blob: 459bcde36ee97c350f2c854a16428efce92a8c9d [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000046 */
Daniel Veillard4255d502002-04-16 15:50:10 +000047#define IN_LIBXML
48#include "libxml.h"
49
50#ifdef LIBXML_SCHEMAS_ENABLED
51
52#include <string.h>
53#include <libxml/xmlmemory.h>
54#include <libxml/parser.h>
55#include <libxml/parserInternals.h>
56#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000057#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000058#include <libxml/xmlschemas.h>
59#include <libxml/schemasInternals.h>
60#include <libxml/xmlschemastypes.h>
61#include <libxml/xmlautomata.h>
62#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000063#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000064#include <libxml/encoding.h>
65#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000066#ifdef LIBXML_PATTERN_ENABLED
67#include <libxml/pattern.h>
68#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000069#ifdef LIBXML_READER_ENABLED
70#include <libxml/xmlreader.h>
71#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000072
Daniel Veillarda84c0b32003-06-02 16:58:46 +000073/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074
Daniel Veillard82bbbd42003-05-11 20:16:09 +000075/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076
Daniel Veillard82bbbd42003-05-11 20:16:09 +000077/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000078
Daniel Veillard118aed72002-09-24 14:13:13 +000079/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000080
Daniel Veillard4255d502002-04-16 15:50:10 +000081/* #define DEBUG_AUTOMATA 1 */
82
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000083/* #define DEBUG_IDC */
84
85/* #define DEBUG_IDC_NODE_TABLE */
86
87#ifdef DEBUG_IDC
88 #ifndef DEBUG_IDC_NODE_TABLE
89 #define DEBUG_IDC_NODE_TABLE
90 #endif
91#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000092
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000093/* #define ENABLE_PARTICLE_RESTRICTION 1 */
94
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000095#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000096
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000097/* #define ENABLE_NAMED_LOCALS */
98
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000099/* #define ENABLE_IDC_NODE_TABLES_TEST */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000100
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000101#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102
103#ifdef LIBXML_READER_ENABLED
104/* #define XML_SCHEMA_READER_ENABLED */
105#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000106
Daniel Veillard4255d502002-04-16 15:50:10 +0000107#define UNBOUNDED (1 << 30)
108#define TODO \
109 xmlGenericError(xmlGenericErrorContext, \
110 "Unimplemented block at %s:%d\n", \
111 __FILE__, __LINE__);
112
William M. Brack2f2a6632004-08-20 23:09:47 +0000113#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000114
Daniel Veillard4255d502002-04-16 15:50:10 +0000115/*
116 * The XML Schemas namespaces
117 */
118static const xmlChar *xmlSchemaNs = (const xmlChar *)
119 "http://www.w3.org/2001/XMLSchema";
120
121static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
122 "http://www.w3.org/2001/XMLSchema-instance";
123
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000124static const xmlChar *xmlNamespaceNs = (const xmlChar *)
125 "http://www.w3.org/2000/xmlns/";
126
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000127/*
128* Come casting macros.
129*/
130#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +0000131#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
132#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000133#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
134#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
135#define WXS_PTC_CAST (xmlSchemaParticlePtr)
136#define WXS_TYPE_CAST (xmlSchemaTypePtr)
137#define WXS_ELEM_CAST (xmlSchemaElementPtr)
138#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
139#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
140#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
141#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
142#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
143#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
144#define WXS_IDC_CAST (xmlSchemaIDCPtr)
145#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
146#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000147
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000148/*
149* Macros to query common properties of components.
150*/
151#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000152
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000153#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
154/*
155* Macros for element declarations.
156*/
157#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000158
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000159#define WXS_SUBST_HEAD(item) (item)->refDecl
160/*
161* Macros for attribute declarations.
162*/
163#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
164/*
165* Macros for attribute uses.
166*/
167#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000168
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000169#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000170
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000171#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
172
173#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
174/*
175* Macros for attribute groups.
176*/
177#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
178#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
179/*
180* Macros for particles.
181*/
182#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
183
184#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
185
186#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
187/*
188* Macros for model groups definitions.
189*/
190#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
191/*
192* Macros for model groups.
193*/
194#define WXS_IS_MODEL_GROUP(i) \
195 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
196 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
197 ((i)->type == XML_SCHEMA_TYPE_ALL))
198
199#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
200/*
201* Macros for schema buckets.
202*/
203#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
204 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
205
206#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
207 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
208
209#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
210
211#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
212/*
213* Macros for complex/simple types.
214*/
215#define WXS_IS_ANYTYPE(i) \
216 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
217 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
218
219#define WXS_IS_COMPLEX(i) \
220 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
221 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_SIMPLE(item) \
224 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
225 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000226 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000227
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000228#define WXS_IS_ANY_SIMPLE_TYPE(i) \
229 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
230 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000232#define WXS_IS_RESTRICTION(t) \
233 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000234
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000235#define WXS_IS_EXTENSION(t) \
236 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
237
238#define WXS_IS_TYPE_NOT_FIXED(i) \
239 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
240 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
241
242#define WXS_IS_TYPE_NOT_FIXED_1(item) \
243 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000244 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000245/*
246* Macros for exclusively for complex types.
247*/
248#define WXS_HAS_COMPLEX_CONTENT(item) \
249 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
250 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000251 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000253#define WXS_HAS_SIMPLE_CONTENT(item) \
254 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000255 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
256
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000257#define WXS_HAS_MIXED_CONTENT(item) \
258 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000259
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000260#define WXS_EMPTIABLE(t) \
261 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000262
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000263#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000265#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000267#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
268/*
269* Macros for exclusively for simple types.
270*/
271#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000273#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000276
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000277#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
278/*
279* Misc parser context macros.
280*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000281#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
282
283#define WXS_HAS_BUCKETS(ctx) \
284( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
285(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
286
287#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
288
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000289#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000290
291#define WXS_SCHEMA(ctx) (ctx)->schema
292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000293#define WXS_ADD_LOCAL(ctx, item) \
294 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000295
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000296#define WXS_ADD_GLOBAL(ctx, item) \
297 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000298
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000299#define WXS_ADD_PENDING(ctx, item) \
300 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
301/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000302* xmlSchemaItemList macros.
303*/
304#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
305/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000306* Misc macros.
307*/
308#define IS_SCHEMA(node, type) \
309 ((node != NULL) && (node->ns != NULL) && \
310 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
311 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000312
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000313#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000314
315/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000316* Since we put the default/fixed values into the dict, we can
317* use pointer comparison for those values.
318* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000319*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000320#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000321
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000322#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000323
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000324#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000325
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000326#define HFAILURE if (res == -1) goto exit_failure;
327
328#define HERROR if (res != 0) goto exit_error;
329
330#define HSTOP(ctx) if ((ctx)->stop) goto exit;
331/*
332* Some flags used for various schema constraints.
333*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000334#define SUBSET_RESTRICTION 1<<0
335#define SUBSET_EXTENSION 1<<1
336#define SUBSET_SUBSTITUTION 1<<2
337#define SUBSET_LIST 1<<3
338#define SUBSET_UNION 1<<4
339
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000340typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
341typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000342
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000343typedef struct _xmlSchemaItemList xmlSchemaItemList;
344typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000345struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000346 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000347 int nbItems; /* used for dynamic addition of schemata */
348 int sizeItems; /* used for dynamic addition of schemata */
349};
350
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000351#define XML_SCHEMA_CTXT_PARSER 1
352#define XML_SCHEMA_CTXT_VALIDATOR 2
353
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000354typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
355typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
356struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000357 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000358};
359
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000360typedef struct _xmlSchemaBucket xmlSchemaBucket;
361typedef xmlSchemaBucket *xmlSchemaBucketPtr;
362
363#define XML_SCHEMA_SCHEMA_MAIN 0
364#define XML_SCHEMA_SCHEMA_IMPORT 1
365#define XML_SCHEMA_SCHEMA_INCLUDE 2
366#define XML_SCHEMA_SCHEMA_REDEFINE 3
367
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000368/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000369 * xmlSchemaSchemaRelation:
370 *
371 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000372 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000373typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
374typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
375struct _xmlSchemaSchemaRelation {
376 xmlSchemaSchemaRelationPtr next;
377 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
378 const xmlChar *importNamespace;
379 xmlSchemaBucketPtr bucket;
380};
381
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000382#define XML_SCHEMA_BUCKET_MARKED 1<<0
383#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
384
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000385struct _xmlSchemaBucket {
386 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000387 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000388 const xmlChar *schemaLocation;
389 const xmlChar *origTargetNamespace;
390 const xmlChar *targetNamespace;
391 xmlDocPtr doc;
392 xmlSchemaSchemaRelationPtr relations;
393 int located;
394 int parsed;
395 int imported;
396 int preserveDoc;
397 xmlSchemaItemListPtr globals; /* Global components. */
398 xmlSchemaItemListPtr locals; /* Local components. */
399};
400
401/**
402 * xmlSchemaImport:
403 * (extends xmlSchemaBucket)
404 *
405 * Reflects a schema. Holds some information
406 * about the schema and its toplevel components. Duplicate
407 * toplevel components are not checked at this level.
408 */
409typedef struct _xmlSchemaImport xmlSchemaImport;
410typedef xmlSchemaImport *xmlSchemaImportPtr;
411struct _xmlSchemaImport {
412 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000413 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000414 const xmlChar *schemaLocation; /* The URI of the schema document. */
415 /* For chameleon includes, @origTargetNamespace will be NULL */
416 const xmlChar *origTargetNamespace;
417 /*
418 * For chameleon includes, @targetNamespace will be the
419 * targetNamespace of the including schema.
420 */
421 const xmlChar *targetNamespace;
422 xmlDocPtr doc; /* The schema node-tree. */
423 /* @relations will hold any included/imported/redefined schemas. */
424 xmlSchemaSchemaRelationPtr relations;
425 int located;
426 int parsed;
427 int imported;
428 int preserveDoc;
429 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000430 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000431 /* The imported schema. */
432 xmlSchemaPtr schema;
433};
434
435/*
436* (extends xmlSchemaBucket)
437*/
438typedef struct _xmlSchemaInclude xmlSchemaInclude;
439typedef xmlSchemaInclude *xmlSchemaIncludePtr;
440struct _xmlSchemaInclude {
441 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000442 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000443 const xmlChar *schemaLocation;
444 const xmlChar *origTargetNamespace;
445 const xmlChar *targetNamespace;
446 xmlDocPtr doc;
447 xmlSchemaSchemaRelationPtr relations;
448 int located;
449 int parsed;
450 int imported;
451 int preserveDoc;
452 xmlSchemaItemListPtr globals; /* Global components. */
453 xmlSchemaItemListPtr locals; /* Local components. */
454
455 /* The owning main or import schema bucket. */
456 xmlSchemaImportPtr ownerImport;
457};
458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000459/**
460 * xmlSchemaBasicItem:
461 *
462 * The abstract base type for schema components.
463 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000464typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
465typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
466struct _xmlSchemaBasicItem {
467 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000468};
469
470/**
471 * xmlSchemaAnnotItem:
472 *
473 * The abstract base type for annotated schema components.
474 * (Extends xmlSchemaBasicItem)
475 */
476typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
477typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
478struct _xmlSchemaAnnotItem {
479 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000480 xmlSchemaAnnotPtr annot;
481};
482
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000483/**
484 * xmlSchemaTreeItem:
485 *
486 * The abstract base type for tree-like structured schema components.
487 * (Extends xmlSchemaAnnotItem)
488 */
489typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
490typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
491struct _xmlSchemaTreeItem {
492 xmlSchemaTypeType type;
493 xmlSchemaAnnotPtr annot;
494 xmlSchemaTreeItemPtr next;
495 xmlSchemaTreeItemPtr children;
496};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000497
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000498
499#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
500/**
501 * xmlSchemaAttributeUsePtr:
502 *
503 * The abstract base type for tree-like structured schema components.
504 * (Extends xmlSchemaTreeItem)
505 */
506typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
507typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
508struct _xmlSchemaAttributeUse {
509 xmlSchemaTypeType type;
510 xmlSchemaAnnotPtr annot;
511 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
512 /*
513 * The attr. decl. OR a QName-ref. to an attr. decl. OR
514 * a QName-ref. to an attribute group definition.
515 */
516 xmlSchemaAttributePtr attrDecl;
517
518 int flags;
519 xmlNodePtr node;
520 int occurs; /* required, optional */
521 const xmlChar * defValue;
522 xmlSchemaValPtr defVal;
523};
524
525/**
526 * xmlSchemaAttributeUseProhibPtr:
527 *
528 * A helper component to reflect attribute prohibitions.
529 * (Extends xmlSchemaBasicItem)
530 */
531typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
532typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
533struct _xmlSchemaAttributeUseProhib {
534 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
535 xmlNodePtr node;
536 const xmlChar *name;
537 const xmlChar *targetNamespace;
538 int isRef;
539};
540
541/**
542 * xmlSchemaRedef:
543 */
544typedef struct _xmlSchemaRedef xmlSchemaRedef;
545typedef xmlSchemaRedef *xmlSchemaRedefPtr;
546struct _xmlSchemaRedef {
547 xmlSchemaRedefPtr next;
548 xmlSchemaBasicItemPtr item; /* The redefining component. */
549 xmlSchemaBasicItemPtr reference; /* The referencing component. */
550 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
551 const xmlChar *refName; /* The name of the to-be-redefined component. */
552 const xmlChar *refTargetNs; /* The target namespace of the
553 to-be-redefined comp. */
554 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
555};
556
557/**
558 * xmlSchemaConstructionCtxt:
559 */
560typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
561typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
562struct _xmlSchemaConstructionCtxt {
563 xmlSchemaPtr mainSchema; /* The main schema. */
564 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
565 xmlDictPtr dict;
566 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
567 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
568 xmlSchemaBucketPtr bucket; /* The current schema bucket */
569 xmlSchemaItemListPtr pending; /* All Components of all schemas that
570 need to be fixed. */
571 xmlHashTablePtr substGroups;
572 xmlSchemaRedefPtr redefs;
573 xmlSchemaRedefPtr lastRedef;
574};
575
576#define XML_SCHEMAS_PARSE_ERROR 1
577#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
578
579struct _xmlSchemaParserCtxt {
580 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000581 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000582 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
583 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Kasimier T. Buchcikdfbc33a2006-01-03 10:51:59 +0000584 int err;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000585 int nberrors;
586 xmlStructuredErrorFunc serror;
587
588 xmlSchemaConstructionCtxtPtr constructor;
589 int ownsConstructor; /* TODO: Move this to parser *flags*. */
590
591 /* xmlSchemaPtr topschema; */
592 /* xmlHashTablePtr namespaces; */
593
594 xmlSchemaPtr schema; /* The main schema in use */
595 int counter;
596
597 const xmlChar *URL;
598 xmlDocPtr doc;
599 int preserve; /* Whether the doc should be freed */
600
601 const char *buffer;
602 int size;
603
604 /*
605 * Used to build complex element content models
606 */
607 xmlAutomataPtr am;
608 xmlAutomataStatePtr start;
609 xmlAutomataStatePtr end;
610 xmlAutomataStatePtr state;
611
612 xmlDictPtr dict; /* dictionnary for interned string names */
613 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
614 int options;
615 xmlSchemaValidCtxtPtr vctxt;
616 int isS4S;
617 int isRedefine;
618 int xsiAssemble;
619 int stop; /* If the parser should stop; i.e. a critical error. */
620 const xmlChar *targetNamespace;
621 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
622
623 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
624 int redefCounter; /* Used for redefinitions. */
625 xmlSchemaItemListPtr attrProhibs;
626};
627
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000628/**
629 * xmlSchemaQNameRef:
630 *
631 * A component reference item (not a schema component)
632 * (Extends xmlSchemaBasicItem)
633 */
634typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
635typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
636struct _xmlSchemaQNameRef {
637 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000638 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000639 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000640 const xmlChar *name;
641 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000642 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000643};
644
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645/**
646 * xmlSchemaParticle:
647 *
648 * A particle component.
649 * (Extends xmlSchemaTreeItem)
650 */
651typedef struct _xmlSchemaParticle xmlSchemaParticle;
652typedef xmlSchemaParticle *xmlSchemaParticlePtr;
653struct _xmlSchemaParticle {
654 xmlSchemaTypeType type;
655 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000656 xmlSchemaTreeItemPtr next; /* next particle */
657 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
658 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
659 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000660 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000661 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662 xmlNodePtr node;
663};
664
665/**
666 * xmlSchemaModelGroup:
667 *
668 * A model group component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
672typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
673struct _xmlSchemaModelGroup {
674 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
675 xmlSchemaAnnotPtr annot;
676 xmlSchemaTreeItemPtr next; /* not used */
677 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
678 xmlNodePtr node;
679};
680
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000681#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000682#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000683/**
684 * xmlSchemaModelGroupDef:
685 *
686 * A model group definition component.
687 * (Extends xmlSchemaTreeItem)
688 */
689typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
690typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
691struct _xmlSchemaModelGroupDef {
692 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
693 xmlSchemaAnnotPtr annot;
694 xmlSchemaTreeItemPtr next; /* not used */
695 xmlSchemaTreeItemPtr children; /* the "model group" */
696 const xmlChar *name;
697 const xmlChar *targetNamespace;
698 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000699 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000700};
701
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000702typedef struct _xmlSchemaIDC xmlSchemaIDC;
703typedef xmlSchemaIDC *xmlSchemaIDCPtr;
704
705/**
706 * xmlSchemaIDCSelect:
707 *
708 * The identity-constraint "field" and "selector" item, holding the
709 * XPath expression.
710 */
711typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
712typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000713struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000714 xmlSchemaIDCSelectPtr next;
715 xmlSchemaIDCPtr idc;
716 int index; /* an index position if significant for IDC key-sequences */
717 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000718 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000719};
720
721/**
722 * xmlSchemaIDC:
723 *
724 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000725 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000726 */
727
728struct _xmlSchemaIDC {
729 xmlSchemaTypeType type;
730 xmlSchemaAnnotPtr annot;
731 xmlSchemaIDCPtr next;
732 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000733 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 const xmlChar *targetNamespace;
735 xmlSchemaIDCSelectPtr selector;
736 xmlSchemaIDCSelectPtr fields;
737 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000738 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000739};
740
741/**
742 * xmlSchemaIDCAug:
743 *
744 * The augmented IDC information used for validation.
745 */
746typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
747typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
748struct _xmlSchemaIDCAug {
749 xmlSchemaIDCAugPtr next; /* next in a list */
750 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000751 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000752 tables need to be bubbled upwards */
753};
754
755/**
756 * xmlSchemaPSVIIDCKeySequence:
757 *
758 * The key sequence of a node table item.
759 */
760typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
761typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
762struct _xmlSchemaPSVIIDCKey {
763 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000764 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000765};
766
767/**
768 * xmlSchemaPSVIIDCNode:
769 *
770 * The node table item of a node table.
771 */
772typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
773typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
774struct _xmlSchemaPSVIIDCNode {
775 xmlNodePtr node;
776 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000777 int nodeLine;
778 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000779
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000780};
781
782/**
783 * xmlSchemaPSVIIDCBinding:
784 *
785 * The identity-constraint binding item of the [identity-constraint table].
786 */
787typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
788typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
789struct _xmlSchemaPSVIIDCBinding {
790 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
791 xmlSchemaIDCPtr definition; /* the IDC definition */
792 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
793 int nbNodes; /* number of entries in the node table */
794 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000795 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000796};
797
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000798
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000799#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
800#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
801
802#define XPATH_STATE_OBJ_MATCHES -2
803#define XPATH_STATE_OBJ_BLOCKED -3
804
805typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
806typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
807
808/**
809 * xmlSchemaIDCStateObj:
810 *
811 * The state object used to evaluate XPath expressions.
812 */
813typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
814typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
815struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000816 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000817 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000818 int depth; /* depth of creation */
819 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000820 int nbHistory;
821 int sizeHistory;
822 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
823 matcher */
824 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000825 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000826};
827
828#define IDC_MATCHER 0
829
830/**
831 * xmlSchemaIDCMatcher:
832 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000833 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000834 */
835struct _xmlSchemaIDCMatcher {
836 int type;
837 int depth; /* the tree depth at creation time */
838 xmlSchemaIDCMatcherPtr next; /* next in the list */
839 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000840 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000841 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
842 elements */
843 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000844 int targetDepth;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000845 xmlSchemaItemListPtr targets; /* list of target-node
846 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000847};
848
849/*
850* Element info flags.
851*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000852#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
853#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
854#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
855#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
856
857#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
858#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
859#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
860
861#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
862#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
863#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
864#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000865
866/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000867 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000868 *
869 * Holds information of an element node.
870 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000871struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000872 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000873 xmlNodePtr node;
874 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000875 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000876 const xmlChar *nsName;
877 const xmlChar *value;
878 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000879 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000880
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000881 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000883 int valNeeded;
884 int normVal;
885
886 xmlSchemaElementPtr decl; /* the element/attribute declaration */
887 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000888 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
889 for the scope element*/
890 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
891 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000892 xmlRegExecCtxtPtr regexCtxt;
893
894 const xmlChar **nsBindings; /* Namespace bindings on this element */
895 int nbNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000896 int sizeNsBindings;
897
898 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000899 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000900};
901
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000902#define XML_SCHEMAS_ATTR_UNKNOWN 1
903#define XML_SCHEMAS_ATTR_ASSESSED 2
904#define XML_SCHEMAS_ATTR_PROHIBITED 3
905#define XML_SCHEMAS_ATTR_ERR_MISSING 4
906#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
907#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
908#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
909#define XML_SCHEMAS_ATTR_DEFAULT 8
910#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
911#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
912#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
913#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
914#define XML_SCHEMAS_ATTR_WILD_SKIP 13
915#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
916#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
917#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
918#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000919/*
920* @metaType values of xmlSchemaAttrInfo.
921*/
922#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
923#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
924#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
926#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000928typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
929typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
930struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000931 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000932 xmlNodePtr node;
933 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000934 const xmlChar *localName;
935 const xmlChar *nsName;
936 const xmlChar *value;
937 xmlSchemaValPtr val; /* the pre-computed value if any */
938 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
939 int flags; /* combination of node info flags */
940
941 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000942 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000943 int state;
944 int metaType;
945 const xmlChar *vcValue; /* the value constraint value */
946 xmlSchemaNodeInfoPtr parent;
947};
948
949
950#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000951/**
952 * xmlSchemaValidCtxt:
953 *
954 * A Schemas validation context
955 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000956struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000957 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000958 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000959 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000960 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000961 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000962
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000963 xmlSchemaPtr schema; /* The schema in use */
964 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000965 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000966 xmlCharEncoding enc;
967 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000968 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000969 void *user_data; /* TODO: What is this for? */
Daniel Veillard4255d502002-04-16 15:50:10 +0000970
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000971 int err;
972 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000973
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000974 xmlNodePtr node;
975 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000976 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000977
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000978 xmlRegExecCtxtPtr regexp;
979 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000980
Daniel Veillardc0826a72004-08-10 14:17:33 +0000981 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000982 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000983 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000984 xmlSchemaParserCtxtPtr pctxt;
985 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000986
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000987 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000988 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000989 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000990 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000991
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000992 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
993
994 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
995 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000996
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000997 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
998 int nbIdcNodes;
999 int sizeIdcNodes;
1000
1001 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1002 int nbIdcKeys;
1003 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001004
1005 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001006
1007 xmlDictPtr dict;
1008
Daniel Veillard39e5c892005-07-03 22:48:50 +00001009#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001010 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001011#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001012
1013 xmlSchemaAttrInfoPtr *attrInfos;
1014 int nbAttrInfos;
1015 int sizeAttrInfos;
1016
1017 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001018 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001019 int hasKeyrefs;
1020 int createIDCNodeTables;
1021 int psviExposeIDCNodeTables;
Daniel Veillard4255d502002-04-16 15:50:10 +00001022};
1023
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001024/**
1025 * xmlSchemaSubstGroup:
1026 *
1027 *
1028 */
1029typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1030typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1031struct _xmlSchemaSubstGroup {
1032 xmlSchemaElementPtr head;
1033 xmlSchemaItemListPtr members;
1034};
1035
Daniel Veillard4255d502002-04-16 15:50:10 +00001036/************************************************************************
1037 * *
1038 * Some predeclarations *
1039 * *
1040 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001041
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001042static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1043 xmlSchemaPtr schema,
1044 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001045static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1046 xmlSchemaPtr schema,
1047 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001048static int
1049xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001050 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001051static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001052xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1053static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001054xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1055 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001056static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001057xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1058 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001059static void
1060xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001061static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001062xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001063static xmlSchemaTreeItemPtr
1064xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1065 xmlNodePtr node, xmlSchemaTypeType type,
1066 int withParticle);
1067static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001068xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001069static xmlSchemaTypeLinkPtr
1070xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001071static void
1072xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1073 const char *funcName,
1074 const char *message);
1075static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001076xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001077 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001078 xmlSchemaTypePtr baseType,
1079 int subset);
1080static void
1081xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001082 xmlSchemaParserCtxtPtr ctxt);
1083static void
1084xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001085static xmlSchemaQNameRefPtr
1086xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1087 xmlSchemaPtr schema,
1088 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001090/************************************************************************
1091 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001092 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001093 * *
1094 ************************************************************************/
1095
1096/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001097 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001098 * @type: the type of the schema item
1099 *
1100 * Returns the component name of a schema item.
1101 */
1102static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001103xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001104{
1105 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001106 case XML_SCHEMA_TYPE_BASIC:
1107 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001108 case XML_SCHEMA_TYPE_SIMPLE:
1109 return(BAD_CAST "simple type definition");
1110 case XML_SCHEMA_TYPE_COMPLEX:
1111 return(BAD_CAST "complex type definition");
1112 case XML_SCHEMA_TYPE_ELEMENT:
1113 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001114 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1115 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001116 case XML_SCHEMA_TYPE_ATTRIBUTE:
1117 return(BAD_CAST "attribute declaration");
1118 case XML_SCHEMA_TYPE_GROUP:
1119 return(BAD_CAST "model group definition");
1120 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1121 return(BAD_CAST "attribute group definition");
1122 case XML_SCHEMA_TYPE_NOTATION:
1123 return(BAD_CAST "notation declaration");
1124 case XML_SCHEMA_TYPE_SEQUENCE:
1125 return(BAD_CAST "model group (sequence)");
1126 case XML_SCHEMA_TYPE_CHOICE:
1127 return(BAD_CAST "model group (choice)");
1128 case XML_SCHEMA_TYPE_ALL:
1129 return(BAD_CAST "model group (all)");
1130 case XML_SCHEMA_TYPE_PARTICLE:
1131 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001132 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001133 return(BAD_CAST "unique identity-constraint");
1134 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001135 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001136 return(BAD_CAST "key identity-constraint");
1137 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001138 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001139 return(BAD_CAST "keyref identity-constraint");
1140 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001141 case XML_SCHEMA_TYPE_ANY:
1142 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001143 case XML_SCHEMA_EXTRA_QNAMEREF:
1144 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001145 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1146 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001147 default:
1148 return(BAD_CAST "Not a schema component");
1149 }
1150}
1151
1152/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001153 * xmlSchemaGetComponentTypeStr:
1154 * @type: the type of the schema item
1155 *
1156 * Returns the component name of a schema item.
1157 */
1158static const xmlChar *
1159xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1160{
1161 switch (item->type) {
1162 case XML_SCHEMA_TYPE_BASIC:
1163 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1164 return(BAD_CAST "complex type definition");
1165 else
1166 return(BAD_CAST "simple type definition");
1167 default:
1168 return(xmlSchemaItemTypeToStr(item->type));
1169 }
1170}
1171
1172/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001173 * xmlSchemaGetComponentNode:
1174 * @item: a schema component
1175 *
1176 * Returns node associated with the schema component.
1177 * NOTE that such a node need not be available; plus, a component's
1178 * node need not to reflect the component directly, since there is no
1179 * one-to-one relationship between the XML Schema representation and
1180 * the component representation.
1181 */
1182static xmlNodePtr
1183xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1184{
1185 switch (item->type) {
1186 case XML_SCHEMA_TYPE_ELEMENT:
1187 return (((xmlSchemaElementPtr) item)->node);
1188 case XML_SCHEMA_TYPE_ATTRIBUTE:
1189 return (((xmlSchemaAttributePtr) item)->node);
1190 case XML_SCHEMA_TYPE_COMPLEX:
1191 case XML_SCHEMA_TYPE_SIMPLE:
1192 return (((xmlSchemaTypePtr) item)->node);
1193 case XML_SCHEMA_TYPE_ANY:
1194 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1195 return (((xmlSchemaWildcardPtr) item)->node);
1196 case XML_SCHEMA_TYPE_PARTICLE:
1197 return (((xmlSchemaParticlePtr) item)->node);
1198 case XML_SCHEMA_TYPE_SEQUENCE:
1199 case XML_SCHEMA_TYPE_CHOICE:
1200 case XML_SCHEMA_TYPE_ALL:
1201 return (((xmlSchemaModelGroupPtr) item)->node);
1202 case XML_SCHEMA_TYPE_GROUP:
1203 return (((xmlSchemaModelGroupDefPtr) item)->node);
1204 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1205 return (((xmlSchemaAttributeGroupPtr) item)->node);
1206 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1207 case XML_SCHEMA_TYPE_IDC_KEY:
1208 case XML_SCHEMA_TYPE_IDC_KEYREF:
1209 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001210 case XML_SCHEMA_EXTRA_QNAMEREF:
1211 return(((xmlSchemaQNameRefPtr) item)->node);
1212 /* TODO: What to do with NOTATIONs?
1213 case XML_SCHEMA_TYPE_NOTATION:
1214 return (((xmlSchemaNotationPtr) item)->node);
1215 */
1216 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1217 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001218 default:
1219 return (NULL);
1220 }
1221}
1222
1223#if 0
1224/**
1225 * xmlSchemaGetNextComponent:
1226 * @item: a schema component
1227 *
1228 * Returns the next sibling of the schema component.
1229 */
1230static xmlSchemaBasicItemPtr
1231xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1232{
1233 switch (item->type) {
1234 case XML_SCHEMA_TYPE_ELEMENT:
1235 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1236 case XML_SCHEMA_TYPE_ATTRIBUTE:
1237 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1238 case XML_SCHEMA_TYPE_COMPLEX:
1239 case XML_SCHEMA_TYPE_SIMPLE:
1240 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1241 case XML_SCHEMA_TYPE_ANY:
1242 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1243 return (NULL);
1244 case XML_SCHEMA_TYPE_PARTICLE:
1245 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1246 case XML_SCHEMA_TYPE_SEQUENCE:
1247 case XML_SCHEMA_TYPE_CHOICE:
1248 case XML_SCHEMA_TYPE_ALL:
1249 return (NULL);
1250 case XML_SCHEMA_TYPE_GROUP:
1251 return (NULL);
1252 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1253 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1254 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1255 case XML_SCHEMA_TYPE_IDC_KEY:
1256 case XML_SCHEMA_TYPE_IDC_KEYREF:
1257 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1258 default:
1259 return (NULL);
1260 }
1261}
1262#endif
1263
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001264
1265/**
1266 * xmlSchemaFormatQName:
1267 * @buf: the string buffer
1268 * @namespaceName: the namespace name
1269 * @localName: the local name
1270 *
1271 * Returns the given QName in the format "{namespaceName}localName" or
1272 * just "localName" if @namespaceName is NULL.
1273 *
1274 * Returns the localName if @namespaceName is NULL, a formatted
1275 * string otherwise.
1276 */
1277static const xmlChar*
1278xmlSchemaFormatQName(xmlChar **buf,
1279 const xmlChar *namespaceName,
1280 const xmlChar *localName)
1281{
1282 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001283 if (namespaceName != NULL) {
1284 *buf = xmlStrdup(BAD_CAST "{");
1285 *buf = xmlStrcat(*buf, namespaceName);
1286 *buf = xmlStrcat(*buf, BAD_CAST "}");
1287 }
1288 if (localName != NULL) {
1289 if (namespaceName == NULL)
1290 return(localName);
1291 *buf = xmlStrcat(*buf, localName);
1292 } else {
1293 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001295 return ((const xmlChar *) *buf);
1296}
1297
1298static const xmlChar*
1299xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1300{
1301 if (ns != NULL)
1302 return (xmlSchemaFormatQName(buf, ns->href, localName));
1303 else
1304 return (xmlSchemaFormatQName(buf, NULL, localName));
1305}
1306
1307static const xmlChar *
1308xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1309{
1310 switch (item->type) {
1311 case XML_SCHEMA_TYPE_ELEMENT:
1312 return (((xmlSchemaElementPtr) item)->name);
1313 case XML_SCHEMA_TYPE_ATTRIBUTE:
1314 return (((xmlSchemaAttributePtr) item)->name);
1315 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1316 return (((xmlSchemaAttributeGroupPtr) item)->name);
1317 case XML_SCHEMA_TYPE_BASIC:
1318 case XML_SCHEMA_TYPE_SIMPLE:
1319 case XML_SCHEMA_TYPE_COMPLEX:
1320 return (((xmlSchemaTypePtr) item)->name);
1321 case XML_SCHEMA_TYPE_GROUP:
1322 return (((xmlSchemaModelGroupDefPtr) item)->name);
1323 case XML_SCHEMA_TYPE_IDC_KEY:
1324 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1325 case XML_SCHEMA_TYPE_IDC_KEYREF:
1326 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001327 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1328 if (WXS_ATTRUSE_DECL(item) != NULL) {
1329 return(xmlSchemaGetComponentName(
1330 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1331 } else
1332 return(NULL);
1333 case XML_SCHEMA_EXTRA_QNAMEREF:
1334 return (((xmlSchemaQNameRefPtr) item)->name);
1335 case XML_SCHEMA_TYPE_NOTATION:
1336 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001337 default:
1338 /*
1339 * Other components cannot have names.
1340 */
1341 break;
1342 }
1343 return (NULL);
1344}
1345
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001346#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1347#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1348/*
1349static const xmlChar *
1350xmlSchemaGetQNameRefName(void *ref)
1351{
1352 return(((xmlSchemaQNameRefPtr) ref)->name);
1353}
1354
1355static const xmlChar *
1356xmlSchemaGetQNameRefTargetNs(void *ref)
1357{
1358 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1359}
1360*/
1361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001362static const xmlChar *
1363xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1364{
1365 switch (item->type) {
1366 case XML_SCHEMA_TYPE_ELEMENT:
1367 return (((xmlSchemaElementPtr) item)->targetNamespace);
1368 case XML_SCHEMA_TYPE_ATTRIBUTE:
1369 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1370 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1371 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1372 case XML_SCHEMA_TYPE_BASIC:
1373 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1374 case XML_SCHEMA_TYPE_SIMPLE:
1375 case XML_SCHEMA_TYPE_COMPLEX:
1376 return (((xmlSchemaTypePtr) item)->targetNamespace);
1377 case XML_SCHEMA_TYPE_GROUP:
1378 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1379 case XML_SCHEMA_TYPE_IDC_KEY:
1380 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1381 case XML_SCHEMA_TYPE_IDC_KEYREF:
1382 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001383 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1384 if (WXS_ATTRUSE_DECL(item) != NULL) {
1385 return(xmlSchemaGetComponentTargetNs(
1386 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1387 }
1388 /* TODO: Will returning NULL break something? */
1389 break;
1390 case XML_SCHEMA_EXTRA_QNAMEREF:
1391 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1392 case XML_SCHEMA_TYPE_NOTATION:
1393 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001394 default:
1395 /*
1396 * Other components cannot have names.
1397 */
1398 break;
1399 }
1400 return (NULL);
1401}
1402
1403static const xmlChar*
1404xmlSchemaGetComponentQName(xmlChar **buf,
1405 void *item)
1406{
1407 return (xmlSchemaFormatQName(buf,
1408 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1409 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1410}
1411
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001412static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001413xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001414{
1415 xmlChar *str = NULL;
1416
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001417 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001418 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001419 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1420 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001421 *buf = xmlStrcat(*buf, BAD_CAST "'");
1422 FREE_AND_NULL(str);
1423 return(*buf);
1424}
1425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001426static const xmlChar*
1427xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1428{
1429 return(xmlSchemaGetComponentDesignation(buf, idc));
1430}
1431
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001432/**
1433 * xmlSchemaWildcardPCToString:
1434 * @pc: the type of processContents
1435 *
1436 * Returns a string representation of the type of
1437 * processContents.
1438 */
1439static const xmlChar *
1440xmlSchemaWildcardPCToString(int pc)
1441{
1442 switch (pc) {
1443 case XML_SCHEMAS_ANY_SKIP:
1444 return (BAD_CAST "skip");
1445 case XML_SCHEMAS_ANY_LAX:
1446 return (BAD_CAST "lax");
1447 case XML_SCHEMAS_ANY_STRICT:
1448 return (BAD_CAST "strict");
1449 default:
1450 return (BAD_CAST "invalid process contents");
1451 }
1452}
1453
1454/**
1455 * xmlSchemaGetCanonValueWhtspExt:
1456 * @val: the precomputed value
1457 * @retValue: the returned value
1458 * @ws: the whitespace type of the value
1459 *
1460 * Get a the cononical representation of the value.
1461 * The caller has to free the returned retValue.
1462 *
1463 * Returns 0 if the value could be built and -1 in case of
1464 * API errors or if the value type is not supported yet.
1465 */
1466static int
1467xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1468 xmlSchemaWhitespaceValueType ws,
1469 xmlChar **retValue)
1470{
1471 int list;
1472 xmlSchemaValType valType;
1473 const xmlChar *value, *value2 = NULL;
1474
1475
1476 if ((retValue == NULL) || (val == NULL))
1477 return (-1);
1478 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1479 *retValue = NULL;
1480 do {
1481 value = NULL;
1482 valType = xmlSchemaGetValType(val);
1483 switch (valType) {
1484 case XML_SCHEMAS_STRING:
1485 case XML_SCHEMAS_NORMSTRING:
1486 case XML_SCHEMAS_ANYSIMPLETYPE:
1487 value = xmlSchemaValueGetAsString(val);
1488 if (value != NULL) {
1489 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1490 value2 = xmlSchemaCollapseString(value);
1491 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1492 value2 = xmlSchemaWhiteSpaceReplace(value);
1493 if (value2 != NULL)
1494 value = value2;
1495 }
1496 break;
1497 default:
1498 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1499 if (value2 != NULL)
1500 xmlFree((xmlChar *) value2);
1501 goto internal_error;
1502 }
1503 value = value2;
1504 }
1505 if (*retValue == NULL)
1506 if (value == NULL) {
1507 if (! list)
1508 *retValue = xmlStrdup(BAD_CAST "");
1509 } else
1510 *retValue = xmlStrdup(value);
1511 else if (value != NULL) {
1512 /* List. */
1513 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1514 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1515 }
1516 FREE_AND_NULL(value2)
1517 val = xmlSchemaValueGetNext(val);
1518 } while (val != NULL);
1519
1520 return (0);
1521internal_error:
1522 if (*retValue != NULL)
1523 xmlFree((xmlChar *) (*retValue));
1524 if (value2 != NULL)
1525 xmlFree((xmlChar *) value2);
1526 return (-1);
1527}
1528
1529/**
1530 * xmlSchemaFormatItemForReport:
1531 * @buf: the string buffer
1532 * @itemDes: the designation of the item
1533 * @itemName: the name of the item
1534 * @item: the item as an object
1535 * @itemNode: the node of the item
1536 * @local: the local name
1537 * @parsing: if the function is used during the parse
1538 *
1539 * Returns a representation of the given item used
1540 * for error reports.
1541 *
1542 * The following order is used to build the resulting
1543 * designation if the arguments are not NULL:
1544 * 1a. If itemDes not NULL -> itemDes
1545 * 1b. If (itemDes not NULL) and (itemName not NULL)
1546 * -> itemDes + itemName
1547 * 2. If the preceding was NULL and (item not NULL) -> item
1548 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1549 *
1550 * If the itemNode is an attribute node, the name of the attribute
1551 * will be appended to the result.
1552 *
1553 * Returns the formatted string and sets @buf to the resulting value.
1554 */
1555static xmlChar*
1556xmlSchemaFormatItemForReport(xmlChar **buf,
1557 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001558 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559 xmlNodePtr itemNode)
1560{
1561 xmlChar *str = NULL;
1562 int named = 1;
1563
1564 if (*buf != NULL) {
1565 xmlFree(*buf);
1566 *buf = NULL;
1567 }
1568
1569 if (itemDes != NULL) {
1570 *buf = xmlStrdup(itemDes);
1571 } else if (item != NULL) {
1572 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001573 case XML_SCHEMA_TYPE_BASIC: {
1574 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1575
1576 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001577 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001578 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1582 else
1583 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001584 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001585 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001587 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001588 case XML_SCHEMA_TYPE_SIMPLE: {
1589 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1590
1591 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001592 *buf = xmlStrdup(BAD_CAST"");
1593 } else {
1594 *buf = xmlStrdup(BAD_CAST "local ");
1595 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001596 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001597 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1602 else
1603 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001604 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001605 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001606 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607 *buf = xmlStrcat(*buf, BAD_CAST "'");
1608 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001610 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001611 case XML_SCHEMA_TYPE_COMPLEX: {
1612 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1613
1614 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615 *buf = xmlStrdup(BAD_CAST "");
1616 else
1617 *buf = xmlStrdup(BAD_CAST "local ");
1618 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001619 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001620 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001621 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001622 *buf = xmlStrcat(*buf, BAD_CAST "'");
1623 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001624 }
1625 break;
1626 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1627 xmlSchemaAttributeUsePtr ause;
1628
1629 ause = WXS_ATTR_USE_CAST item;
1630 *buf = xmlStrdup(BAD_CAST "attribute use ");
1631 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1632 *buf = xmlStrcat(*buf, BAD_CAST "'");
1633 *buf = xmlStrcat(*buf,
1634 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1635 FREE_AND_NULL(str)
1636 *buf = xmlStrcat(*buf, BAD_CAST "'");
1637 } else {
1638 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1639 }
1640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001641 break;
1642 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1643 xmlSchemaAttributePtr attr;
1644
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001645 attr = (xmlSchemaAttributePtr) item;
1646 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1647 *buf = xmlStrcat(*buf, BAD_CAST " '");
1648 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1649 attr->targetNamespace, attr->name));
1650 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001652 }
1653 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001654 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1655 xmlSchemaGetComponentDesignation(buf, item);
1656 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001657 case XML_SCHEMA_TYPE_ELEMENT: {
1658 xmlSchemaElementPtr elem;
1659
1660 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001661 *buf = xmlStrdup(BAD_CAST "element decl.");
1662 *buf = xmlStrcat(*buf, BAD_CAST " '");
1663 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1664 elem->targetNamespace, elem->name));
1665 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001666 }
1667 break;
1668 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1669 case XML_SCHEMA_TYPE_IDC_KEY:
1670 case XML_SCHEMA_TYPE_IDC_KEYREF:
1671 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1672 *buf = xmlStrdup(BAD_CAST "unique '");
1673 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1674 *buf = xmlStrdup(BAD_CAST "key '");
1675 else
1676 *buf = xmlStrdup(BAD_CAST "keyRef '");
1677 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1678 *buf = xmlStrcat(*buf, BAD_CAST "'");
1679 break;
1680 case XML_SCHEMA_TYPE_ANY:
1681 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1682 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1683 ((xmlSchemaWildcardPtr) item)->processContents));
1684 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1685 break;
1686 case XML_SCHEMA_FACET_MININCLUSIVE:
1687 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1688 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1689 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1690 case XML_SCHEMA_FACET_TOTALDIGITS:
1691 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1692 case XML_SCHEMA_FACET_PATTERN:
1693 case XML_SCHEMA_FACET_ENUMERATION:
1694 case XML_SCHEMA_FACET_WHITESPACE:
1695 case XML_SCHEMA_FACET_LENGTH:
1696 case XML_SCHEMA_FACET_MAXLENGTH:
1697 case XML_SCHEMA_FACET_MINLENGTH:
1698 *buf = xmlStrdup(BAD_CAST "facet '");
1699 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1700 *buf = xmlStrcat(*buf, BAD_CAST "'");
1701 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001703 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001704 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001705 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 *buf = xmlStrcat(*buf, BAD_CAST "'");
1707 FREE_AND_NULL(str)
1708 }
1709 break;
1710 case XML_SCHEMA_TYPE_SEQUENCE:
1711 case XML_SCHEMA_TYPE_CHOICE:
1712 case XML_SCHEMA_TYPE_ALL:
1713 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001714 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1715 break;
1716 case XML_SCHEMA_TYPE_NOTATION: {
1717 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1718 *buf = xmlStrcat(*buf, BAD_CAST " '");
1719 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720 *buf = xmlStrcat(*buf, BAD_CAST "'");
1721 FREE_AND_NULL(str);
1722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001723 default:
1724 named = 0;
1725 }
1726 } else
1727 named = 0;
1728
1729 if ((named == 0) && (itemNode != NULL)) {
1730 xmlNodePtr elem;
1731
1732 if (itemNode->type == XML_ATTRIBUTE_NODE)
1733 elem = itemNode->parent;
1734 else
1735 elem = itemNode;
1736 *buf = xmlStrdup(BAD_CAST "Element '");
1737 if (elem->ns != NULL) {
1738 *buf = xmlStrcat(*buf,
1739 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1740 FREE_AND_NULL(str)
1741 } else
1742 *buf = xmlStrcat(*buf, elem->name);
1743 *buf = xmlStrcat(*buf, BAD_CAST "'");
1744
1745 }
1746 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1747 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1748 if (itemNode->ns != NULL) {
1749 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1750 itemNode->ns->href, itemNode->name));
1751 FREE_AND_NULL(str)
1752 } else
1753 *buf = xmlStrcat(*buf, itemNode->name);
1754 *buf = xmlStrcat(*buf, BAD_CAST "'");
1755 }
1756 FREE_AND_NULL(str)
1757
1758 return (*buf);
1759}
1760
1761/**
1762 * xmlSchemaFormatFacetEnumSet:
1763 * @buf: the string buffer
1764 * @type: the type holding the enumeration facets
1765 *
1766 * Builds a string consisting of all enumeration elements.
1767 *
1768 * Returns a string of all enumeration elements.
1769 */
1770static const xmlChar *
1771xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1772 xmlChar **buf, xmlSchemaTypePtr type)
1773{
1774 xmlSchemaFacetPtr facet;
1775 xmlSchemaWhitespaceValueType ws;
1776 xmlChar *value = NULL;
1777 int res;
1778
1779 if (*buf != NULL)
1780 xmlFree(*buf);
1781 *buf = NULL;
1782
1783 do {
1784 /*
1785 * Use the whitespace type of the base type.
1786 */
1787 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1788 for (facet = type->facets; facet != NULL; facet = facet->next) {
1789 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1790 continue;
1791 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1792 ws, &value);
1793 if (res == -1) {
1794 xmlSchemaInternalErr(actxt,
1795 "xmlSchemaFormatFacetEnumSet",
1796 "compute the canonical lexical representation");
1797 if (*buf != NULL)
1798 xmlFree(*buf);
1799 *buf = NULL;
1800 return (NULL);
1801 }
1802 if (*buf == NULL)
1803 *buf = xmlStrdup(BAD_CAST "'");
1804 else
1805 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1806 *buf = xmlStrcat(*buf, BAD_CAST value);
1807 *buf = xmlStrcat(*buf, BAD_CAST "'");
1808 if (value != NULL) {
1809 xmlFree((xmlChar *)value);
1810 value = NULL;
1811 }
1812 }
1813 type = type->baseType;
1814 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1815
1816 return ((const xmlChar *) *buf);
1817}
1818
1819/************************************************************************
1820 * *
1821 * Error functions *
1822 * *
1823 ************************************************************************/
1824
1825#if 0
1826static void
1827xmlSchemaErrMemory(const char *msg)
1828{
1829 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1830 msg);
1831}
1832#endif
1833
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001834static void
1835xmlSchemaPSimpleErr(const char *msg)
1836{
1837 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1838 msg);
1839}
1840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001841/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001842 * xmlSchemaPErrMemory:
1843 * @node: a context node
1844 * @extra: extra informations
1845 *
1846 * Handle an out of memory condition
1847 */
1848static void
1849xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1850 const char *extra, xmlNodePtr node)
1851{
1852 if (ctxt != NULL)
1853 ctxt->nberrors++;
1854 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1855 extra);
1856}
1857
1858/**
1859 * xmlSchemaPErr:
1860 * @ctxt: the parsing context
1861 * @node: the context node
1862 * @error: the error code
1863 * @msg: the error message
1864 * @str1: extra data
1865 * @str2: extra data
1866 *
1867 * Handle a parser error
1868 */
1869static void
1870xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1871 const char *msg, const xmlChar * str1, const xmlChar * str2)
1872{
1873 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001874 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001875 void *data = NULL;
1876
1877 if (ctxt != NULL) {
1878 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001879 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001881 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001882 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001883 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001884 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001885 error, XML_ERR_ERROR, NULL, 0,
1886 (const char *) str1, (const char *) str2, NULL, 0, 0,
1887 msg, str1, str2);
1888}
1889
1890/**
1891 * xmlSchemaPErr2:
1892 * @ctxt: the parsing context
1893 * @node: the context node
1894 * @node: the current child
1895 * @error: the error code
1896 * @msg: the error message
1897 * @str1: extra data
1898 * @str2: extra data
1899 *
1900 * Handle a parser error
1901 */
1902static void
1903xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1904 xmlNodePtr child, int error,
1905 const char *msg, const xmlChar * str1, const xmlChar * str2)
1906{
1907 if (child != NULL)
1908 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1909 else
1910 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1911}
1912
Daniel Veillard01fa6152004-06-29 17:04:39 +00001913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001915 * xmlSchemaPErrExt:
1916 * @ctxt: the parsing context
1917 * @node: the context node
1918 * @error: the error code
1919 * @strData1: extra data
1920 * @strData2: extra data
1921 * @strData3: extra data
1922 * @msg: the message
1923 * @str1: extra parameter for the message display
1924 * @str2: extra parameter for the message display
1925 * @str3: extra parameter for the message display
1926 * @str4: extra parameter for the message display
1927 * @str5: extra parameter for the message display
1928 *
1929 * Handle a parser error
1930 */
1931static void
1932xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1933 const xmlChar * strData1, const xmlChar * strData2,
1934 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1935 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1936 const xmlChar * str5)
1937{
1938
1939 xmlGenericErrorFunc channel = NULL;
1940 xmlStructuredErrorFunc schannel = NULL;
1941 void *data = NULL;
1942
1943 if (ctxt != NULL) {
1944 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001945 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001946 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001947 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001948 schannel = ctxt->serror;
1949 }
1950 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1951 error, XML_ERR_ERROR, NULL, 0,
1952 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001953 (const char *) strData3, 0, 0, msg, str1, str2,
1954 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001955}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001956
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001957/************************************************************************
1958 * *
1959 * Allround error functions *
1960 * *
1961 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001962
1963/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964 * xmlSchemaVTypeErrMemory:
1965 * @node: a context node
1966 * @extra: extra informations
1967 *
1968 * Handle an out of memory condition
1969 */
1970static void
1971xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1972 const char *extra, xmlNodePtr node)
1973{
1974 if (ctxt != NULL) {
1975 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001976 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001977 }
1978 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1979 extra);
1980}
1981
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001982static void
1983xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1984 const char *msg, const xmlChar *str)
1985{
1986 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1987 msg, (const char *) str);
1988}
1989
1990#define WXS_ERROR_TYPE_ERROR 1
1991#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001992/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001993 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994 * @ctxt: the validation context
1995 * @node: the context node
1996 * @error: the error code
1997 * @msg: the error message
1998 * @str1: extra data
1999 * @str2: extra data
2000 * @str3: extra data
2001 *
2002 * Handle a validation error
2003 */
2004static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002005xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002006 xmlErrorLevel errorLevel,
2007 int error, xmlNodePtr node, int line, const char *msg,
2008 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002009 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002010{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002011 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002013 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002014
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002015 if (ctxt != NULL) {
2016 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2017 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002018 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002019 if (errorLevel != XML_ERR_WARNING) {
2020 vctxt->nberrors++;
2021 vctxt->err = error;
2022 channel = vctxt->error;
2023 } else {
2024 channel = vctxt->warning;
2025 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002026 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002027 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002028
2029 /*
2030 * Error node. If we specify a line number, then
2031 * do not channel any node to the error function.
2032 */
2033 if (line == 0) {
2034 if ((node == NULL) &&
2035 (vctxt->depth >= 0) &&
2036 (vctxt->inode != NULL)) {
2037 node = vctxt->inode->node;
2038 }
2039 /*
2040 * Get filename and line if no node-tree.
2041 */
2042 if ((node == NULL) &&
2043 (vctxt->parserCtxt != NULL) &&
2044 (vctxt->parserCtxt->input != NULL)) {
2045 file = vctxt->parserCtxt->input->filename;
2046 line = vctxt->parserCtxt->input->line;
2047 }
2048 } else {
2049 /*
2050 * Override the given node's (if any) position
2051 * and channel only the given line number.
2052 */
2053 node = NULL;
2054 /*
2055 * Get filename.
2056 */
2057 if (vctxt->doc != NULL)
2058 file = (const char *) vctxt->doc->URL;
2059 else if ((vctxt->parserCtxt != NULL) &&
2060 (vctxt->parserCtxt->input != NULL))
2061 file = vctxt->parserCtxt->input->filename;
2062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002063 __xmlRaiseError(schannel, channel, data, ctxt,
2064 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002065 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002066 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002067 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002068
2069 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2070 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002071 if (errorLevel != XML_ERR_WARNING) {
2072 pctxt->nberrors++;
2073 pctxt->err = error;
2074 channel = pctxt->error;
2075 } else {
2076 channel = pctxt->warning;
2077 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002078 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002079 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002080 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002081 node, XML_FROM_SCHEMASP, error,
2082 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002083 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002084 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002085 } else {
2086 TODO
2087 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002088 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002089}
2090
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002091/**
2092 * xmlSchemaErr3:
2093 * @ctxt: the validation context
2094 * @node: the context node
2095 * @error: the error code
2096 * @msg: the error message
2097 * @str1: extra data
2098 * @str2: extra data
2099 * @str3: extra data
2100 *
2101 * Handle a validation error
2102 */
2103static void
2104xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2105 int error, xmlNodePtr node, const char *msg,
2106 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2107{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002108 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2109 msg, str1, str2, str3, NULL);
2110}
2111
2112static void
2113xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2114 int error, xmlNodePtr node, const char *msg,
2115 const xmlChar *str1, const xmlChar *str2,
2116 const xmlChar *str3, const xmlChar *str4)
2117{
2118 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2119 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002120}
2121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002122static void
2123xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2124 int error, xmlNodePtr node, const char *msg,
2125 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002126{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002127 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002128}
2129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130static xmlChar *
2131xmlSchemaFormatNodeForError(xmlChar ** msg,
2132 xmlSchemaAbstractCtxtPtr actxt,
2133 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134{
2135 xmlChar *str = NULL;
2136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002137 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002138 if ((node != NULL) &&
2139 (node->type != XML_ELEMENT_NODE) &&
2140 (node->type != XML_ATTRIBUTE_NODE))
2141 {
2142 /*
2143 * Don't try to format other nodes than element and
2144 * attribute nodes.
2145 * Play save and return an empty string.
2146 */
2147 *msg = xmlStrdup(BAD_CAST "");
2148 return(*msg);
2149 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 if (node != NULL) {
2151 /*
2152 * Work on tree nodes.
2153 */
2154 if (node->type == XML_ATTRIBUTE_NODE) {
2155 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 *msg = xmlStrdup(BAD_CAST "Element '");
2158 if (elem->ns != NULL)
2159 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2160 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002161 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2163 NULL, elem->name));
2164 FREE_AND_NULL(str);
2165 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2166 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2167 } else {
2168 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002170 if (node->ns != NULL)
2171 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2172 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2175 NULL, node->name));
2176 FREE_AND_NULL(str);
2177 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2178 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2179 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2180 /*
2181 * Work on node infos.
2182 */
2183 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2184 xmlSchemaNodeInfoPtr ielem =
2185 vctxt->elemInfos[vctxt->depth];
2186
2187 *msg = xmlStrdup(BAD_CAST "Element '");
2188 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2189 ielem->nsName, ielem->localName));
2190 FREE_AND_NULL(str);
2191 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2192 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2193 } else {
2194 *msg = xmlStrdup(BAD_CAST "Element '");
2195 }
2196 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2197 vctxt->inode->nsName, vctxt->inode->localName));
2198 FREE_AND_NULL(str);
2199 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002200 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2201 /*
2202 * Hmm, no node while parsing?
2203 * Return an empty string, in case NULL will break something.
2204 */
2205 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002206 } else {
2207 TODO
2208 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 /*
2211 * VAL TODO: The output of the given schema component is currently
2212 * disabled.
2213 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002214#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002215 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2216 *msg = xmlStrcat(*msg, BAD_CAST " [");
2217 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2218 NULL, type, NULL, 0));
2219 FREE_AND_NULL(str)
2220 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002222#endif
2223 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002224}
2225
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002227xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002229 const char *message,
2230 const xmlChar *str1,
2231 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002233 xmlChar *msg = NULL;
2234
2235 msg = xmlStrdup(BAD_CAST "Internal error: ");
2236 msg = xmlStrcat(msg, BAD_CAST funcName);
2237 msg = xmlStrcat(msg, BAD_CAST ", ");
2238 msg = xmlStrcat(msg, BAD_CAST message);
2239 msg = xmlStrcat(msg, BAD_CAST ".\n");
2240
2241 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2242 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002243 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002244
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002245 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002247 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248
2249 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250}
2251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002253xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2254 const char *funcName,
2255 const char *message)
2256{
2257 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2258}
2259
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002260#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002261static void
2262xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2263 const char *funcName,
2264 const char *message,
2265 const xmlChar *str1,
2266 const xmlChar *str2)
2267{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002268 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002269 str1, str2);
2270}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002271#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002272
2273static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002274xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2275 xmlParserErrors error,
2276 xmlNodePtr node,
2277 xmlSchemaBasicItemPtr item,
2278 const char *message,
2279 const xmlChar *str1, const xmlChar *str2,
2280 const xmlChar *str3, const xmlChar *str4)
2281{
2282 xmlChar *msg = NULL;
2283
2284 if ((node == NULL) && (item != NULL) &&
2285 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2286 node = WXS_ITEM_NODE(item);
2287 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2288 msg = xmlStrcat(msg, BAD_CAST ": ");
2289 } else
2290 xmlSchemaFormatNodeForError(&msg, actxt, node);
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 xmlSchemaErr4(actxt, error, node,
2294 (const char *) msg, str1, str2, str3, str4);
2295 FREE_AND_NULL(msg)
2296}
2297
2298static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2300 xmlParserErrors error,
2301 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002302 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002303 const char *message,
2304 const xmlChar *str1,
2305 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002306{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002307 xmlSchemaCustomErr4(actxt, error, node, item,
2308 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002309}
2310
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002311
2312
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002313static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002314xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2315 xmlParserErrors error,
2316 xmlNodePtr node,
2317 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2318 const char *message,
2319 const xmlChar *str1,
2320 const xmlChar *str2,
2321 const xmlChar *str3)
2322{
2323 xmlChar *msg = NULL;
2324
2325 xmlSchemaFormatNodeForError(&msg, actxt, node);
2326 msg = xmlStrcat(msg, (const xmlChar *) message);
2327 msg = xmlStrcat(msg, BAD_CAST ".\n");
2328
2329 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002330 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2331 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002332
2333 FREE_AND_NULL(msg)
2334}
2335
2336
2337
2338static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002339xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2340 xmlParserErrors error,
2341 xmlSchemaPSVIIDCNodePtr idcNode,
2342 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2343 const char *message,
2344 const xmlChar *str1,
2345 const xmlChar *str2)
2346{
2347 xmlChar *msg = NULL, *qname = NULL;
2348
2349 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2350 msg = xmlStrcat(msg, (const xmlChar *) message);
2351 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002352 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002353 error, NULL, idcNode->nodeLine, (const char *) msg,
2354 xmlSchemaFormatQName(&qname,
2355 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2356 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002357 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002358 FREE_AND_NULL(qname);
2359 FREE_AND_NULL(msg);
2360}
2361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002362static int
2363xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2364 xmlNodePtr node)
2365{
2366 if (node != NULL)
2367 return (node->type);
2368 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2369 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2370 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2371 return (-1);
2372}
2373
2374static int
2375xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2376{
2377 switch (item->type) {
2378 case XML_SCHEMA_TYPE_COMPLEX:
2379 case XML_SCHEMA_TYPE_SIMPLE:
2380 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2381 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002382 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002383 case XML_SCHEMA_TYPE_GROUP:
2384 return (1);
2385 case XML_SCHEMA_TYPE_ELEMENT:
2386 if ( ((xmlSchemaElementPtr) item)->flags &
2387 XML_SCHEMAS_ELEM_GLOBAL)
2388 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002389 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002390 case XML_SCHEMA_TYPE_ATTRIBUTE:
2391 if ( ((xmlSchemaAttributePtr) item)->flags &
2392 XML_SCHEMAS_ATTR_GLOBAL)
2393 return(1);
2394 break;
2395 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002396 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002397 return(1);
2398 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002399 return (0);
2400}
2401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002402static void
2403xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2404 xmlParserErrors error,
2405 xmlNodePtr node,
2406 const xmlChar *value,
2407 xmlSchemaTypePtr type,
2408 int displayValue)
2409{
2410 xmlChar *msg = NULL;
2411
2412 xmlSchemaFormatNodeForError(&msg, actxt, node);
2413
2414 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2415 XML_ATTRIBUTE_NODE))
2416 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2417 else
2418 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2419 "value of ");
2420
2421 if (! xmlSchemaIsGlobalItem(type))
2422 msg = xmlStrcat(msg, BAD_CAST "the local ");
2423 else
2424 msg = xmlStrcat(msg, BAD_CAST "the ");
2425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002426 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002427 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002428 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002430 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 msg = xmlStrcat(msg, BAD_CAST "union type");
2432
2433 if (xmlSchemaIsGlobalItem(type)) {
2434 xmlChar *str = NULL;
2435 msg = xmlStrcat(msg, BAD_CAST " '");
2436 if (type->builtInType != 0) {
2437 msg = xmlStrcat(msg, BAD_CAST "xs:");
2438 msg = xmlStrcat(msg, type->name);
2439 } else
2440 msg = xmlStrcat(msg,
2441 xmlSchemaFormatQName(&str,
2442 type->targetNamespace, type->name));
2443 msg = xmlStrcat(msg, BAD_CAST "'");
2444 FREE_AND_NULL(str);
2445 }
2446 msg = xmlStrcat(msg, BAD_CAST ".\n");
2447 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2448 XML_ATTRIBUTE_NODE))
2449 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2450 else
2451 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2452 FREE_AND_NULL(msg)
2453}
2454
Daniel Veillardc0826a72004-08-10 14:17:33 +00002455static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2457 xmlSchemaNodeInfoPtr ni,
2458 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 if (node != NULL) {
2461 if (node->ns != NULL)
2462 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2463 else
2464 return (xmlSchemaFormatQName(str, NULL, node->name));
2465 } else if (ni != NULL)
2466 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2467 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468}
2469
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002471xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2472 xmlParserErrors error,
2473 xmlSchemaAttrInfoPtr ni,
2474 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476 xmlChar *msg = NULL, *str = NULL;
2477
2478 xmlSchemaFormatNodeForError(&msg, actxt, node);
2479 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2480 xmlSchemaErr(actxt, error, node, (const char *) msg,
2481 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2482 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002483 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485}
2486
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2489 xmlParserErrors error,
2490 xmlNodePtr node,
2491 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002492 const char *message,
2493 int nbval,
2494 int nbneg,
2495 xmlChar **values)
2496{
2497 xmlChar *str = NULL, *msg = NULL;
2498 xmlChar *localName, *nsName;
2499 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002500 int i;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002502 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 /*
2506 * Note that is does not make sense to report that we have a
2507 * wildcard here, since the wildcard might be unfolded into
2508 * multiple transitions.
2509 */
2510 if (nbval + nbneg > 0) {
2511 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002512 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002513 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002515 nsName = NULL;
2516
2517 for (i = 0; i < nbval + nbneg; i++) {
2518 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002519 if (cur == NULL)
2520 continue;
2521 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2522 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002523 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002524 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002525 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002526 /*
2527 * Get the local name.
2528 */
2529 localName = NULL;
2530
2531 end = cur;
2532 if (*end == '*') {
2533 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002534 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002535 } else {
2536 while ((*end != 0) && (*end != '|'))
2537 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002538 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002539 }
2540 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002541 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002542 /*
2543 * Skip "*|*" if they come with negated expressions, since
2544 * they represent the same negated wildcard.
2545 */
2546 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2547 /*
2548 * Get the namespace name.
2549 */
2550 cur = end;
2551 if (*end == '*') {
2552 nsName = xmlStrdup(BAD_CAST "{*}");
2553 } else {
2554 while (*end != 0)
2555 end++;
2556
2557 if (i >= nbval)
2558 nsName = xmlStrdup(BAD_CAST "{##other:");
2559 else
2560 nsName = xmlStrdup(BAD_CAST "{");
2561
2562 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2563 nsName = xmlStrcat(nsName, BAD_CAST "}");
2564 }
2565 str = xmlStrcat(str, BAD_CAST nsName);
2566 FREE_AND_NULL(nsName)
2567 } else {
2568 FREE_AND_NULL(localName);
2569 continue;
2570 }
2571 }
2572 str = xmlStrcat(str, BAD_CAST localName);
2573 FREE_AND_NULL(localName);
2574
2575 if (i < nbval + nbneg -1)
2576 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002579 msg = xmlStrcat(msg, BAD_CAST str);
2580 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 } else
2582 msg = xmlStrcat(msg, BAD_CAST "\n");
2583 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002584 xmlFree(msg);
2585}
2586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587static void
2588xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2589 xmlParserErrors error,
2590 xmlNodePtr node,
2591 const xmlChar *value,
2592 unsigned long length,
2593 xmlSchemaTypePtr type,
2594 xmlSchemaFacetPtr facet,
2595 const char *message,
2596 const xmlChar *str1,
2597 const xmlChar *str2)
2598{
2599 xmlChar *str = NULL, *msg = NULL;
2600 xmlSchemaTypeType facetType;
2601 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2602
2603 xmlSchemaFormatNodeForError(&msg, actxt, node);
2604 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2605 facetType = XML_SCHEMA_FACET_ENUMERATION;
2606 /*
2607 * If enumerations are validated, one must not expect the
2608 * facet to be given.
2609 */
2610 } else
2611 facetType = facet->type;
2612 msg = xmlStrcat(msg, BAD_CAST "[");
2613 msg = xmlStrcat(msg, BAD_CAST "facet '");
2614 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2615 msg = xmlStrcat(msg, BAD_CAST "'] ");
2616 if (message == NULL) {
2617 /*
2618 * Use a default message.
2619 */
2620 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2621 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2622 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2623
2624 char len[25], actLen[25];
2625
2626 /* FIXME, TODO: What is the max expected string length of the
2627 * this value?
2628 */
2629 if (nodeType == XML_ATTRIBUTE_NODE)
2630 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2631 else
2632 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2633
2634 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2635 snprintf(actLen, 24, "%lu", length);
2636
2637 if (facetType == XML_SCHEMA_FACET_LENGTH)
2638 msg = xmlStrcat(msg,
2639 BAD_CAST "this differs from the allowed length of '%s'.\n");
2640 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2641 msg = xmlStrcat(msg,
2642 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2643 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2644 msg = xmlStrcat(msg,
2645 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2646
2647 if (nodeType == XML_ATTRIBUTE_NODE)
2648 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2649 value, (const xmlChar *) actLen, (const xmlChar *) len);
2650 else
2651 xmlSchemaErr(actxt, error, node, (const char *) msg,
2652 (const xmlChar *) actLen, (const xmlChar *) len);
2653
2654 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2655 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2656 "of the set {%s}.\n");
2657 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2658 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2659 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2660 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2661 "by the pattern '%s'.\n");
2662 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2663 facet->value);
2664 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2665 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2666 "minimum value allowed ('%s').\n");
2667 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2668 facet->value);
2669 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2670 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2671 "maximum value allowed ('%s').\n");
2672 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2673 facet->value);
2674 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002675 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002676 "'%s'.\n");
2677 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 facet->value);
2679 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002681 "'%s'.\n");
2682 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 facet->value);
2684 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2685 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2686 "digits than are allowed ('%s').\n");
2687 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2688 facet->value);
2689 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2690 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2691 "digits than are allowed ('%s').\n");
2692 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2693 facet->value);
2694 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2695 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2696 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2697 } else {
2698 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2699 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2700 }
2701 } else {
2702 msg = xmlStrcat(msg, (const xmlChar *) message);
2703 msg = xmlStrcat(msg, BAD_CAST ".\n");
2704 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2705 }
2706 FREE_AND_NULL(str)
2707 xmlFree(msg);
2708}
2709
2710#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002711 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002712
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002713#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002715#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2716#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
2718#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2719
2720
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002721/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002722 * xmlSchemaPMissingAttrErr:
2723 * @ctxt: the schema validation context
2724 * @ownerDes: the designation of the owner
2725 * @ownerName: the name of the owner
2726 * @ownerItem: the owner as a schema object
2727 * @ownerElem: the owner as an element node
2728 * @node: the parent element node of the missing attribute node
2729 * @type: the corresponding type of the attribute node
2730 *
2731 * Reports an illegal attribute.
2732 */
2733static void
2734xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002735 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002736 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002737 xmlNodePtr ownerElem,
2738 const char *name,
2739 const char *message)
2740{
2741 xmlChar *des = NULL;
2742
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002743 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2744
Daniel Veillardc0826a72004-08-10 14:17:33 +00002745 if (message != NULL)
2746 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002747 else
2748 xmlSchemaPErr(ctxt, ownerElem, error,
2749 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002750 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002752}
2753
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002754
Daniel Veillardc0826a72004-08-10 14:17:33 +00002755/**
2756 * xmlSchemaPResCompAttrErr:
2757 * @ctxt: the schema validation context
2758 * @error: the error code
2759 * @ownerDes: the designation of the owner
2760 * @ownerItem: the owner as a schema object
2761 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002762 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002763 * @refName: the referenced local name
2764 * @refURI: the referenced namespace URI
2765 * @message: optional message
2766 *
2767 * Used to report QName attribute values that failed to resolve
2768 * to schema components.
2769 */
2770static void
2771xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002772 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002773 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002774 xmlNodePtr ownerElem,
2775 const char *name,
2776 const xmlChar *refName,
2777 const xmlChar *refURI,
2778 xmlSchemaTypeType refType,
2779 const char *refTypeStr)
2780{
2781 xmlChar *des = NULL, *strA = NULL;
2782
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002784 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002785 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002786 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002787 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2789 "%s.\n", BAD_CAST des, BAD_CAST name,
2790 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002791 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002792 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793 FREE_AND_NULL(strA)
2794}
2795
William M. Brack2f2a6632004-08-20 23:09:47 +00002796/**
2797 * xmlSchemaPCustomAttrErr:
2798 * @ctxt: the schema parser context
2799 * @error: the error code
2800 * @ownerDes: the designation of the owner
2801 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002802 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002803 *
2804 * Reports an illegal attribute during the parse.
2805 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002806static void
2807xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002808 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002809 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002810 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002811 xmlAttrPtr attr,
2812 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002813{
2814 xmlChar *des = NULL;
2815
2816 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002817 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002819 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002820 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002821 } else
2822 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002823 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2826 if (ownerDes == NULL)
2827 FREE_AND_NULL(des);
2828}
2829
2830/**
2831 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002832 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002833 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002834 * @ownerDes: the designation of the attribute's owner
2835 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002837 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002838 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839 */
2840static void
2841xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002842 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002843 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002844 xmlAttrPtr attr)
2845{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002846 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002848 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2849 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2850 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2851 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2852 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002853 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002854 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855}
2856
William M. Brack2f2a6632004-08-20 23:09:47 +00002857/**
2858 * xmlSchemaPCustomErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @itemDes: the designation of the schema item
2862 * @item: the schema item
2863 * @itemElem: the node of the schema item
2864 * @message: the error message
2865 * @str1: an optional param for the error message
2866 * @str2: an optional param for the error message
2867 * @str3: an optional param for the error message
2868 *
2869 * Reports an error during parsing.
2870 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002871static void
2872xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002873 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002874 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002875 xmlNodePtr itemElem,
2876 const char *message,
2877 const xmlChar *str1,
2878 const xmlChar *str2,
2879 const xmlChar *str3)
2880{
2881 xmlChar *des = NULL, *msg = NULL;
2882
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002883 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002884 msg = xmlStrdup(BAD_CAST "%s: ");
2885 msg = xmlStrcat(msg, (const xmlChar *) message);
2886 msg = xmlStrcat(msg, BAD_CAST ".\n");
2887 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002888 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002889 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002890 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002891 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002892 FREE_AND_NULL(msg);
2893}
2894
William M. Brack2f2a6632004-08-20 23:09:47 +00002895/**
2896 * xmlSchemaPCustomErr:
2897 * @ctxt: the schema parser context
2898 * @error: the error code
2899 * @itemDes: the designation of the schema item
2900 * @item: the schema item
2901 * @itemElem: the node of the schema item
2902 * @message: the error message
2903 * @str1: the optional param for the error message
2904 *
2905 * Reports an error during parsing.
2906 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002907static void
2908xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002909 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002910 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002911 xmlNodePtr itemElem,
2912 const char *message,
2913 const xmlChar *str1)
2914{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002915 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002916 str1, NULL, NULL);
2917}
2918
William M. Brack2f2a6632004-08-20 23:09:47 +00002919/**
2920 * xmlSchemaPAttrUseErr:
2921 * @ctxt: the schema parser context
2922 * @error: the error code
2923 * @itemDes: the designation of the schema type
2924 * @item: the schema type
2925 * @itemElem: the node of the schema type
2926 * @attr: the invalid schema attribute
2927 * @message: the error message
2928 * @str1: the optional param for the error message
2929 *
2930 * Reports an attribute use error during parsing.
2931 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002933xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002934 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002935 xmlNodePtr node,
2936 xmlSchemaBasicItemPtr ownerItem,
2937 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002938 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 const xmlChar *str1, const xmlChar *str2,
2940 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002941{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002942 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002943
2944 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2945 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002946 msg = xmlStrcat(msg,
2947 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002949 FREE_AND_NULL(str);
2950 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002951 msg = xmlStrcat(msg, (const xmlChar *) message);
2952 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2954 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002955 xmlFree(msg);
2956}
2957
William M. Brack2f2a6632004-08-20 23:09:47 +00002958/**
2959 * xmlSchemaPIllegalFacetAtomicErr:
2960 * @ctxt: the schema parser context
2961 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002962 * @type: the schema type
2963 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002964 * @facet: the illegal facet
2965 *
2966 * Reports an illegal facet for atomic simple types.
2967 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968static void
2969xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002971 xmlSchemaTypePtr type,
2972 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002973 xmlSchemaFacetPtr facet)
2974{
2975 xmlChar *des = NULL, *strT = NULL;
2976
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002977 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2978 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002979 "%s: The facet '%s' is not allowed on types derived from the "
2980 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002981 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002982 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002983 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002984 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002985 FREE_AND_NULL(strT);
2986}
2987
William M. Brack2f2a6632004-08-20 23:09:47 +00002988/**
2989 * xmlSchemaPIllegalFacetListUnionErr:
2990 * @ctxt: the schema parser context
2991 * @error: the error code
2992 * @itemDes: the designation of the schema item involved
2993 * @item: the schema item involved
2994 * @facet: the illegal facet
2995 *
2996 * Reports an illegal facet for <list> and <union>.
2997 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998static void
2999xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003000 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003001 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003002 xmlSchemaFacetPtr facet)
3003{
3004 xmlChar *des = NULL, *strT = NULL;
3005
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003006 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3007 type->node);
3008 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003009 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003010 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003011 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003012 FREE_AND_NULL(strT);
3013}
3014
3015/**
3016 * xmlSchemaPMutualExclAttrErr:
3017 * @ctxt: the schema validation context
3018 * @error: the error code
3019 * @elemDes: the designation of the parent element node
3020 * @attr: the bad attribute node
3021 * @type: the corresponding type of the attribute node
3022 *
3023 * Reports an illegal attribute.
3024 */
3025static void
3026xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3027 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003028 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003029 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003030 const char *name1,
3031 const char *name2)
3032{
3033 xmlChar *des = NULL;
3034
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003035 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003036 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003037 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003039 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003040}
3041
3042/**
3043 * xmlSchemaPSimpleTypeErr:
3044 * @ctxt: the schema validation context
3045 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003046 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003047 * @ownerDes: the designation of the owner
3048 * @ownerItem: the schema object if existent
3049 * @node: the validated node
3050 * @value: the validated value
3051 *
3052 * Reports a simple type validation error.
3053 * TODO: Should this report the value of an element as well?
3054 */
3055static void
3056xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3057 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003058 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003060 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003061 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003062 const xmlChar *value,
3063 const char *message,
3064 const xmlChar *str1,
3065 const xmlChar *str2)
3066{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003069 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070 if (message == NULL) {
3071 /*
3072 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003073 */
3074 if (type != NULL) {
3075 if (node->type == XML_ATTRIBUTE_NODE)
3076 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3077 else
3078 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3079 "valid value of ");
3080 if (! xmlSchemaIsGlobalItem(type))
3081 msg = xmlStrcat(msg, BAD_CAST "the local ");
3082 else
3083 msg = xmlStrcat(msg, BAD_CAST "the ");
3084
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003085 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003086 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003087 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003088 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003089 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003090 msg = xmlStrcat(msg, BAD_CAST "union type");
3091
3092 if (xmlSchemaIsGlobalItem(type)) {
3093 xmlChar *str = NULL;
3094 msg = xmlStrcat(msg, BAD_CAST " '");
3095 if (type->builtInType != 0) {
3096 msg = xmlStrcat(msg, BAD_CAST "xs:");
3097 msg = xmlStrcat(msg, type->name);
3098 } else
3099 msg = xmlStrcat(msg,
3100 xmlSchemaFormatQName(&str,
3101 type->targetNamespace, type->name));
3102 msg = xmlStrcat(msg, BAD_CAST "'.");
3103 FREE_AND_NULL(str);
3104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003105 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003106 if (node->type == XML_ATTRIBUTE_NODE)
3107 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3108 else
3109 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3110 "valid.");
3111 }
3112 if (expected) {
3113 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3114 msg = xmlStrcat(msg, BAD_CAST expected);
3115 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3116 } else
3117 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003118 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003119 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3120 else
3121 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3122 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003123 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003124 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003126 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003127 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 /* Cleanup. */
3129 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003130}
3131
William M. Brack2f2a6632004-08-20 23:09:47 +00003132/**
3133 * xmlSchemaPContentErr:
3134 * @ctxt: the schema parser context
3135 * @error: the error code
3136 * @onwerDes: the designation of the holder of the content
3137 * @ownerItem: the owner item of the holder of the content
3138 * @ownerElem: the node of the holder of the content
3139 * @child: the invalid child node
3140 * @message: the optional error message
3141 * @content: the optional string describing the correct content
3142 *
3143 * Reports an error concerning the content of a schema element.
3144 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003145static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003147 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003148 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003149 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003150 xmlNodePtr child,
3151 const char *message,
3152 const char *content)
3153{
3154 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003156 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003157 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003158 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3159 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003160 BAD_CAST des, BAD_CAST message);
3161 else {
3162 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3164 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 BAD_CAST des, BAD_CAST content);
3166 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003167 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3168 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003169 BAD_CAST des, NULL);
3170 }
3171 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003172 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003173}
3174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003175/************************************************************************
3176 * *
3177 * Streamable error functions *
3178 * *
3179 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003180
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003181
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003182
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003183
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003184/************************************************************************
3185 * *
3186 * Validation helper functions *
3187 * *
3188 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003189
Daniel Veillardc0826a72004-08-10 14:17:33 +00003190
Daniel Veillard4255d502002-04-16 15:50:10 +00003191/************************************************************************
3192 * *
3193 * Allocation functions *
3194 * *
3195 ************************************************************************/
3196
3197/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003198 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003199 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 *
3201 * Allocate a new Schema structure.
3202 *
3203 * Returns the newly allocated structure or NULL in case or error
3204 */
3205static xmlSchemaPtr
3206xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3207{
3208 xmlSchemaPtr ret;
3209
3210 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3211 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 return (NULL);
3214 }
3215 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003217 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218
3219 return (ret);
3220}
3221
3222/**
3223 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 *
3225 * Allocate a new Facet structure.
3226 *
3227 * Returns the newly allocated structure or NULL in case or error
3228 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003229xmlSchemaFacetPtr
3230xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003231{
3232 xmlSchemaFacetPtr ret;
3233
3234 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3235 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 return (NULL);
3237 }
3238 memset(ret, 0, sizeof(xmlSchemaFacet));
3239
3240 return (ret);
3241}
3242
3243/**
3244 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003245 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003246 * @node: a node
3247 *
3248 * Allocate a new annotation structure.
3249 *
3250 * Returns the newly allocated structure or NULL in case or error
3251 */
3252static xmlSchemaAnnotPtr
3253xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3254{
3255 xmlSchemaAnnotPtr ret;
3256
3257 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3258 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 return (NULL);
3261 }
3262 memset(ret, 0, sizeof(xmlSchemaAnnot));
3263 ret->content = node;
3264 return (ret);
3265}
3266
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003267static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003268xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003269{
3270 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003271
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003272 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3273 if (ret == NULL) {
3274 xmlSchemaPErrMemory(NULL,
3275 "allocating an item list structure", NULL);
3276 return (NULL);
3277 }
3278 memset(ret, 0, sizeof(xmlSchemaItemList));
3279 return (ret);
3280}
3281
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003282static void
3283xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3284{
3285 if (list->items != NULL) {
3286 xmlFree(list->items);
3287 list->items = NULL;
3288 }
3289 list->nbItems = 0;
3290 list->sizeItems = 0;
3291}
3292
3293static int
3294xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3295{
3296 if (list->items == NULL) {
3297 list->items = (void **) xmlMalloc(
3298 20 * sizeof(void *));
3299 if (list->items == NULL) {
3300 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3301 return(-1);
3302 }
3303 list->sizeItems = 20;
3304 } else if (list->sizeItems <= list->nbItems) {
3305 list->sizeItems *= 2;
3306 list->items = (void **) xmlRealloc(list->items,
3307 list->sizeItems * sizeof(void *));
3308 if (list->items == NULL) {
3309 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3310 list->sizeItems = 0;
3311 return(-1);
3312 }
3313 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003314 list->items[list->nbItems++] = item;
3315 return(0);
3316}
3317
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003318static int
3319xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3320 int initialSize,
3321 void *item)
3322{
3323 if (list->items == NULL) {
3324 if (initialSize <= 0)
3325 initialSize = 1;
3326 list->items = (void **) xmlMalloc(
3327 initialSize * sizeof(void *));
3328 if (list->items == NULL) {
3329 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3330 return(-1);
3331 }
3332 list->sizeItems = initialSize;
3333 } else if (list->sizeItems <= list->nbItems) {
3334 list->sizeItems *= 2;
3335 list->items = (void **) xmlRealloc(list->items,
3336 list->sizeItems * sizeof(void *));
3337 if (list->items == NULL) {
3338 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3339 list->sizeItems = 0;
3340 return(-1);
3341 }
3342 }
3343 list->items[list->nbItems++] = item;
3344 return(0);
3345}
3346
3347static int
3348xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3349{
3350 if (list->items == NULL) {
3351 list->items = (void **) xmlMalloc(
3352 20 * sizeof(void *));
3353 if (list->items == NULL) {
3354 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3355 return(-1);
3356 }
3357 list->sizeItems = 20;
3358 } else if (list->sizeItems <= list->nbItems) {
3359 list->sizeItems *= 2;
3360 list->items = (void **) xmlRealloc(list->items,
3361 list->sizeItems * sizeof(void *));
3362 if (list->items == NULL) {
3363 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3364 list->sizeItems = 0;
3365 return(-1);
3366 }
3367 }
3368 /*
3369 * Just append if the index is greater/equal than the item count.
3370 */
3371 if (idx >= list->nbItems) {
3372 list->items[list->nbItems++] = item;
3373 } else {
3374 int i;
3375 for (i = list->nbItems; i > idx; i--)
3376 list->items[i] = list->items[i-1];
3377 list->items[idx] = item;
3378 list->nbItems++;
3379 }
3380 return(0);
3381}
3382
3383#if 0 /* enable if ever needed */
3384static int
3385xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3386 int initialSize,
3387 void *item,
3388 int idx)
3389{
3390 if (list->items == NULL) {
3391 if (initialSize <= 0)
3392 initialSize = 1;
3393 list->items = (void **) xmlMalloc(
3394 initialSize * sizeof(void *));
3395 if (list->items == NULL) {
3396 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3397 return(-1);
3398 }
3399 list->sizeItems = initialSize;
3400 } else if (list->sizeItems <= list->nbItems) {
3401 list->sizeItems *= 2;
3402 list->items = (void **) xmlRealloc(list->items,
3403 list->sizeItems * sizeof(void *));
3404 if (list->items == NULL) {
3405 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3406 list->sizeItems = 0;
3407 return(-1);
3408 }
3409 }
3410 /*
3411 * Just append if the index is greater/equal than the item count.
3412 */
3413 if (idx >= list->nbItems) {
3414 list->items[list->nbItems++] = item;
3415 } else {
3416 int i;
3417 for (i = list->nbItems; i > idx; i--)
3418 list->items[i] = list->items[i-1];
3419 list->items[idx] = item;
3420 list->nbItems++;
3421 }
3422 return(0);
3423}
3424#endif
3425
3426static int
3427xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3428{
3429 int i;
3430 if ((list->items == NULL) || (idx >= list->nbItems)) {
3431 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3432 "index error.\n");
3433 return(-1);
3434 }
3435
3436 if (list->nbItems == 1) {
3437 /* TODO: Really free the list? */
3438 xmlFree(list->items);
3439 list->items = NULL;
3440 list->nbItems = 0;
3441 list->sizeItems = 0;
3442 } else if (list->nbItems -1 == idx) {
3443 list->nbItems--;
3444 } else {
3445 for (i = idx; i < list->nbItems -1; i++)
3446 list->items[i] = list->items[i+1];
3447 list->nbItems--;
3448 }
3449 return(0);
3450}
3451
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003452/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003453 * xmlSchemaItemListFree:
3454 * @annot: a schema type structure
3455 *
3456 * Deallocate a annotation structure
3457 */
3458static void
3459xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3460{
3461 if (list == NULL)
3462 return;
3463 if (list->items != NULL)
3464 xmlFree(list->items);
3465 xmlFree(list);
3466}
3467
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003468static void
3469xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003470{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003471 if (bucket == NULL)
3472 return;
3473 if (bucket->globals != NULL) {
3474 xmlSchemaComponentListFree(bucket->globals);
3475 xmlSchemaItemListFree(bucket->globals);
3476 }
3477 if (bucket->locals != NULL) {
3478 xmlSchemaComponentListFree(bucket->locals);
3479 xmlSchemaItemListFree(bucket->locals);
3480 }
3481 if (bucket->relations != NULL) {
3482 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3483 do {
3484 prev = cur;
3485 cur = cur->next;
3486 xmlFree(prev);
3487 } while (cur != NULL);
3488 }
3489 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3490 xmlFreeDoc(bucket->doc);
3491 }
3492 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003493 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3494 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003495 }
3496 xmlFree(bucket);
3497}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003498
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003499static xmlSchemaBucketPtr
3500xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003501 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003502{
3503 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504 int size;
3505 xmlSchemaPtr mainSchema;
3506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003507 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003508 PERROR_INT("xmlSchemaBucketCreate",
3509 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003510 return(NULL);
3511 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003512 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003513 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003514 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003515 size = sizeof(xmlSchemaInclude);
3516 else
3517 size = sizeof(xmlSchemaImport);
3518 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3519 if (ret == NULL) {
3520 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3521 return(NULL);
3522 }
3523 memset(ret, 0, size);
3524 ret->targetNamespace = targetNamespace;
3525 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003526 ret->globals = xmlSchemaItemListCreate();
3527 if (ret->globals == NULL) {
3528 xmlFree(ret);
3529 return(NULL);
3530 }
3531 ret->locals = xmlSchemaItemListCreate();
3532 if (ret->locals == NULL) {
3533 xmlFree(ret);
3534 return(NULL);
3535 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003536 /*
3537 * The following will assure that only the first bucket is marked as
3538 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3539 * For each following import buckets an xmlSchema will be created.
3540 */
3541 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003542 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003543 PERROR_INT("xmlSchemaBucketCreate",
3544 "first bucket but it's an include or redefine");
3545 xmlSchemaBucketFree(ret);
3546 return(NULL);
3547 }
3548 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3549 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3550 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003551 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3552 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003553 } else {
3554 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3555 PERROR_INT("xmlSchemaBucketCreate",
3556 "main bucket but it's not the first one");
3557 xmlSchemaBucketFree(ret);
3558 return(NULL);
3559 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3560 /*
3561 * Create a schema for imports.
3562 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003563 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3564 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003565 xmlSchemaBucketFree(ret);
3566 return(NULL);
3567 }
3568 }
3569 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003570 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003571 int res;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003572 /* Imports go into the "schemasImports" slot of the main *schema*. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003573 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003574 mainSchema->schemasImports = xmlHashCreateDict(5,
3575 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576 if (mainSchema->schemasImports == NULL) {
3577 xmlSchemaBucketFree(ret);
3578 return(NULL);
3579 }
3580 }
3581 if (targetNamespace == NULL)
3582 res = xmlHashAddEntry(mainSchema->schemasImports,
3583 XML_SCHEMAS_NO_NAMESPACE, ret);
3584 else
3585 res = xmlHashAddEntry(mainSchema->schemasImports,
3586 targetNamespace, ret);
3587 if (res != 0) {
3588 PERROR_INT("xmlSchemaBucketCreate",
3589 "failed to add the schema bucket to the hash");
3590 xmlSchemaBucketFree(ret);
3591 return(NULL);
3592 }
3593 } else {
3594 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003595 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3596 WXS_INCBUCKET(ret)->ownerImport =
3597 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003598 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003599 WXS_INCBUCKET(ret)->ownerImport =
3600 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003601
3602 /* Includes got into the "includes" slot of the *main* schema. */
3603 if (mainSchema->includes == NULL) {
3604 mainSchema->includes = xmlSchemaItemListCreate();
3605 if (mainSchema->includes == NULL) {
3606 xmlSchemaBucketFree(ret);
3607 return(NULL);
3608 }
3609 }
3610 xmlSchemaItemListAdd(mainSchema->includes, ret);
3611 }
3612 /*
3613 * Add to list of all buckets; this is used for lookup
3614 * during schema construction time only.
3615 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003616 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003617 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003618 return(ret);
3619}
3620
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003621static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003622xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003623{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003624 if (*list == NULL) {
3625 *list = xmlSchemaItemListCreate();
3626 if (*list == NULL)
3627 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003628 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003629 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003630 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003631}
3632
3633/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003634 * xmlSchemaFreeAnnot:
3635 * @annot: a schema type structure
3636 *
3637 * Deallocate a annotation structure
3638 */
3639static void
3640xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3641{
3642 if (annot == NULL)
3643 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003644 if (annot->next == NULL) {
3645 xmlFree(annot);
3646 } else {
3647 xmlSchemaAnnotPtr prev;
3648
3649 do {
3650 prev = annot;
3651 annot = annot->next;
3652 xmlFree(prev);
3653 } while (annot != NULL);
3654 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003655}
3656
3657/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003658 * xmlSchemaFreeNotation:
3659 * @schema: a schema notation structure
3660 *
3661 * Deallocate a Schema Notation structure.
3662 */
3663static void
3664xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3665{
3666 if (nota == NULL)
3667 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003668 xmlFree(nota);
3669}
3670
3671/**
3672 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003673 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003675 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 */
3677static void
3678xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3679{
3680 if (attr == NULL)
3681 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003682 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003683 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003684 if (attr->defVal != NULL)
3685 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 xmlFree(attr);
3687}
3688
3689/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003690 * xmlSchemaFreeAttributeUse:
3691 * @use: an attribute use
3692 *
3693 * Deallocates an attribute use structure.
3694 */
3695static void
3696xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3697{
3698 if (use == NULL)
3699 return;
3700 if (use->annot != NULL)
3701 xmlSchemaFreeAnnot(use->annot);
3702 if (use->defVal != NULL)
3703 xmlSchemaFreeValue(use->defVal);
3704 xmlFree(use);
3705}
3706
3707/**
3708 * xmlSchemaFreeAttributeUseProhib:
3709 * @prohib: an attribute use prohibition
3710 *
3711 * Deallocates an attribute use structure.
3712 */
3713static void
3714xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3715{
3716 if (prohib == NULL)
3717 return;
3718 xmlFree(prohib);
3719}
3720
3721/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003722 * xmlSchemaFreeWildcardNsSet:
3723 * set: a schema wildcard namespace
3724 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003725 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003726 */
3727static void
3728xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3729{
3730 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003731
Daniel Veillard3646d642004-06-02 19:19:14 +00003732 while (set != NULL) {
3733 next = set->next;
3734 xmlFree(set);
3735 set = next;
3736 }
3737}
3738
3739/**
3740 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003741 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003742 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003743 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003744 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003745void
Daniel Veillard3646d642004-06-02 19:19:14 +00003746xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3747{
3748 if (wildcard == NULL)
3749 return;
3750 if (wildcard->annot != NULL)
3751 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 if (wildcard->nsSet != NULL)
3753 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3754 if (wildcard->negNsSet != NULL)
3755 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003756 xmlFree(wildcard);
3757}
3758
3759/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003760 * xmlSchemaFreeAttributeGroup:
3761 * @schema: a schema attribute group structure
3762 *
3763 * Deallocate a Schema Attribute Group structure.
3764 */
3765static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003766xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003767{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003768 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003770 if (attrGr->annot != NULL)
3771 xmlSchemaFreeAnnot(attrGr->annot);
3772 if (attrGr->attrUses != NULL)
3773 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3774 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003775}
3776
3777/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003778 * xmlSchemaFreeQNameRef:
3779 * @item: a QName reference structure
3780 *
3781 * Deallocatea a QName reference structure.
3782 */
3783static void
3784xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3785{
3786 xmlFree(item);
3787}
3788
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003789/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003790 * xmlSchemaFreeTypeLinkList:
3791 * @alink: a type link
3792 *
3793 * Deallocate a list of types.
3794 */
3795static void
3796xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3797{
3798 xmlSchemaTypeLinkPtr next;
3799
3800 while (link != NULL) {
3801 next = link->next;
3802 xmlFree(link);
3803 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003805}
3806
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003807static void
3808xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3809{
3810 xmlSchemaIDCStateObjPtr next;
3811 while (sto != NULL) {
3812 next = sto->next;
3813 if (sto->history != NULL)
3814 xmlFree(sto->history);
3815 if (sto->xpathCtxt != NULL)
3816 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3817 xmlFree(sto);
3818 sto = next;
3819 }
3820}
3821
3822/**
3823 * xmlSchemaFreeIDC:
3824 * @idc: a identity-constraint definition
3825 *
3826 * Deallocates an identity-constraint definition.
3827 */
3828static void
3829xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3830{
3831 xmlSchemaIDCSelectPtr cur, prev;
3832
3833 if (idcDef == NULL)
3834 return;
3835 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003836 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003837 /* Selector */
3838 if (idcDef->selector != NULL) {
3839 if (idcDef->selector->xpathComp != NULL)
3840 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3841 xmlFree(idcDef->selector);
3842 }
3843 /* Fields */
3844 if (idcDef->fields != NULL) {
3845 cur = idcDef->fields;
3846 do {
3847 prev = cur;
3848 cur = cur->next;
3849 if (prev->xpathComp != NULL)
3850 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003852 } while (cur != NULL);
3853 }
3854 xmlFree(idcDef);
3855}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003856
Daniel Veillard01fa6152004-06-29 17:04:39 +00003857/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003858 * xmlSchemaFreeElement:
3859 * @schema: a schema element structure
3860 *
3861 * Deallocate a Schema Element structure.
3862 */
3863static void
3864xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3865{
3866 if (elem == NULL)
3867 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003868 if (elem->annot != NULL)
3869 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003871 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003872 if (elem->defVal != NULL)
3873 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 xmlFree(elem);
3875}
3876
3877/**
3878 * xmlSchemaFreeFacet:
3879 * @facet: a schema facet structure
3880 *
3881 * Deallocate a Schema Facet structure.
3882 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003883void
Daniel Veillard4255d502002-04-16 15:50:10 +00003884xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3885{
3886 if (facet == NULL)
3887 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003891 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003892 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003894 xmlFree(facet);
3895}
3896
3897/**
3898 * xmlSchemaFreeType:
3899 * @type: a schema type structure
3900 *
3901 * Deallocate a Schema Type structure.
3902 */
3903void
3904xmlSchemaFreeType(xmlSchemaTypePtr type)
3905{
3906 if (type == NULL)
3907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003908 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003909 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 facet = type->facets;
3914 while (facet != NULL) {
3915 next = facet->next;
3916 xmlSchemaFreeFacet(facet);
3917 facet = next;
3918 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003919 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003920 if (type->attrUses != NULL)
3921 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003922 if (type->memberTypes != NULL)
3923 xmlSchemaFreeTypeLinkList(type->memberTypes);
3924 if (type->facetSet != NULL) {
3925 xmlSchemaFacetLinkPtr next, link;
3926
3927 link = type->facetSet;
3928 do {
3929 next = link->next;
3930 xmlFree(link);
3931 link = next;
3932 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003933 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003934 if (type->contModel != NULL)
3935 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 xmlFree(type);
3937}
3938
3939/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003940 * xmlSchemaFreeModelGroupDef:
3941 * @item: a schema model group definition
3942 *
3943 * Deallocates a schema model group definition.
3944 */
3945static void
3946xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3947{
3948 if (item->annot != NULL)
3949 xmlSchemaFreeAnnot(item->annot);
3950 xmlFree(item);
3951}
3952
3953/**
3954 * xmlSchemaFreeModelGroup:
3955 * @item: a schema model group
3956 *
3957 * Deallocates a schema model group structure.
3958 */
3959static void
3960xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3961{
3962 if (item->annot != NULL)
3963 xmlSchemaFreeAnnot(item->annot);
3964 xmlFree(item);
3965}
3966
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003967static void
3968xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3969{
3970 if ((list == NULL) || (list->nbItems == 0))
3971 return;
3972 {
3973 xmlSchemaTreeItemPtr item;
3974 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3975 int i;
3976
3977 for (i = 0; i < list->nbItems; i++) {
3978 item = items[i];
3979 if (item == NULL)
3980 continue;
3981 switch (item->type) {
3982 case XML_SCHEMA_TYPE_SIMPLE:
3983 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003984 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003985 break;
3986 case XML_SCHEMA_TYPE_ATTRIBUTE:
3987 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003988 break;
3989 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
3990 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
3991 break;
3992 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
3993 xmlSchemaFreeAttributeUseProhib(
3994 (xmlSchemaAttributeUseProhibPtr) item);
3995 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003996 case XML_SCHEMA_TYPE_ELEMENT:
3997 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
3998 break;
3999 case XML_SCHEMA_TYPE_PARTICLE:
4000 if (item->annot != NULL)
4001 xmlSchemaFreeAnnot(item->annot);
4002 xmlFree(item);
4003 break;
4004 case XML_SCHEMA_TYPE_SEQUENCE:
4005 case XML_SCHEMA_TYPE_CHOICE:
4006 case XML_SCHEMA_TYPE_ALL:
4007 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4008 break;
4009 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4010 xmlSchemaFreeAttributeGroup(
4011 (xmlSchemaAttributeGroupPtr) item);
4012 break;
4013 case XML_SCHEMA_TYPE_GROUP:
4014 xmlSchemaFreeModelGroupDef(
4015 (xmlSchemaModelGroupDefPtr) item);
4016 break;
4017 case XML_SCHEMA_TYPE_ANY:
4018 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4019 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4020 break;
4021 case XML_SCHEMA_TYPE_IDC_KEY:
4022 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4023 case XML_SCHEMA_TYPE_IDC_KEYREF:
4024 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4025 break;
4026 case XML_SCHEMA_TYPE_NOTATION:
4027 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4028 break;
4029 case XML_SCHEMA_EXTRA_QNAMEREF:
4030 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4031 break;
4032 default: {
4033 /* TODO: This should never be hit. */
4034 xmlSchemaPSimpleInternalErr(NULL,
4035 "Internal error: xmlSchemaComponentListFree, "
4036 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004037 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004038 }
4039 break;
4040 }
4041 }
4042 list->nbItems = 0;
4043 }
4044}
4045
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004046/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004047 * xmlSchemaFree:
4048 * @schema: a schema structure
4049 *
4050 * Deallocate a Schema structure.
4051 */
4052void
4053xmlSchemaFree(xmlSchemaPtr schema)
4054{
4055 if (schema == NULL)
4056 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004057 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004058 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004059 TODO
4060 /*
4061 * Note that those slots are not responsible for freeing
4062 * schema components anymore; this will now be done by
4063 * the schema buckets.
4064 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004065 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004066 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004068 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004069 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004070 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004072 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004073 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004074 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004075 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004076 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004077 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004078 xmlHashFree(schema->idcDef, NULL);
4079
Daniel Veillard1d913862003-11-21 00:28:39 +00004080 if (schema->schemasImports != NULL)
4081 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004082 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004083 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004084 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4085 int i;
4086 for (i = 0; i < list->nbItems; i++) {
4087 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4088 }
4089 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004090 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004091 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004093 /* Never free the doc here, since this will be done by the buckets. */
4094
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004095 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 xmlFree(schema);
4097}
4098
4099/************************************************************************
4100 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 * Debug functions *
4102 * *
4103 ************************************************************************/
4104
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004105#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004106
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004107static void
4108xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4109
Daniel Veillard4255d502002-04-16 15:50:10 +00004110/**
4111 * xmlSchemaElementDump:
4112 * @elem: an element
4113 * @output: the file output
4114 *
4115 * Dump the element
4116 */
4117static void
4118xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004119 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004120 const xmlChar * namespace ATTRIBUTE_UNUSED,
4121 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004122{
4123 if (elem == NULL)
4124 return;
4125
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004126
4127 fprintf(output, "Element");
4128 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4129 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004130 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004131 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004132 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004133 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004134#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004135 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004136 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 if (elem->maxOccurs >= UNBOUNDED)
4138 fprintf(output, "max: unbounded\n");
4139 else if (elem->maxOccurs != 1)
4140 fprintf(output, "max: %d\n", elem->maxOccurs);
4141 else
4142 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004143 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004144#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004145 /*
4146 * Misc other properties.
4147 */
4148 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4149 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4150 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004151 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004152 fprintf(output, " props: ");
4153 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4154 fprintf(output, "[fixed] ");
4155 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4156 fprintf(output, "[default] ");
4157 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4158 fprintf(output, "[abstract] ");
4159 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4160 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004161 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004162 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004163 /*
4164 * Default/fixed value.
4165 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004166 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004167 fprintf(output, " value: '%s'\n", elem->value);
4168 /*
4169 * Type.
4170 */
4171 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004172 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004173 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004174 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004175 else
4176 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004177 } else if (elem->subtypes != NULL) {
4178 /*
4179 * Dump local types.
4180 */
4181 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004182 }
4183 /*
4184 * Substitution group.
4185 */
4186 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004187 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004188 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004189 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004190 else
4191 fprintf(output, "\n");
4192 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004193}
4194
4195/**
4196 * xmlSchemaAnnotDump:
4197 * @output: the file output
4198 * @annot: a annotation
4199 *
4200 * Dump the annotation
4201 */
4202static void
4203xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4204{
4205 xmlChar *content;
4206
4207 if (annot == NULL)
4208 return;
4209
4210 content = xmlNodeGetContent(annot->content);
4211 if (content != NULL) {
4212 fprintf(output, " Annot: %s\n", content);
4213 xmlFree(content);
4214 } else
4215 fprintf(output, " Annot: empty\n");
4216}
4217
4218/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004219 * xmlSchemaContentModelDump:
4220 * @particle: the schema particle
4221 * @output: the file output
4222 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 *
4224 * Dump a SchemaType structure
4225 */
4226static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004227xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4228{
4229 xmlChar *str = NULL;
4230 xmlSchemaTreeItemPtr term;
4231 char shift[100];
4232 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004233
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004234 if (particle == NULL)
4235 return;
4236 for (i = 0;((i < depth) && (i < 25));i++)
4237 shift[2 * i] = shift[2 * i + 1] = ' ';
4238 shift[2 * i] = shift[2 * i + 1] = 0;
4239 fprintf(output, shift);
4240 if (particle->children == NULL) {
4241 fprintf(output, "MISSING particle term\n");
4242 return;
4243 }
4244 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004245 if (term == NULL) {
4246 fprintf(output, "(NULL)");
4247 } else {
4248 switch (term->type) {
4249 case XML_SCHEMA_TYPE_ELEMENT:
4250 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4251 ((xmlSchemaElementPtr)term)->targetNamespace,
4252 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004253 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004254 break;
4255 case XML_SCHEMA_TYPE_SEQUENCE:
4256 fprintf(output, "SEQUENCE");
4257 break;
4258 case XML_SCHEMA_TYPE_CHOICE:
4259 fprintf(output, "CHOICE");
4260 break;
4261 case XML_SCHEMA_TYPE_ALL:
4262 fprintf(output, "ALL");
4263 break;
4264 case XML_SCHEMA_TYPE_ANY:
4265 fprintf(output, "ANY");
4266 break;
4267 default:
4268 fprintf(output, "UNKNOWN\n");
4269 return;
4270 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004271 }
4272 if (particle->minOccurs != 1)
4273 fprintf(output, " min: %d", particle->minOccurs);
4274 if (particle->maxOccurs >= UNBOUNDED)
4275 fprintf(output, " max: unbounded");
4276 else if (particle->maxOccurs != 1)
4277 fprintf(output, " max: %d", particle->maxOccurs);
4278 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004279 if (term &&
4280 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4281 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4282 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4283 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004284 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4285 output, depth +1);
4286 }
4287 if (particle->next != NULL)
4288 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4289 output, depth);
4290}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004291
4292/**
4293 * xmlSchemaAttrUsesDump:
4294 * @uses: attribute uses list
4295 * @output: the file output
4296 *
4297 * Dumps a list of attribute use components.
4298 */
4299static void
4300xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4301{
4302 xmlSchemaAttributeUsePtr use;
4303 xmlSchemaAttributeUseProhibPtr prohib;
4304 xmlSchemaQNameRefPtr ref;
4305 const xmlChar *name, *tns;
4306 xmlChar *str = NULL;
4307 int i;
4308
4309 if ((uses == NULL) || (uses->nbItems == 0))
4310 return;
4311
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004312 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004313 for (i = 0; i < uses->nbItems; i++) {
4314 use = uses->items[i];
4315 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4316 fprintf(output, " [prohibition] ");
4317 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4318 name = prohib->name;
4319 tns = prohib->targetNamespace;
4320 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4321 fprintf(output, " [reference] ");
4322 ref = (xmlSchemaQNameRefPtr) use;
4323 name = ref->name;
4324 tns = ref->targetNamespace;
4325 } else {
4326 fprintf(output, " [use] ");
4327 name = WXS_ATTRUSE_DECL_NAME(use);
4328 tns = WXS_ATTRUSE_DECL_TNS(use);
4329 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004330 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004331 (const char *) xmlSchemaFormatQName(&str, tns, name));
4332 FREE_AND_NULL(str);
4333 }
4334}
4335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004336/**
4337 * xmlSchemaTypeDump:
4338 * @output: the file output
4339 * @type: a type structure
4340 *
4341 * Dump a SchemaType structure
4342 */
4343static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004344xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4345{
4346 if (type == NULL) {
4347 fprintf(output, "Type: NULL\n");
4348 return;
4349 }
4350 fprintf(output, "Type: ");
4351 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004352 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004354 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004355 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004356 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 switch (type->type) {
4358 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004359 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 break;
4361 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004362 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 break;
4364 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004365 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 break;
4367 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004368 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 break;
4370 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004371 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 break;
4373 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004374 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 break;
4376 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004377 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 break;
4379 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004380 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 break;
4382 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004383 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 break;
4385 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004386 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004388 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004389 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004391 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004392 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004393 break;
4394 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004395 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 break;
4397 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004398 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 break;
4400 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004401 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 break;
4403 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004404 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 break;
4406 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004407 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 break;
4409 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004410 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 break;
4412 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004413 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 }
4416 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004417 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004418 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004419 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004420 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004421 else
4422 fprintf(output, "\n");
4423 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004424 if (type->attrUses != NULL)
4425 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 if (type->annot != NULL)
4427 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004428#ifdef DUMP_CONTENT_MODEL
4429 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4430 (type->subtypes != NULL)) {
4431 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4432 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004434#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004435}
4436
4437/**
4438 * xmlSchemaDump:
4439 * @output: the file output
4440 * @schema: a schema structure
4441 *
4442 * Dump a Schema structure.
4443 */
4444void
4445xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4446{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004447 if (output == NULL)
4448 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 if (schema == NULL) {
4450 fprintf(output, "Schemas: NULL\n");
4451 return;
4452 }
4453 fprintf(output, "Schemas: ");
4454 if (schema->name != NULL)
4455 fprintf(output, "%s, ", schema->name);
4456 else
4457 fprintf(output, "no name, ");
4458 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004459 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004460 else
4461 fprintf(output, "no target namespace");
4462 fprintf(output, "\n");
4463 if (schema->annot != NULL)
4464 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4466 output);
4467 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004468 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004469}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004470
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004471#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004472/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004473 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004474 * @vctxt: the WXS validation context
4475 *
4476 * Displays the current IDC table for debug purposes.
4477 */
4478static void
4479xmlSchemaDebugDumpIDCTable(FILE * output,
4480 const xmlChar *namespaceName,
4481 const xmlChar *localName,
4482 xmlSchemaPSVIIDCBindingPtr bind)
4483{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004484 xmlChar *str = NULL;
4485 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004486 xmlSchemaPSVIIDCNodePtr tab;
4487 xmlSchemaPSVIIDCKeyPtr key;
4488 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004489
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004490 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004491 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004492 FREE_AND_NULL(str)
4493
4494 if (bind == NULL)
4495 return;
4496 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004497 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004498 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004499 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004500 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004501 for (i = 0; i < bind->nbNodes; i++) {
4502 tab = bind->nodeTable[i];
4503 fprintf(output, " ( ");
4504 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 key = tab->keys[j];
4506 if ((key != NULL) && (key->val != NULL)) {
4507 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004508 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004509 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004510 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004511 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004513 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004514 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004515 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004516 else
4517 fprintf(output, "(key missing), ");
4518 }
4519 fprintf(output, ")\n");
4520 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004521 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004522 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004523 for (i = 0; i < bind->dupls->nbItems; i++) {
4524 tab = bind->dupls->items[i];
4525 fprintf(output, " ( ");
4526 for (j = 0; j < bind->definition->nbFields; j++) {
4527 key = tab->keys[j];
4528 if ((key != NULL) && (key->val != NULL)) {
4529 res = xmlSchemaGetCanonValue(key->val, &value);
4530 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004531 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004532 else
4533 fprintf(output, "CANON-VALUE-FAILED ");
4534 if (res == 0)
4535 FREE_AND_NULL(value)
4536 } else if (key != NULL)
4537 fprintf(output, "(no val), ");
4538 else
4539 fprintf(output, "(key missing), ");
4540 }
4541 fprintf(output, ")\n");
4542 }
4543 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004544 bind = bind->next;
4545 } while (bind != NULL);
4546}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004547#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004548#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004549
4550/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004551 * *
4552 * Utilities *
4553 * *
4554 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004555
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556/**
4557 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004558 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004559 * @name: the name of the attribute
4560 *
4561 * Seeks an attribute with a name of @name in
4562 * no namespace.
4563 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004564 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004565 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004566static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004567xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004568{
4569 xmlAttrPtr prop;
4570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004572 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004573 prop = node->properties;
4574 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004575 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004576 return(prop);
4577 prop = prop->next;
4578 }
4579 return (NULL);
4580}
4581
4582/**
4583 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004585 * @uri: the uri
4586 * @name: the name of the attribute
4587 *
4588 * Seeks an attribute with a local name of @name and
4589 * a namespace URI of @uri.
4590 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004591 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004592 */
4593static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004594xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004595{
4596 xmlAttrPtr prop;
4597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004598 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004599 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004600 prop = node->properties;
4601 while (prop != NULL) {
4602 if ((prop->ns != NULL) &&
4603 xmlStrEqual(prop->name, BAD_CAST name) &&
4604 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004605 return(prop);
4606 prop = prop->next;
4607 }
4608 return (NULL);
4609}
4610
4611static const xmlChar *
4612xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4613{
4614 xmlChar *val;
4615 const xmlChar *ret;
4616
4617 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004619 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004620 ret = xmlDictLookup(ctxt->dict, val, -1);
4621 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004622 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004623}
4624
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004625static const xmlChar *
4626xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4627{
4628 return((const xmlChar*) xmlNodeGetContent(node));
4629}
4630
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004631/**
4632 * xmlSchemaGetProp:
4633 * @ctxt: the parser context
4634 * @node: the node
4635 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004636 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004637 * Read a attribute value and internalize the string
4638 *
4639 * Returns the string or NULL if not present.
4640 */
4641static const xmlChar *
4642xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4643 const char *name)
4644{
4645 xmlChar *val;
4646 const xmlChar *ret;
4647
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004648 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004649 if (val == NULL)
4650 return(NULL);
4651 ret = xmlDictLookup(ctxt->dict, val, -1);
4652 xmlFree(val);
4653 return(ret);
4654}
4655
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004656/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004657 * *
4658 * Parsing functions *
4659 * *
4660 ************************************************************************/
4661
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004662#define WXS_FIND_GLOBAL_ITEM(slot) \
4663 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4664 ret = xmlHashLookup(schema->slot, name); \
4665 if (ret != NULL) goto exit; \
4666 } \
4667 if (xmlHashSize(schema->schemasImports) > 1) { \
4668 xmlSchemaImportPtr import; \
4669 if (nsName == NULL) \
4670 import = xmlHashLookup(schema->schemasImports, \
4671 XML_SCHEMAS_NO_NAMESPACE); \
4672 else \
4673 import = xmlHashLookup(schema->schemasImports, nsName); \
4674 if (import == NULL) \
4675 goto exit; \
4676 ret = xmlHashLookup(import->schema->slot, name); \
4677 }
4678
Daniel Veillard4255d502002-04-16 15:50:10 +00004679/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004680 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004681 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004682 * @name: the element name
4683 * @ns: the element namespace
4684 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004685 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004686 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004687 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004688 */
4689static xmlSchemaElementPtr
4690xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004691 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004692{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004693 xmlSchemaElementPtr ret = NULL;
4694
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004695 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004696 return(NULL);
4697 if (schema != NULL) {
4698 WXS_FIND_GLOBAL_ITEM(elemDecl)
4699 }
4700exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004701#ifdef DEBUG
4702 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004703 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004704 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004705 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004706 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004707 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004708 }
4709#endif
4710 return (ret);
4711}
4712
4713/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004714 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004715 * @schema: the main schema
4716 * @name: the type's name
4717 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004718 *
4719 * Lookup a type in the schemas or the predefined types
4720 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004721 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004722 */
4723static xmlSchemaTypePtr
4724xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004725 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004726{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004727 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004728
4729 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004730 return (NULL);
4731 /* First try the built-in types. */
4732 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4733 ret = xmlSchemaGetPredefinedType(name, nsName);
4734 if (ret != NULL)
4735 goto exit;
4736 /*
4737 * Note that we try the parsed schemas as well here
4738 * since one might have parsed the S4S, which contain more
4739 * than the built-in types.
4740 * TODO: Can we optimize this?
4741 */
4742 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004743 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004744 WXS_FIND_GLOBAL_ITEM(typeDecl)
4745 }
4746exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004747
Daniel Veillard4255d502002-04-16 15:50:10 +00004748#ifdef DEBUG
4749 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004750 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004751 fprintf(stderr, "Unable to lookup type %s", name);
4752 else
4753 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004754 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004755 }
4756#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004757 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004758}
4759
Daniel Veillard3646d642004-06-02 19:19:14 +00004760/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004761 * xmlSchemaGetAttributeDecl:
4762 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004763 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004764 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004765 *
4766 * Lookup a an attribute in the schema or imported schemas
4767 *
4768 * Returns the attribute declaration or NULL if not found.
4769 */
4770static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004771xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004772 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004773{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004774 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004775
4776 if ((name == NULL) || (schema == NULL))
4777 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004778 if (schema != NULL) {
4779 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004780 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004781exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004782#ifdef DEBUG
4783 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004784 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004785 fprintf(stderr, "Unable to lookup attribute %s", name);
4786 else
4787 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004788 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004789 }
4790#endif
4791 return (ret);
4792}
4793
4794/**
4795 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004797 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004798 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004799 *
4800 * Lookup a an attribute group in the schema or imported schemas
4801 *
4802 * Returns the attribute group definition or NULL if not found.
4803 */
4804static xmlSchemaAttributeGroupPtr
4805xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004806 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004807{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004808 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004809
4810 if ((name == NULL) || (schema == NULL))
4811 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004812 if (schema != NULL) {
4813 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4814 }
4815exit:
4816 /* TODO:
4817 if ((ret != NULL) && (ret->redef != NULL)) {
4818 * Return the last redefinition. *
4819 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004821 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004822#ifdef DEBUG
4823 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004824 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 fprintf(stderr, "Unable to lookup attribute group %s", name);
4826 else
4827 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004828 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004829 }
4830#endif
4831 return (ret);
4832}
4833
4834/**
4835 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004836 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004837 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004838 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004839 *
4840 * Lookup a group in the schema or imported schemas
4841 *
4842 * Returns the group definition or NULL if not found.
4843 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004844static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004845xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004846 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004847{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004848 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004849
4850 if ((name == NULL) || (schema == NULL))
4851 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004852 if (schema != NULL) {
4853 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004854 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004855exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004856
Daniel Veillard3646d642004-06-02 19:19:14 +00004857#ifdef DEBUG
4858 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004859 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004860 fprintf(stderr, "Unable to lookup group %s", name);
4861 else
4862 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004863 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004864 }
4865#endif
4866 return (ret);
4867}
4868
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004869static xmlSchemaNotationPtr
4870xmlSchemaGetNotation(xmlSchemaPtr schema,
4871 const xmlChar *name,
4872 const xmlChar *nsName)
4873{
4874 xmlSchemaNotationPtr ret = NULL;
4875
4876 if ((name == NULL) || (schema == NULL))
4877 return (NULL);
4878 if (schema != NULL) {
4879 WXS_FIND_GLOBAL_ITEM(notaDecl)
4880 }
4881exit:
4882 return (ret);
4883}
4884
4885static xmlSchemaIDCPtr
4886xmlSchemaGetIDC(xmlSchemaPtr schema,
4887 const xmlChar *name,
4888 const xmlChar *nsName)
4889{
4890 xmlSchemaIDCPtr ret = NULL;
4891
4892 if ((name == NULL) || (schema == NULL))
4893 return (NULL);
4894 if (schema != NULL) {
4895 WXS_FIND_GLOBAL_ITEM(idcDef)
4896 }
4897exit:
4898 return (ret);
4899}
4900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004901/**
4902 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004903 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004904 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004905 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004906 *
4907 * Lookup a group in the schema or imported schemas
4908 *
4909 * Returns the group definition or NULL if not found.
4910 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004911static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004912xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4913 xmlSchemaTypeType itemType,
4914 const xmlChar *name,
4915 const xmlChar *targetNs)
4916{
4917 switch (itemType) {
4918 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004919 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004920 name, targetNs));
4921 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004922 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004923 name, targetNs));
4924 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004925 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004926 return (NULL);
4927 }
4928}
4929
Daniel Veillard4255d502002-04-16 15:50:10 +00004930/************************************************************************
4931 * *
4932 * Parsing functions *
4933 * *
4934 ************************************************************************/
4935
4936#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004937 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004938
4939/**
4940 * xmlSchemaIsBlank:
4941 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004942 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004943 *
4944 * Check if a string is ignorable
4945 *
4946 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4947 */
4948static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004949xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004950{
Daniel Veillard4255d502002-04-16 15:50:10 +00004951 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004952 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004953 if (len < 0) {
4954 while (*str != 0) {
4955 if (!(IS_BLANK_CH(*str)))
4956 return (0);
4957 str++;
4958 }
4959 } else while ((*str != 0) && (len != 0)) {
4960 if (!(IS_BLANK_CH(*str)))
4961 return (0);
4962 str++;
4963 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004964 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004965
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004966 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004967}
4968
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004969#define WXS_COMP_NAME(c, t) ((t) (c))->name
4970#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4971/*
4972* xmlSchemaFindRedefCompInGraph:
4973* ATTENTION TODO: This uses pointer comp. for strings.
4974*/
4975static xmlSchemaBasicItemPtr
4976xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4977 xmlSchemaTypeType type,
4978 const xmlChar *name,
4979 const xmlChar *nsName)
4980{
4981 xmlSchemaBasicItemPtr ret;
4982 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004983
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004984 if ((bucket == NULL) || (name == NULL))
4985 return(NULL);
4986 if ((bucket->globals == NULL) ||
4987 (bucket->globals->nbItems == 0))
4988 goto subschemas;
4989 /*
4990 * Search in global components.
4991 */
4992 for (i = 0; i < bucket->globals->nbItems; i++) {
4993 ret = bucket->globals->items[i];
4994 if (ret->type == type) {
4995 switch (type) {
4996 case XML_SCHEMA_TYPE_COMPLEX:
4997 case XML_SCHEMA_TYPE_SIMPLE:
4998 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
4999 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5000 nsName))
5001 {
5002 return(ret);
5003 }
5004 break;
5005 case XML_SCHEMA_TYPE_GROUP:
5006 if ((WXS_COMP_NAME(ret,
5007 xmlSchemaModelGroupDefPtr) == name) &&
5008 (WXS_COMP_TNS(ret,
5009 xmlSchemaModelGroupDefPtr) == nsName))
5010 {
5011 return(ret);
5012 }
5013 break;
5014 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5015 if ((WXS_COMP_NAME(ret,
5016 xmlSchemaAttributeGroupPtr) == name) &&
5017 (WXS_COMP_TNS(ret,
5018 xmlSchemaAttributeGroupPtr) == nsName))
5019 {
5020 return(ret);
5021 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005022 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005023 default:
5024 /* Should not be hit. */
5025 return(NULL);
5026 }
5027 }
5028 }
5029subschemas:
5030 /*
5031 * Process imported/included schemas.
5032 */
5033 if (bucket->relations != NULL) {
5034 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5035
5036 /*
5037 * TODO: Marking the bucket will not avoid multiple searches
5038 * in the same schema, but avoids at least circularity.
5039 */
5040 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5041 do {
5042 if ((rel->bucket != NULL) &&
5043 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5044 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5045 type, name, nsName);
5046 if (ret != NULL)
5047 return(ret);
5048 }
5049 rel = rel->next;
5050 } while (rel != NULL);
5051 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5052 }
5053 return(NULL);
5054}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005055
5056/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005057 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005058 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005059 * @schema: the schema being built
5060 * @name: the item name
5061 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005062 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 * *WARNING* this interface is highly subject to change
5064 *
5065 * Returns the new struture or NULL in case of error
5066 */
5067static xmlSchemaNotationPtr
5068xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005069 const xmlChar *name, const xmlChar *nsName,
5070 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005071{
5072 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005073
5074 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5075 return (NULL);
5076
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5078 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005079 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 return (NULL);
5081 }
5082 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005083 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005084 ret->name = name;
5085 ret->targetNamespace = nsName;
5086 /* TODO: do we need the node to be set?
5087 * ret->node = node;*/
5088 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 return (ret);
5090}
5091
Daniel Veillard4255d502002-04-16 15:50:10 +00005092/**
5093 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005094 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005095 * @schema: the schema being built
5096 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005097 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 *
5099 * Add an XML schema Attrribute declaration
5100 * *WARNING* this interface is highly subject to change
5101 *
5102 * Returns the new struture or NULL in case of error
5103 */
5104static xmlSchemaAttributePtr
5105xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005106 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005107 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005108{
5109 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005110
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005111 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005112 return (NULL);
5113
5114 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5115 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 return (NULL);
5118 }
5119 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005120 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5121 ret->node = node;
5122 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005123 ret->targetNamespace = nsName;
5124
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005125 if (topLevel)
5126 WXS_ADD_GLOBAL(ctxt, ret);
5127 else
5128 WXS_ADD_LOCAL(ctxt, ret);
5129 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005130 return (ret);
5131}
5132
5133/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005134 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005135 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 * @schema: the schema being built
5137 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005138 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005139 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005140 * Add an XML schema Attrribute declaration
5141 * *WARNING* this interface is highly subject to change
5142 *
5143 * Returns the new struture or NULL in case of error
5144 */
5145static xmlSchemaAttributeUsePtr
5146xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5147 xmlNodePtr node)
5148{
5149 xmlSchemaAttributeUsePtr ret = NULL;
5150
5151 if (pctxt == NULL)
5152 return (NULL);
5153
5154 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5155 if (ret == NULL) {
5156 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5157 return (NULL);
5158 }
5159 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5160 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5161 ret->node = node;
5162
5163 WXS_ADD_LOCAL(pctxt, ret);
5164 return (ret);
5165}
5166
5167/*
5168* xmlSchemaAddRedef:
5169*
5170* Adds a redefinition information. This is used at a later stage to:
5171* resolve references to the redefined components and to check constraints.
5172*/
5173static xmlSchemaRedefPtr
5174xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5175 xmlSchemaBucketPtr targetBucket,
5176 void *item,
5177 const xmlChar *refName,
5178 const xmlChar *refTargetNs)
5179{
5180 xmlSchemaRedefPtr ret;
5181
5182 ret = (xmlSchemaRedefPtr)
5183 xmlMalloc(sizeof(xmlSchemaRedef));
5184 if (ret == NULL) {
5185 xmlSchemaPErrMemory(pctxt,
5186 "allocating redefinition info", NULL);
5187 return (NULL);
5188 }
5189 memset(ret, 0, sizeof(xmlSchemaRedef));
5190 ret->item = item;
5191 ret->targetBucket = targetBucket;
5192 ret->refName = refName;
5193 ret->refTargetNs = refTargetNs;
5194 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5195 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5196 else
5197 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5198 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5199
5200 return (ret);
5201}
5202
5203/**
5204 * xmlSchemaAddAttributeGroupDefinition:
5205 * @ctxt: a schema parser context
5206 * @schema: the schema being built
5207 * @name: the item name
5208 * @nsName: the target namespace
5209 * @node: the corresponding node
5210 *
5211 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005212 *
5213 * Returns the new struture or NULL in case of error
5214 */
5215static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005216xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5217 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5218 const xmlChar *name,
5219 const xmlChar *nsName,
5220 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005221{
5222 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005223
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005224 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005225 return (NULL);
5226
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005227 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005228 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005229 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005230 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005231 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 }
5233 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005234 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005235 ret->name = name;
5236 ret->targetNamespace = nsName;
5237 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005238
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005239 /* TODO: Remove the flag. */
5240 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5241 if (pctxt->isRedefine) {
5242 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5243 ret, name, nsName);
5244 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005245 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005246 return(NULL);
5247 }
5248 pctxt->redefCounter = 0;
5249 }
5250 WXS_ADD_GLOBAL(pctxt, ret);
5251 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 return (ret);
5253}
5254
5255/**
5256 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005257 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005258 * @schema: the schema being built
5259 * @name: the type name
5260 * @namespace: the type namespace
5261 *
5262 * Add an XML schema Element declaration
5263 * *WARNING* this interface is highly subject to change
5264 *
5265 * Returns the new struture or NULL in case of error
5266 */
5267static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005268xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005269 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005270 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005271{
5272 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005274 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 return (NULL);
5276
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5278 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005279 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280 return (NULL);
5281 }
5282 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005283 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5284 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005285 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005286 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005287
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005288 if (topLevel)
5289 WXS_ADD_GLOBAL(ctxt, ret);
5290 else
5291 WXS_ADD_LOCAL(ctxt, ret);
5292 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005293 return (ret);
5294}
5295
5296/**
5297 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005298 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005299 * @schema: the schema being built
5300 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005301 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005302 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005303 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 * *WARNING* this interface is highly subject to change
5305 *
5306 * Returns the new struture or NULL in case of error
5307 */
5308static xmlSchemaTypePtr
5309xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005310 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005311 const xmlChar * name, const xmlChar * nsName,
5312 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005313{
5314 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005315
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005316 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 return (NULL);
5318
5319 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5320 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 return (NULL);
5323 }
5324 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005325 ret->type = type;
5326 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005327 ret->targetNamespace = nsName;
5328 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005329 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005330 if (ctxt->isRedefine) {
5331 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5332 ret, name, nsName);
5333 if (ctxt->redef == NULL) {
5334 xmlFree(ret);
5335 return(NULL);
5336 }
5337 ctxt->redefCounter = 0;
5338 }
5339 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005340 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005341 WXS_ADD_LOCAL(ctxt, ret);
5342 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005343 return (ret);
5344}
5345
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005346static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005347xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005348 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005349 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005350 const xmlChar *refNs)
5351{
5352 xmlSchemaQNameRefPtr ret;
5353
5354 ret = (xmlSchemaQNameRefPtr)
5355 xmlMalloc(sizeof(xmlSchemaQNameRef));
5356 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005357 xmlSchemaPErrMemory(pctxt,
5358 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005359 return (NULL);
5360 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005361 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005362 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5363 ret->name = refName;
5364 ret->targetNamespace = refNs;
5365 ret->item = NULL;
5366 ret->itemType = refType;
5367 /*
5368 * Store the reference item in the schema.
5369 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005370 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005371 return (ret);
5372}
5373
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005374static xmlSchemaAttributeUseProhibPtr
5375xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5376{
5377 xmlSchemaAttributeUseProhibPtr ret;
5378
5379 ret = (xmlSchemaAttributeUseProhibPtr)
5380 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5381 if (ret == NULL) {
5382 xmlSchemaPErrMemory(pctxt,
5383 "allocating attribute use prohibition", NULL);
5384 return (NULL);
5385 }
5386 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5387 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5388 WXS_ADD_LOCAL(pctxt, ret);
5389 return (ret);
5390}
5391
5392
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005393/**
5394 * xmlSchemaAddModelGroup:
5395 * @ctxt: a schema parser context
5396 * @schema: the schema being built
5397 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005398 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005399 *
5400 * Adds a schema model group
5401 * *WARNING* this interface is highly subject to change
5402 *
5403 * Returns the new struture or NULL in case of error
5404 */
5405static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005406xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5407 xmlSchemaPtr schema,
5408 xmlSchemaTypeType type,
5409 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005410{
5411 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005412
5413 if ((ctxt == NULL) || (schema == NULL))
5414 return (NULL);
5415
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005416 ret = (xmlSchemaModelGroupPtr)
5417 xmlMalloc(sizeof(xmlSchemaModelGroup));
5418 if (ret == NULL) {
5419 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5420 NULL);
5421 return (NULL);
5422 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005423 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005424 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005425 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005426 WXS_ADD_LOCAL(ctxt, ret);
5427 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5428 (type == XML_SCHEMA_TYPE_CHOICE))
5429 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430 return (ret);
5431}
5432
5433
5434/**
5435 * xmlSchemaAddParticle:
5436 * @ctxt: a schema parser context
5437 * @schema: the schema being built
5438 * @node: the corresponding node in the schema doc
5439 * @min: the minOccurs
5440 * @max: the maxOccurs
5441 *
5442 * Adds an XML schema particle component.
5443 * *WARNING* this interface is highly subject to change
5444 *
5445 * Returns the new struture or NULL in case of error
5446 */
5447static xmlSchemaParticlePtr
5448xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5449 xmlNodePtr node, int min, int max)
5450{
5451 xmlSchemaParticlePtr ret = NULL;
5452 if ((ctxt == NULL) || (schema == NULL))
5453 return (NULL);
5454
5455#ifdef DEBUG
5456 fprintf(stderr, "Adding particle component\n");
5457#endif
5458 ret = (xmlSchemaParticlePtr)
5459 xmlMalloc(sizeof(xmlSchemaParticle));
5460 if (ret == NULL) {
5461 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5462 NULL);
5463 return (NULL);
5464 }
5465 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5466 ret->annot = NULL;
5467 ret->node = node;
5468 ret->minOccurs = min;
5469 ret->maxOccurs = max;
5470 ret->next = NULL;
5471 ret->children = NULL;
5472
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005473 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005474 /*
5475 * Note that addition to pending components will be done locally
5476 * to the specific parsing function, since the most particles
5477 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005478 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005479 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005480 return (ret);
5481}
5482
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005483/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005484 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005485 * @ctxt: a schema validation context
5486 * @schema: the schema being built
5487 * @name: the group name
5488 *
5489 * Add an XML schema Group definition
5490 *
5491 * Returns the new struture or NULL in case of error
5492 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005493static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005494xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5495 xmlSchemaPtr schema,
5496 const xmlChar *name,
5497 const xmlChar *nsName,
5498 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005499{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005500 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005501
5502 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5503 return (NULL);
5504
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005505 ret = (xmlSchemaModelGroupDefPtr)
5506 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005507 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005508 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005509 return (NULL);
5510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005511 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005512 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005513 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005514 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005515 ret->targetNamespace = nsName;
5516
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005517 if (ctxt->isRedefine) {
5518 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5519 ret, name, nsName);
5520 if (ctxt->redef == NULL) {
5521 xmlFree(ret);
5522 return(NULL);
5523 }
5524 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005525 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005526 WXS_ADD_GLOBAL(ctxt, ret);
5527 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005528 return (ret);
5529}
5530
Daniel Veillard3646d642004-06-02 19:19:14 +00005531/**
5532 * xmlSchemaNewWildcardNs:
5533 * @ctxt: a schema validation context
5534 *
5535 * Creates a new wildcard namespace constraint.
5536 *
5537 * Returns the new struture or NULL in case of error
5538 */
5539static xmlSchemaWildcardNsPtr
5540xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5541{
5542 xmlSchemaWildcardNsPtr ret;
5543
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005544 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005545 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5546 if (ret == NULL) {
5547 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005548 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005549 }
5550 ret->value = NULL;
5551 ret->next = NULL;
5552 return (ret);
5553}
5554
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005555static xmlSchemaIDCPtr
5556xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5557 const xmlChar *name, const xmlChar *nsName,
5558 int category, xmlNodePtr node)
5559{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005560 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005561
5562 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5563 return (NULL);
5564
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005565 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5566 if (ret == NULL) {
5567 xmlSchemaPErrMemory(ctxt,
5568 "allocating an identity-constraint definition", NULL);
5569 return (NULL);
5570 }
5571 memset(ret, 0, sizeof(xmlSchemaIDC));
5572 /* The target namespace of the parent element declaration. */
5573 ret->targetNamespace = nsName;
5574 ret->name = name;
5575 ret->type = category;
5576 ret->node = node;
5577
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005578 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005579 /*
5580 * Only keyrefs need to be fixup up.
5581 */
5582 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005583 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005584 return (ret);
5585}
5586
Daniel Veillard3646d642004-06-02 19:19:14 +00005587/**
5588 * xmlSchemaAddWildcard:
5589 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 * @schema: a schema
5591 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005592 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005593 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005594 *
5595 * Returns the new struture or NULL in case of error
5596 */
5597static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005598xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5599 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005600{
5601 xmlSchemaWildcardPtr ret = NULL;
5602
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005603 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005604 return (NULL);
5605
5606 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5607 if (ret == NULL) {
5608 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5609 return (NULL);
5610 }
5611 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005612 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005613 ret->node = node;
5614 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005615 return (ret);
5616}
5617
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005618static void
5619xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5620{
5621 if (group == NULL)
5622 return;
5623 if (group->members != NULL)
5624 xmlSchemaItemListFree(group->members);
5625 xmlFree(group);
5626}
5627
5628static xmlSchemaSubstGroupPtr
5629xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5630 xmlSchemaElementPtr head)
5631{
5632 xmlSchemaSubstGroupPtr ret;
5633
5634 /* Init subst group hash. */
5635 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5636 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5637 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5638 return(NULL);
5639 }
5640 /* Create a new substitution group. */
5641 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5642 if (ret == NULL) {
5643 xmlSchemaPErrMemory(NULL,
5644 "allocating a substitution group container", NULL);
5645 return(NULL);
5646 }
5647 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5648 ret->head = head;
5649 /* Create list of members. */
5650 ret->members = xmlSchemaItemListCreate();
5651 if (ret->members == NULL) {
5652 xmlSchemaSubstGroupFree(ret);
5653 return(NULL);
5654 }
5655 /* Add subst group to hash. */
5656 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5657 head->name, head->targetNamespace, ret) != 0) {
5658 PERROR_INT("xmlSchemaSubstGroupAdd",
5659 "failed to add a new substitution container");
5660 xmlSchemaSubstGroupFree(ret);
5661 return(NULL);
5662 }
5663 return(ret);
5664}
5665
5666static xmlSchemaSubstGroupPtr
5667xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5668 xmlSchemaElementPtr head)
5669{
5670 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5671 return(NULL);
5672 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5673 head->name, head->targetNamespace));
5674
5675}
5676
5677/**
5678 * xmlSchemaAddElementSubstitutionMember:
5679 * @pctxt: a schema parser context
5680 * @head: the head of the substitution group
5681 * @member: the new member of the substitution group
5682 *
5683 * Allocate a new annotation structure.
5684 *
5685 * Returns the newly allocated structure or NULL in case or error
5686 */
5687static int
5688xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5689 xmlSchemaElementPtr head,
5690 xmlSchemaElementPtr member)
5691{
5692 xmlSchemaSubstGroupPtr substGroup = NULL;
5693
5694 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5695 return (-1);
5696
5697 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5698 if (substGroup == NULL)
5699 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5700 if (substGroup == NULL)
5701 return(-1);
5702 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5703 return(-1);
5704 return(0);
5705}
5706
Daniel Veillard4255d502002-04-16 15:50:10 +00005707/************************************************************************
5708 * *
5709 * Utilities for parsing *
5710 * *
5711 ************************************************************************/
5712
Daniel Veillard4255d502002-04-16 15:50:10 +00005713/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 * xmlSchemaPValAttrNodeQNameValue:
5715 * @ctxt: a schema parser context
5716 * @schema: the schema context
5717 * @ownerDes: the designation of the parent element
5718 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005719 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005720 * @local: the resulting local part if found, the attribute value otherwise
5721 * @uri: the resulting namespace URI if found
5722 *
5723 * Extracts the local name and the URI of a QName value and validates it.
5724 * This one is intended to be used on attribute values that
5725 * should resolve to schema components.
5726 *
5727 * Returns 0, in case the QName is valid, a positive error code
5728 * if not valid and -1 if an internal error occurs.
5729 */
5730static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005731xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005732 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005733 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 xmlAttrPtr attr,
5735 const xmlChar *value,
5736 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 const xmlChar **local)
5738{
5739 const xmlChar *pref;
5740 xmlNsPtr ns;
5741 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005742
Daniel Veillardc0826a72004-08-10 14:17:33 +00005743 *uri = NULL;
5744 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005745 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746 if (ret > 0) {
5747 xmlSchemaPSimpleTypeErr(ctxt,
5748 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5749 ownerItem, (xmlNodePtr) attr,
5750 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5751 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005753 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 } else if (ret < 0)
5755 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005756
5757 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005758 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 if (ns)
5760 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5761 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005762 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5763 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 /*
5765 * This one takes care of included schemas with no
5766 * target namespace.
5767 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005768 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005770 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005771 return (0);
5772 }
5773 /*
5774 * At this point xmlSplitQName3 has to return a local name.
5775 */
5776 *local = xmlSplitQName3(value, &len);
5777 *local = xmlDictLookup(ctxt->dict, *local, -1);
5778 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5780 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005781 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005782 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005783 ownerItem, (xmlNodePtr) attr,
5784 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5785 "The value '%s' of simple type 'xs:QName' has no "
5786 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005787 return (ctxt->err);
5788 } else {
5789 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005790 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 return (0);
5792}
5793
5794/**
5795 * xmlSchemaPValAttrNodeQName:
5796 * @ctxt: a schema parser context
5797 * @schema: the schema context
5798 * @ownerDes: the designation of the owner element
5799 * @ownerItem: the owner as a schema object
5800 * @attr: the attribute node
5801 * @local: the resulting local part if found, the attribute value otherwise
5802 * @uri: the resulting namespace URI if found
5803 *
5804 * Extracts and validates the QName of an attribute value.
5805 * This one is intended to be used on attribute values that
5806 * should resolve to schema components.
5807 *
5808 * Returns 0, in case the QName is valid, a positive error code
5809 * if not valid and -1 if an internal error occurs.
5810 */
5811static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005812xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005813 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005814 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 xmlAttrPtr attr,
5816 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 const xmlChar **local)
5818{
5819 const xmlChar *value;
5820
5821 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005822 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005823 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005824}
5825
5826/**
5827 * xmlSchemaPValAttrQName:
5828 * @ctxt: a schema parser context
5829 * @schema: the schema context
5830 * @ownerDes: the designation of the parent element
5831 * @ownerItem: the owner as a schema object
5832 * @ownerElem: the parent node of the attribute
5833 * @name: the name of the attribute
5834 * @local: the resulting local part if found, the attribute value otherwise
5835 * @uri: the resulting namespace URI if found
5836 *
5837 * Extracts and validates the QName of an attribute value.
5838 *
5839 * Returns 0, in case the QName is valid, a positive error code
5840 * if not valid and -1 if an internal error occurs.
5841 */
5842static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005843xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5844 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005845 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005846 xmlNodePtr ownerElem,
5847 const char *name,
5848 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005849 const xmlChar **local)
5850{
5851 xmlAttrPtr attr;
5852
5853 attr = xmlSchemaGetPropNode(ownerElem, name);
5854 if (attr == NULL) {
5855 *local = NULL;
5856 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005857 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005859 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005860 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861}
5862
5863/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005864 * xmlSchemaPValAttrID:
5865 * @ctxt: a schema parser context
5866 * @schema: the schema context
5867 * @ownerDes: the designation of the parent element
5868 * @ownerItem: the owner as a schema object
5869 * @ownerElem: the parent node of the attribute
5870 * @name: the name of the attribute
5871 *
5872 * Extracts and validates the ID of an attribute value.
5873 *
5874 * Returns 0, in case the ID is valid, a positive error code
5875 * if not valid and -1 if an internal error occurs.
5876 */
5877static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005878xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005879{
5880 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005881 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005882
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005883 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005884 return(0);
5885 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5886 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005887 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005888 /*
5889 * NOTE: the IDness might have already be declared in the DTD
5890 */
5891 if (attr->atype != XML_ATTRIBUTE_ID) {
5892 xmlIDPtr res;
5893 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005894
5895 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005896 * TODO: Use xmlSchemaStrip here; it's not exported at this
5897 * moment.
5898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005899 strip = xmlSchemaCollapseString(value);
5900 if (strip != NULL) {
5901 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005902 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005903 }
5904 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005905 if (res == NULL) {
5906 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 xmlSchemaPSimpleTypeErr(ctxt,
5908 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005909 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005910 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5911 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005912 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005913 } else
5914 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005915 }
5916 } else if (ret > 0) {
5917 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005918 xmlSchemaPSimpleTypeErr(ctxt,
5919 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005920 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005921 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5922 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5923 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005924 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005925 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005926 if (value != NULL)
5927 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005928
5929 return (ret);
5930}
5931
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005932static int
5933xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5934 xmlNodePtr ownerElem,
5935 const xmlChar *name)
5936{
5937 xmlAttrPtr attr;
5938
5939 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5940 if (attr == NULL)
5941 return(0);
5942 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5943
5944}
5945
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005946/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005947 * xmlGetMaxOccurs:
5948 * @ctxt: a schema validation context
5949 * @node: a subtree containing XML Schema informations
5950 *
5951 * Get the maxOccurs property
5952 *
5953 * Returns the default if not found, or the value
5954 */
5955static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005956xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5957 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005958{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005959 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005961 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005962
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005963 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5964 if (attr == NULL)
5965 return (def);
5966 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005967
5968 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005969 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005970 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005971 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5972 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005974 val, NULL, NULL, NULL);
5975 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005976 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005977 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005978 }
5979
5980 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005981 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005982 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005984 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005985 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5986 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005987 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005988 val, NULL, NULL, NULL);
5989 return (def);
5990 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005992 ret = ret * 10 + (*cur - '0');
5993 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005994 }
William M. Brack76e95df2003-10-18 16:20:14 +00005995 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 /*
5998 * TODO: Restrict the maximal value to Integer.
5999 */
6000 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006001 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6003 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006004 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006005 val, NULL, NULL, NULL);
6006 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006007 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006008 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006009}
6010
6011/**
6012 * xmlGetMinOccurs:
6013 * @ctxt: a schema validation context
6014 * @node: a subtree containing XML Schema informations
6015 *
6016 * Get the minOccurs property
6017 *
6018 * Returns the default if not found, or the value
6019 */
6020static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006021xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006022 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006023{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006024 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006025 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006026 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006027
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006028 attr = xmlSchemaGetPropNode(node, "minOccurs");
6029 if (attr == NULL)
6030 return (def);
6031 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006033 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006035 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006036 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006037 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6038 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006039 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006040 val, NULL, NULL, NULL);
6041 return (def);
6042 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006043 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006044 ret = ret * 10 + (*cur - '0');
6045 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006046 }
William M. Brack76e95df2003-10-18 16:20:14 +00006047 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006049 /*
6050 * TODO: Restrict the maximal value to Integer.
6051 */
6052 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006053 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006054 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6055 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006056 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 val, NULL, NULL, NULL);
6058 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006059 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006060 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006061}
6062
6063/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006064 * xmlSchemaPGetBoolNodeValue:
6065 * @ctxt: a schema validation context
6066 * @ownerDes: owner designation
6067 * @ownerItem: the owner as a schema item
6068 * @node: the node holding the value
6069 *
6070 * Converts a boolean string value into 1 or 0.
6071 *
6072 * Returns 0 or 1.
6073 */
6074static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006075xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006076 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006077 xmlNodePtr node)
6078{
6079 xmlChar *value = NULL;
6080 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006081
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006082 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006084 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006085 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006086 * can have the following legal literals {true, false, 1, 0}.
6087 */
6088 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6089 res = 1;
6090 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6091 res = 0;
6092 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6093 res = 1;
6094 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006096 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006097 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006098 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 ownerItem, node,
6100 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6101 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006102 NULL, NULL, NULL);
6103 }
6104 if (value != NULL)
6105 xmlFree(value);
6106 return (res);
6107}
6108
6109/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 * xmlGetBooleanProp:
6111 * @ctxt: a schema validation context
6112 * @node: a subtree containing XML Schema informations
6113 * @name: the attribute name
6114 * @def: the default value
6115 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006116 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006117 *
6118 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006119 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006120 */
6121static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006122xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006123 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006124 const char *name, int def)
6125{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006126 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006128 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006131 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006132 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006133 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006134 * can have the following legal literals {true, false, 1, 0}.
6135 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 if (xmlStrEqual(val, BAD_CAST "true"))
6137 def = 1;
6138 else if (xmlStrEqual(val, BAD_CAST "false"))
6139 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006140 else if (xmlStrEqual(val, BAD_CAST "1"))
6141 def = 1;
6142 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143 def = 0;
6144 else {
6145 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006146 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006147 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006148 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006149 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6150 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006151 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006152 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006153}
6154
6155/************************************************************************
6156 * *
6157 * Shema extraction from an Infoset *
6158 * *
6159 ************************************************************************/
6160static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6161 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006162 xmlNodePtr node,
6163 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6165 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006167 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006168 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006169static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6170 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006172 xmlNodePtr node,
6173 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006174static xmlSchemaBasicItemPtr
6175xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6176 xmlSchemaPtr schema,
6177 xmlNodePtr node,
6178 xmlSchemaItemListPtr uses,
6179 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006180static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6181 xmlSchemaPtr schema,
6182 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006183static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6185 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006186
6187/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006188 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006189 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006190 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006191 * @ownerDes: the designation of the parent element
6192 * @ownerItem: the schema object owner if existent
6193 * @attr: the schema attribute node being validated
6194 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006195 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006196 *
6197 * Validates a value against the given built-in type.
6198 * This one is intended to be used internally for validation
6199 * of schema attribute values during parsing of the schema.
6200 *
6201 * Returns 0 if the value is valid, a positive error code
6202 * number otherwise and -1 in case of an internal or API error.
6203 */
6204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006205xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006206 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006207 xmlAttrPtr attr,
6208 const xmlChar *value,
6209 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006210{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006211
6212 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006213
6214 /*
6215 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6216 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006217 */
6218 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006219 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6221 PERROR_INT("xmlSchemaPValAttrNodeValue",
6222 "the given type is not a built-in type");
6223 return (-1);
6224 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006225 switch (type->builtInType) {
6226 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006227 case XML_SCHEMAS_QNAME:
6228 case XML_SCHEMAS_ANYURI:
6229 case XML_SCHEMAS_TOKEN:
6230 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006231 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6232 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006233 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006234 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006235 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006236 "validation using the given type is not supported while "
6237 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006238 return (-1);
6239 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006240 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006241 /*
6242 * TODO: Should we use the S4S error codes instead?
6243 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006244 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006245 PERROR_INT("xmlSchemaPValAttrNodeValue",
6246 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006247 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006248 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006249 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006250 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6251 else
6252 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6253 xmlSchemaPSimpleTypeErr(pctxt,
6254 ret, ownerItem, (xmlNodePtr) attr,
6255 type, NULL, value, NULL, NULL, NULL);
6256 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006257 return (ret);
6258}
6259
6260/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006261 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006262 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006263 * @ctxt: a schema parser context
6264 * @ownerDes: the designation of the parent element
6265 * @ownerItem: the schema object owner if existent
6266 * @attr: the schema attribute node being validated
6267 * @type: the built-in type to be validated against
6268 * @value: the resulting value if any
6269 *
6270 * Extracts and validates a value against the given built-in type.
6271 * This one is intended to be used internally for validation
6272 * of schema attribute values during parsing of the schema.
6273 *
6274 * Returns 0 if the value is valid, a positive error code
6275 * number otherwise and -1 in case of an internal or API error.
6276 */
6277static int
6278xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006279 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006280 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 xmlSchemaTypePtr type,
6282 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 const xmlChar *val;
6285
6286 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 return (-1);
6288
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6290 if (value != NULL)
6291 *value = val;
6292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006293 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295}
6296
6297/**
6298 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 * @ctxt: a schema parser context
6301 * @node: the element node of the attribute
6302 * @ownerDes: the designation of the parent element
6303 * @ownerItem: the schema object owner if existent
6304 * @ownerElem: the owner element node
6305 * @name: the name of the schema attribute node
6306 * @type: the built-in type to be validated against
6307 * @value: the resulting value if any
6308 *
6309 * Extracts and validates a value against the given built-in type.
6310 * This one is intended to be used internally for validation
6311 * of schema attribute values during parsing of the schema.
6312 *
6313 * Returns 0 if the value is valid, a positive error code
6314 * number otherwise and -1 in case of an internal or API error.
6315 */
6316static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006317xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6318 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 xmlNodePtr ownerElem,
6320 const char *name,
6321 xmlSchemaTypePtr type,
6322 const xmlChar **value)
6323{
6324 xmlAttrPtr attr;
6325
6326 if ((ctxt == NULL) || (type == NULL)) {
6327 if (value != NULL)
6328 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006329 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 }
6331 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6332 if (value != NULL)
6333 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006335 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 "Internal error: xmlSchemaPValAttr, the given "
6337 "type '%s' is not a built-in type.\n",
6338 type->name, NULL);
6339 return (-1);
6340 }
6341 attr = xmlSchemaGetPropNode(ownerElem, name);
6342 if (attr == NULL) {
6343 if (value != NULL)
6344 *value = NULL;
6345 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006347 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 type, value));
6349}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006350
6351static int
6352xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006353 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006354 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006355 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006356 const xmlChar *namespaceName)
6357{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006358 /* TODO: Pointer comparison instead? */
6359 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006360 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006361 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006362 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006363 /*
6364 * Check if the referenced namespace was <import>ed.
6365 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006366 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006367 xmlSchemaSchemaRelationPtr rel;
6368
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006369 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006370 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006371 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006372 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006373 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006374 rel = rel->next;
6375 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006376 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006377 /*
6378 * No matching <import>ed namespace found.
6379 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006380 {
6381 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6382
6383 if (namespaceName == NULL)
6384 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6385 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6386 "References from this schema to components in no "
6387 "namespace are not allowed, since not indicated by an "
6388 "import statement", NULL, NULL);
6389 else
6390 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6391 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6392 "References from this schema to components in the "
6393 "namespace '%s' are not allowed, since not indicated by an "
6394 "import statement", namespaceName, NULL);
6395 }
6396 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006397}
6398
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006400 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006401 * @ctxt: a schema validation context
6402 * @schema: the schema being built
6403 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006404 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006405 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006406 * Parses attribute uses and attribute declarations and
6407 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006408 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006409static int
6410xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6411 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6412 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006413{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006414 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006415
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006416 while ((IS_SCHEMA((*child), "attribute")) ||
6417 (IS_SCHEMA((*child), "attributeGroup"))) {
6418 if (IS_SCHEMA((*child), "attribute")) {
6419 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6420 *list, parentType);
6421 } else {
6422 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6423 if ((item != NULL) && (hasRefs != NULL))
6424 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006425 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006426 if (item != NULL) {
6427 if (*list == NULL) {
6428 /* TODO: Customize grow factor. */
6429 *list = xmlSchemaItemListCreate();
6430 if (*list == NULL)
6431 return(-1);
6432 }
6433 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6434 return(-1);
6435 }
6436 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006437 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006438 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006439}
6440
6441/**
6442 * xmlSchemaParseAnnotation:
6443 * @ctxt: a schema validation context
6444 * @schema: the schema being built
6445 * @node: a subtree containing XML Schema informations
6446 *
6447 * parse a XML schema Attrribute declaration
6448 * *WARNING* this interface is highly subject to change
6449 *
William M. Bracke7091952004-05-11 15:09:58 +00006450 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006451 * 1 in case of success.
6452 */
6453static xmlSchemaAnnotPtr
6454xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006455 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006456{
6457 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 xmlNodePtr child = NULL;
6459 xmlAttrPtr attr;
6460 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006461
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 /*
6463 * INFO: S4S completed.
6464 */
6465 /*
6466 * id = ID
6467 * {any attributes with non-schema namespace . . .}>
6468 * Content: (appinfo | documentation)*
6469 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6471 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006472 if (needed)
6473 ret = xmlSchemaNewAnnot(ctxt, node);
6474 else
6475 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 attr = node->properties;
6477 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006478 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006479 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006480 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482
6483 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006484 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 }
6486 attr = attr->next;
6487 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006488 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 /*
6490 * And now for the children...
6491 */
6492 child = node->children;
6493 while (child != NULL) {
6494 if (IS_SCHEMA(child, "appinfo")) {
6495 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006497 * source = anyURI
6498 * {any attributes with non-schema namespace . . .}>
6499 * Content: ({any})*
6500 */
6501 attr = child->properties;
6502 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006503 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006505 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006506 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006507
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006508 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006509 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 }
6511 attr = attr->next;
6512 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006513 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 child = child->next;
6516 } else if (IS_SCHEMA(child, "documentation")) {
6517 /* TODO: make available the content of "documentation". */
6518 /*
6519 * source = anyURI
6520 * {any attributes with non-schema namespace . . .}>
6521 * Content: ({any})*
6522 */
6523 attr = child->properties;
6524 while (attr != NULL) {
6525 if (attr->ns == NULL) {
6526 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006527 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 }
6530 } else {
6531 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6532 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6533 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534
6535 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006536 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 }
6538 }
6539 attr = attr->next;
6540 }
6541 /*
6542 * Attribute "xml:lang".
6543 */
6544 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6545 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006546 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 child = child->next;
6549 } else {
6550 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 xmlSchemaPContentErr(ctxt,
6552 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006553 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006554 barked = 1;
6555 child = child->next;
6556 }
6557 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558
Daniel Veillard4255d502002-04-16 15:50:10 +00006559 return (ret);
6560}
6561
6562/**
6563 * xmlSchemaParseFacet:
6564 * @ctxt: a schema validation context
6565 * @schema: the schema being built
6566 * @node: a subtree containing XML Schema informations
6567 *
6568 * parse a XML schema Facet declaration
6569 * *WARNING* this interface is highly subject to change
6570 *
6571 * Returns the new type structure or NULL in case of error
6572 */
6573static xmlSchemaFacetPtr
6574xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006575 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006576{
6577 xmlSchemaFacetPtr facet;
6578 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006579 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006580
6581 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6582 return (NULL);
6583
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006584 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006585 if (facet == NULL) {
6586 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6587 return (NULL);
6588 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006589 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006590 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006591 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006592 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6593 "Facet %s has no value\n", node->name, NULL);
6594 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 return (NULL);
6596 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006597 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006599 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006602 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006604 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006607 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006609 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006610 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006612 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006615 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006617 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6619 } else if (IS_SCHEMA(node, "minLength")) {
6620 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6621 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6623 "Unknown facet type %s\n", node->name, NULL);
6624 xmlSchemaFreeFacet(facet);
6625 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006626 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006627 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006629 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6630 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6631 const xmlChar *fixed;
6632
6633 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6634 if (fixed != NULL) {
6635 if (xmlStrEqual(fixed, BAD_CAST "true"))
6636 facet->fixed = 1;
6637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006638 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006639 child = node->children;
6640
6641 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006642 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006643 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006644 }
6645 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006646 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6647 "Facet %s has unexpected child content\n",
6648 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 }
6650 return (facet);
6651}
6652
6653/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006654 * xmlSchemaParseWildcardNs:
6655 * @ctxt: a schema parser context
6656 * @wildc: the wildcard, already created
6657 * @node: a subtree containing XML Schema informations
6658 *
6659 * Parses the attribute "processContents" and "namespace"
6660 * of a xsd:anyAttribute and xsd:any.
6661 * *WARNING* this interface is highly subject to change
6662 *
6663 * Returns 0 if everything goes fine, a positive error code
6664 * if something is not valid and -1 if an internal error occurs.
6665 */
6666static int
6667xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006668 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006669 xmlSchemaWildcardPtr wildc,
6670 xmlNodePtr node)
6671{
6672 const xmlChar *pc, *ns, *dictnsItem;
6673 int ret = 0;
6674 xmlChar *nsItem;
6675 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6676 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677
Daniel Veillardc0826a72004-08-10 14:17:33 +00006678 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6679 if ((pc == NULL)
6680 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6681 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6682 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6683 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6684 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6685 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6686 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006687 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006688 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006689 NULL, node,
6690 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006691 NULL, NULL, NULL);
6692 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006693 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 }
6695 /*
6696 * Build the namespace constraints.
6697 */
6698 attr = xmlSchemaGetPropNode(node, "namespace");
6699 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006700 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006701 wildc->any = 1;
6702 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6703 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006705 return (-1);
6706 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006707 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006708 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006709 const xmlChar *end, *cur;
6710
6711 cur = ns;
6712 do {
6713 while (IS_BLANK_CH(*cur))
6714 cur++;
6715 end = cur;
6716 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6717 end++;
6718 if (end == cur)
6719 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006720 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006721 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6722 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006723 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006725 NULL, (xmlNodePtr) attr,
6726 NULL,
6727 "((##any | ##other) | List of (xs:anyURI | "
6728 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 nsItem, NULL, NULL, NULL);
6730 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6731 } else {
6732 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006733 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006734 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6735 dictnsItem = NULL;
6736 } else {
6737 /*
6738 * Validate the item (anyURI).
6739 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006740 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6742 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6743 }
6744 /*
6745 * Avoid dublicate namespaces.
6746 */
6747 tmp = wildc->nsSet;
6748 while (tmp != NULL) {
6749 if (dictnsItem == tmp->value)
6750 break;
6751 tmp = tmp->next;
6752 }
6753 if (tmp == NULL) {
6754 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6755 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 return (-1);
6758 }
6759 tmp->value = dictnsItem;
6760 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006761 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006762 wildc->nsSet = tmp;
6763 else
6764 lastNs->next = tmp;
6765 lastNs = tmp;
6766 }
6767
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006768 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006769 xmlFree(nsItem);
6770 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006771 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006772 }
6773 return (ret);
6774}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006775
6776static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006777xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6778 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006779 xmlNodePtr node,
6780 int minOccurs,
6781 int maxOccurs) {
6782
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006783 if ((maxOccurs == 0) && ( minOccurs == 0))
6784 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006785 if (maxOccurs != UNBOUNDED) {
6786 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 * TODO: Maybe we should better not create the particle,
6788 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006789 * content model.
6790 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006791 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006792 * 3.9.6 Schema Component Constraint: Particle Correct
6793 *
6794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006795 if (maxOccurs < 1) {
6796 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006797 * 2.2 {max occurs} must be greater than or equal to 1.
6798 */
6799 xmlSchemaPCustomAttrErr(ctxt,
6800 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006801 NULL, NULL,
6802 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006803 "The value must be greater than or equal to 1");
6804 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6805 } else if (minOccurs > maxOccurs) {
6806 /*
6807 * 2.1 {min occurs} must not be greater than {max occurs}.
6808 */
6809 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006810 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006811 NULL, NULL,
6812 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006813 "The value must not be greater than the value of 'maxOccurs'");
6814 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6815 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006817 return (0);
6818}
6819
Daniel Veillardc0826a72004-08-10 14:17:33 +00006820/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006821 * xmlSchemaParseAny:
6822 * @ctxt: a schema validation context
6823 * @schema: the schema being built
6824 * @node: a subtree containing XML Schema informations
6825 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006826 * Parsea a XML schema <any> element. A particle and wildcard
6827 * will be created (except if minOccurs==maxOccurs==0, in this case
6828 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006829 * *WARNING* this interface is highly subject to change
6830 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006831 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006832 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006833static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006834xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6835 xmlNodePtr node)
6836{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006837 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006838 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006839 xmlSchemaWildcardPtr wild;
6840 int min, max;
6841 xmlAttrPtr attr;
6842 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006843
6844 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6845 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006846 /*
6847 * Check for illegal attributes.
6848 */
6849 attr = node->properties;
6850 while (attr != NULL) {
6851 if (attr->ns == NULL) {
6852 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6853 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6854 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6855 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6856 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006858 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006859 }
6860 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006861 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006862 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006863 }
6864 attr = attr->next;
6865 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006866 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006867 /*
6868 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006869 */
6870 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6871 "(xs:nonNegativeInteger | unbounded)");
6872 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6873 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006874 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6875 /*
6876 * Create & parse the wildcard.
6877 */
6878 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6879 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006880 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006881 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006882 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006883 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006885 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006886 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006887 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006889 }
6890 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006891 xmlSchemaPContentErr(ctxt,
6892 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006893 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006894 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006895 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006896 /*
6897 * No component if minOccurs==maxOccurs==0.
6898 */
6899 if ((min == 0) && (max == 0)) {
6900 /* Don't free the wildcard, since it's already on the list. */
6901 return (NULL);
6902 }
6903 /*
6904 * Create the particle.
6905 */
6906 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6907 if (particle == NULL)
6908 return (NULL);
6909 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006910 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006911
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006912 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006913}
6914
6915/**
6916 * xmlSchemaParseNotation:
6917 * @ctxt: a schema validation context
6918 * @schema: the schema being built
6919 * @node: a subtree containing XML Schema informations
6920 *
6921 * parse a XML schema Notation declaration
6922 *
6923 * Returns the new structure or NULL in case of error
6924 */
6925static xmlSchemaNotationPtr
6926xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006927 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006928{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006929 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 xmlSchemaNotationPtr ret;
6931 xmlNodePtr child = NULL;
6932
6933 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6934 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006935 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006936 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006937 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6938 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006939 return (NULL);
6940 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006941 ret = xmlSchemaAddNotation(ctxt, schema, name,
6942 ctxt->targetNamespace, node);
6943 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006944 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006945 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006946
6947 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006948 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006949 child = child->next;
6950 }
6951
Daniel Veillard4255d502002-04-16 15:50:10 +00006952 child = node->children;
6953 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006954 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006955 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006956 }
6957 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006958 xmlSchemaPContentErr(ctxt,
6959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006960 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006961 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 }
6963
6964 return (ret);
6965}
6966
6967/**
6968 * xmlSchemaParseAnyAttribute:
6969 * @ctxt: a schema validation context
6970 * @schema: the schema being built
6971 * @node: a subtree containing XML Schema informations
6972 *
6973 * parse a XML schema AnyAttrribute declaration
6974 * *WARNING* this interface is highly subject to change
6975 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006976 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006977 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006978static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006979xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6980 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006981{
Daniel Veillard3646d642004-06-02 19:19:14 +00006982 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006983 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006984 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006985
6986 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6987 return (NULL);
6988
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006989 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6990 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006991 if (ret == NULL) {
6992 return (NULL);
6993 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006994 /*
6995 * Check for illegal attributes.
6996 */
6997 attr = node->properties;
6998 while (attr != NULL) {
6999 if (attr->ns == NULL) {
7000 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7001 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7002 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007003 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007005 }
7006 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007007 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007008 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007009 }
7010 attr = attr->next;
7011 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007012 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007013 /*
7014 * Parse the namespace list.
7015 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007016 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007017 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007018 /*
7019 * And now for the children...
7020 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007021 child = node->children;
7022 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007023 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 }
7026 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007027 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007028 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007029 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007030 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007031 }
7032
7033 return (ret);
7034}
7035
7036
7037/**
7038 * xmlSchemaParseAttribute:
7039 * @ctxt: a schema validation context
7040 * @schema: the schema being built
7041 * @node: a subtree containing XML Schema informations
7042 *
7043 * parse a XML schema Attrribute declaration
7044 * *WARNING* this interface is highly subject to change
7045 *
William M. Bracke7091952004-05-11 15:09:58 +00007046 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007048static xmlSchemaBasicItemPtr
7049xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7050 xmlSchemaPtr schema,
7051 xmlNodePtr node,
7052 xmlSchemaItemListPtr uses,
7053 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007054{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007055 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7056 xmlSchemaAttributeUsePtr use = NULL;
7057 xmlNodePtr child = NULL;
7058 xmlAttrPtr attr;
7059 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7060 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7061 int nberrors, hasForm = 0, defValueType = 0;
7062
7063#define WXS_ATTR_DEF_VAL_DEFAULT 1
7064#define WXS_ATTR_DEF_VAL_FIXED 2
7065
7066 /*
7067 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7068 */
7069
7070 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7071 return (NULL);
7072 attr = xmlSchemaGetPropNode(node, "ref");
7073 if (attr != NULL) {
7074 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7075 NULL, attr, &tmpNs, &tmpName) != 0) {
7076 return (NULL);
7077 }
7078 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7079 return(NULL);
7080 isRef = 1;
7081 }
7082 nberrors = pctxt->nberrors;
7083 /*
7084 * Check for illegal attributes.
7085 */
7086 attr = node->properties;
7087 while (attr != NULL) {
7088 if (attr->ns == NULL) {
7089 if (isRef) {
7090 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7091 xmlSchemaPValAttrNodeID(pctxt, attr);
7092 goto attr_next;
7093 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7094 goto attr_next;
7095 }
7096 } else {
7097 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7098 goto attr_next;
7099 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7100 xmlSchemaPValAttrNodeID(pctxt, attr);
7101 goto attr_next;
7102 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7103 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7104 attr, &tmpNs, &tmpName);
7105 goto attr_next;
7106 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7107 /*
7108 * Evaluate the target namespace
7109 */
7110 hasForm = 1;
7111 attrValue = xmlSchemaGetNodeContent(pctxt,
7112 (xmlNodePtr) attr);
7113 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7114 ns = pctxt->targetNamespace;
7115 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7116 {
7117 xmlSchemaPSimpleTypeErr(pctxt,
7118 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7119 NULL, (xmlNodePtr) attr,
7120 NULL, "(qualified | unqualified)",
7121 attrValue, NULL, NULL, NULL);
7122 }
7123 goto attr_next;
7124 }
7125 }
7126 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7127
7128 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7129 /* TODO: Maybe we need to normalize the value beforehand. */
7130 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7131 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7132 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7133 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7134 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7135 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7136 else {
7137 xmlSchemaPSimpleTypeErr(pctxt,
7138 XML_SCHEMAP_INVALID_ATTR_USE,
7139 NULL, (xmlNodePtr) attr,
7140 NULL, "(optional | prohibited | required)",
7141 attrValue, NULL, NULL, NULL);
7142 }
7143 goto attr_next;
7144 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7145 /*
7146 * 3.2.3 : 1
7147 * default and fixed must not both be present.
7148 */
7149 if (defValue) {
7150 xmlSchemaPMutualExclAttrErr(pctxt,
7151 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7152 NULL, attr, "default", "fixed");
7153 } else {
7154 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7155 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7156 }
7157 goto attr_next;
7158 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7159 /*
7160 * 3.2.3 : 1
7161 * default and fixed must not both be present.
7162 */
7163 if (defValue) {
7164 xmlSchemaPMutualExclAttrErr(pctxt,
7165 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7166 NULL, attr, "default", "fixed");
7167 } else {
7168 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7169 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7170 }
7171 goto attr_next;
7172 }
7173 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7174 goto attr_next;
7175
7176 xmlSchemaPIllegalAttrErr(pctxt,
7177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7178
7179attr_next:
7180 attr = attr->next;
7181 }
7182 /*
7183 * 3.2.3 : 2
7184 * If default and use are both present, use must have
7185 * the actual value optional.
7186 */
7187 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7188 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7189 xmlSchemaPSimpleTypeErr(pctxt,
7190 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7191 NULL, node, NULL,
7192 "(optional | prohibited | required)", NULL,
7193 "The value of the attribute 'use' must be 'optional' "
7194 "if the attribute 'default' is present",
7195 NULL, NULL);
7196 }
7197 /*
7198 * We want correct attributes.
7199 */
7200 if (nberrors != pctxt->nberrors)
7201 return(NULL);
7202 if (! isRef) {
7203 xmlSchemaAttributePtr attrDecl;
7204
7205 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7206 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7207 ns = pctxt->targetNamespace;
7208 /*
7209 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7210 * TODO: Move this to the component layer.
7211 */
7212 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7213 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7214 XML_SCHEMAP_NO_XSI,
7215 node, NULL,
7216 "The target namespace must not match '%s'",
7217 xmlSchemaInstanceNs, NULL);
7218 }
7219 attr = xmlSchemaGetPropNode(node, "name");
7220 if (attr == NULL) {
7221 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7222 NULL, node, "name", NULL);
7223 return (NULL);
7224 }
7225 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7226 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7227 return (NULL);
7228 }
7229 /*
7230 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7231 * TODO: Move this to the component layer.
7232 */
7233 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7234 xmlSchemaPSimpleTypeErr(pctxt,
7235 XML_SCHEMAP_NO_XMLNS,
7236 NULL, (xmlNodePtr) attr,
7237 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7238 "The value of the attribute must not match 'xmlns'",
7239 NULL, NULL);
7240 return (NULL);
7241 }
7242 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7243 goto check_children;
7244 /*
7245 * Create the attribute use component.
7246 */
7247 use = xmlSchemaAddAttributeUse(pctxt, node);
7248 if (use == NULL)
7249 return(NULL);
7250 use->occurs = occurs;
7251 /*
7252 * Create the attribute declaration.
7253 */
7254 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7255 if (attrDecl == NULL)
7256 return (NULL);
7257 if (tmpName != NULL) {
7258 attrDecl->typeName = tmpName;
7259 attrDecl->typeNs = tmpNs;
7260 }
7261 use->attrDecl = attrDecl;
7262 /*
7263 * Value constraint.
7264 */
7265 if (defValue != NULL) {
7266 attrDecl->defValue = defValue;
7267 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7268 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7269 }
7270 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7271 xmlSchemaQNameRefPtr ref;
7272
7273 /*
7274 * Create the attribute use component.
7275 */
7276 use = xmlSchemaAddAttributeUse(pctxt, node);
7277 if (use == NULL)
7278 return(NULL);
7279 /*
7280 * We need to resolve the reference at later stage.
7281 */
7282 WXS_ADD_PENDING(pctxt, use);
7283 use->occurs = occurs;
7284 /*
7285 * Create a QName reference to the attribute declaration.
7286 */
7287 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7288 tmpName, tmpNs);
7289 if (ref == NULL)
7290 return(NULL);
7291 /*
7292 * Assign the reference. This will be substituted for the
7293 * referenced attribute declaration when the QName is resolved.
7294 */
7295 use->attrDecl = WXS_ATTR_CAST ref;
7296 /*
7297 * Value constraint.
7298 */
7299 if (defValue != NULL)
7300 use->defValue = defValue;
7301 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7302 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7303 }
7304
7305check_children:
7306 /*
7307 * And now for the children...
7308 */
7309 child = node->children;
7310 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7311 xmlSchemaAttributeUseProhibPtr prohib;
7312
7313 if (IS_SCHEMA(child, "annotation")) {
7314 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7315 child = child->next;
7316 }
7317 if (child != NULL) {
7318 xmlSchemaPContentErr(pctxt,
7319 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7320 NULL, node, child, NULL,
7321 "(annotation?)");
7322 }
7323 /*
7324 * Check for pointlessness of attribute prohibitions.
7325 */
7326 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7327 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7328 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7329 node, NULL,
7330 "Skipping attribute use prohibition, since it is "
7331 "pointless inside an <attributeGroup>",
7332 NULL, NULL, NULL);
7333 return(NULL);
7334 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7335 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7336 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7337 node, NULL,
7338 "Skipping attribute use prohibition, since it is "
7339 "pointless when extending a type",
7340 NULL, NULL, NULL);
7341 return(NULL);
7342 }
7343 if (! isRef) {
7344 tmpName = name;
7345 tmpNs = ns;
7346 }
7347 /*
7348 * Check for duplicate attribute prohibitions.
7349 */
7350 if (uses) {
7351 int i;
7352
7353 for (i = 0; i < uses->nbItems; i++) {
7354 use = uses->items[i];
7355 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7356 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7357 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7358 {
7359 xmlChar *str = NULL;
7360
7361 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7362 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7363 node, NULL,
7364 "Skipping duplicate attribute use prohibition '%s'",
7365 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7366 NULL, NULL);
7367 FREE_AND_NULL(str)
7368 return(NULL);
7369 }
7370 }
7371 }
7372 /*
7373 * Create the attribute prohibition helper component.
7374 */
7375 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7376 if (prohib == NULL)
7377 return(NULL);
7378 prohib->node = node;
7379 prohib->name = tmpName;
7380 prohib->targetNamespace = tmpNs;
7381 if (isRef) {
7382 /*
7383 * We need at least to resolve to the attribute declaration.
7384 */
7385 WXS_ADD_PENDING(pctxt, prohib);
7386 }
7387 return(WXS_BASIC_CAST prohib);
7388 } else {
7389 if (IS_SCHEMA(child, "annotation")) {
7390 /*
7391 * TODO: Should this go into the attr decl?
7392 */
7393 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7394 child = child->next;
7395 }
7396 if (isRef) {
7397 if (child != NULL) {
7398 if (IS_SCHEMA(child, "simpleType"))
7399 /*
7400 * 3.2.3 : 3.2
7401 * If ref is present, then all of <simpleType>,
7402 * form and type must be absent.
7403 */
7404 xmlSchemaPContentErr(pctxt,
7405 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7406 NULL, node, child, NULL,
7407 "(annotation?)");
7408 else
7409 xmlSchemaPContentErr(pctxt,
7410 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7411 NULL, node, child, NULL,
7412 "(annotation?)");
7413 }
7414 } else {
7415 if (IS_SCHEMA(child, "simpleType")) {
7416 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7417 /*
7418 * 3.2.3 : 4
7419 * type and <simpleType> must not both be present.
7420 */
7421 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7422 NULL, node, child,
7423 "The attribute 'type' and the <simpleType> child "
7424 "are mutually exclusive", NULL);
7425 } else
7426 WXS_ATTRUSE_TYPEDEF(use) =
7427 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7428 child = child->next;
7429 }
7430 if (child != NULL)
7431 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7432 NULL, node, child, NULL,
7433 "(annotation?, simpleType?)");
7434 }
7435 }
7436 return (WXS_BASIC_CAST use);
7437}
7438
7439
7440static xmlSchemaAttributePtr
7441xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7442 xmlSchemaPtr schema,
7443 xmlNodePtr node)
7444{
7445 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007446 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007447 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007448 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007449
7450 /*
7451 * Note that the w3c spec assumes the schema to be validated with schema
7452 * for schemas beforehand.
7453 *
7454 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007455 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007456 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7457 return (NULL);
7458 /*
7459 * 3.2.3 : 3.1
7460 * One of ref or name must be present, but not both
7461 */
7462 attr = xmlSchemaGetPropNode(node, "name");
7463 if (attr == NULL) {
7464 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7465 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007466 return (NULL);
7467 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007468 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7469 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7470 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007471 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007472 /*
7473 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7474 * TODO: Move this to the component layer.
7475 */
7476 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7477 xmlSchemaPSimpleTypeErr(pctxt,
7478 XML_SCHEMAP_NO_XMLNS,
7479 NULL, (xmlNodePtr) attr,
7480 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7481 "The value of the attribute must not match 'xmlns'",
7482 NULL, NULL);
7483 return (NULL);
7484 }
7485 /*
7486 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7487 * TODO: Move this to the component layer.
7488 * Or better leave it here and add it to the component layer
7489 * if we have a schema construction API.
7490 */
7491 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7492 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7493 XML_SCHEMAP_NO_XSI, node, NULL,
7494 "The target namespace must not match '%s'",
7495 xmlSchemaInstanceNs, NULL);
7496 }
7497
7498 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7499 pctxt->targetNamespace, node, 1);
7500 if (ret == NULL)
7501 return (NULL);
7502 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7503
7504 /*
7505 * Check for illegal attributes.
7506 */
7507 attr = node->properties;
7508 while (attr != NULL) {
7509 if (attr->ns == NULL) {
7510 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7511 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7512 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7513 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7514 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7515 {
7516 xmlSchemaPIllegalAttrErr(pctxt,
7517 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7518 }
7519 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7520 xmlSchemaPIllegalAttrErr(pctxt,
7521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7522 }
7523 attr = attr->next;
7524 }
7525 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7526 node, "type", &ret->typeNs, &ret->typeName);
7527
7528 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007530 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007531 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007532 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 if (ret->defValue != NULL)
7534 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007536 * Attribute "default".
7537 */
7538 attr = xmlSchemaGetPropNode(node, "default");
7539 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007542 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 */
7544 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007545 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7546 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007548 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 /*
7551 * And now for the children...
7552 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007553 child = node->children;
7554 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007555 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007558 if (IS_SCHEMA(child, "simpleType")) {
7559 if (ret->typeName != NULL) {
7560 /*
7561 * 3.2.3 : 4
7562 * type and <simpleType> must not both be present.
7563 */
7564 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7565 NULL, node, child,
7566 "The attribute 'type' and the <simpleType> child "
7567 "are mutually exclusive", NULL);
7568 } else
7569 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7570 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007572 if (child != NULL)
7573 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7574 NULL, node, child, NULL,
7575 "(annotation?, simpleType?)");
7576
Daniel Veillard4255d502002-04-16 15:50:10 +00007577 return (ret);
7578}
7579
7580/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007581 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 * @ctxt: a schema validation context
7583 * @schema: the schema being built
7584 * @node: a subtree containing XML Schema informations
7585 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007586 * Parse an attribute group definition reference.
7587 * Note that a reference to an attribute group does not
7588 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007589 * *WARNING* this interface is highly subject to change
7590 *
7591 * Returns the attribute group or NULL in case of error.
7592 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007593static xmlSchemaQNameRefPtr
7594xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7595 xmlSchemaPtr schema,
7596 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007597{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007598 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007599 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007600 xmlAttrPtr attr;
7601 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007602
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007603 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007605
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007607 if (attr == NULL) {
7608 xmlSchemaPMissingAttrErr(pctxt,
7609 XML_SCHEMAP_S4S_ATTR_MISSING,
7610 NULL, node, "ref", NULL);
7611 return (NULL);
7612 }
7613 xmlSchemaPValAttrNodeQName(pctxt, schema,
7614 NULL, attr, &refNs, &ref);
7615 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7616 return(NULL);
7617
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007618 /*
7619 * Check for illegal attributes.
7620 */
7621 attr = node->properties;
7622 while (attr != NULL) {
7623 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007624 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007626 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007627 xmlSchemaPIllegalAttrErr(pctxt,
7628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007629 }
7630 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007631 xmlSchemaPIllegalAttrErr(pctxt,
7632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007633 }
7634 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007636 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007637 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7638
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007639 /*
7640 * And now for the children...
7641 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007642 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007643 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007644 /*
7645 * TODO: We do not have a place to store the annotation, do we?
7646 */
7647 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007648 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007649 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007650 if (child != NULL) {
7651 xmlSchemaPContentErr(pctxt,
7652 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7653 NULL, node, child, NULL,
7654 "(annotation?)");
7655 }
7656
7657 /*
7658 * Handle attribute group redefinitions.
7659 */
7660 if (pctxt->isRedefine && pctxt->redef &&
7661 (pctxt->redef->item->type ==
7662 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7663 (ref == pctxt->redef->refName) &&
7664 (refNs == pctxt->redef->refTargetNs))
7665 {
7666 /*
7667 * SPEC src-redefine:
7668 * (7.1) "If it has an <attributeGroup> among its contents
7669 * the ·actual value· of whose ref [attribute] is the same
7670 * as the ·actual value· of its own name attribute plus
7671 * target namespace, then it must have exactly one such group."
7672 */
7673 if (pctxt->redefCounter != 0) {
7674 xmlChar *str = NULL;
7675
7676 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7677 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7678 "The redefining attribute group definition "
7679 "'%s' must not contain more than one "
7680 "reference to the redefined definition",
7681 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7682 FREE_AND_NULL(str);
7683 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007684 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007685 pctxt->redefCounter++;
7686 /*
7687 * URGENT TODO: How to ensure that the reference will not be
7688 * handled by the normal component resolution mechanism?
7689 */
7690 ret = xmlSchemaNewQNameRef(pctxt,
7691 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7692 if (ret == NULL)
7693 return(NULL);
7694 ret->node = node;
7695 pctxt->redef->reference = WXS_BASIC_CAST ret;
7696 } else {
7697 /*
7698 * Create a QName-reference helper component. We will substitute this
7699 * component for the attribute uses of the referenced attribute group
7700 * definition.
7701 */
7702 ret = xmlSchemaNewQNameRef(pctxt,
7703 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7704 if (ret == NULL)
7705 return(NULL);
7706 ret->node = node;
7707 /* Add to pending items, to be able to resolve the reference. */
7708 WXS_ADD_PENDING(pctxt, ret);
7709 }
7710 return (ret);
7711}
7712
7713/**
7714 * xmlSchemaParseAttributeGroupDefinition:
7715 * @pctxt: a schema validation context
7716 * @schema: the schema being built
7717 * @node: a subtree containing XML Schema informations
7718 *
7719 * parse a XML schema Attribute Group declaration
7720 * *WARNING* this interface is highly subject to change
7721 *
7722 * Returns the attribute group definition or NULL in case of error.
7723 */
7724static xmlSchemaAttributeGroupPtr
7725xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7726 xmlSchemaPtr schema,
7727 xmlNodePtr node)
7728{
7729 const xmlChar *name;
7730 xmlSchemaAttributeGroupPtr ret;
7731 xmlNodePtr child = NULL;
7732 xmlAttrPtr attr;
7733 int hasRefs = 0;
7734
7735 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7736 return (NULL);
7737
7738 attr = xmlSchemaGetPropNode(node, "name");
7739 if (attr == NULL) {
7740 xmlSchemaPMissingAttrErr(pctxt,
7741 XML_SCHEMAP_S4S_ATTR_MISSING,
7742 NULL, node, "name", NULL);
7743 return (NULL);
7744 }
7745 /*
7746 * The name is crucial, exit if invalid.
7747 */
7748 if (xmlSchemaPValAttrNode(pctxt,
7749 NULL, attr,
7750 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7751 return (NULL);
7752 }
7753 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7754 name, pctxt->targetNamespace, node);
7755 if (ret == NULL)
7756 return (NULL);
7757 /*
7758 * Check for illegal attributes.
7759 */
7760 attr = node->properties;
7761 while (attr != NULL) {
7762 if (attr->ns == NULL) {
7763 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7764 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7765 {
7766 xmlSchemaPIllegalAttrErr(pctxt,
7767 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7768 }
7769 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7770 xmlSchemaPIllegalAttrErr(pctxt,
7771 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7772 }
7773 attr = attr->next;
7774 }
7775 /* Attribute ID */
7776 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7777 /*
7778 * And now for the children...
7779 */
7780 child = node->children;
7781 if (IS_SCHEMA(child, "annotation")) {
7782 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7783 child = child->next;
7784 }
7785 /*
7786 * Parse contained attribute decls/refs.
7787 */
7788 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7789 (xmlSchemaItemListPtr *) &(ret->attrUses),
7790 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7791 return(NULL);
7792 if (hasRefs)
7793 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7794 /*
7795 * Parse the attribute wildcard.
7796 */
7797 if (IS_SCHEMA(child, "anyAttribute")) {
7798 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7799 schema, child);
7800 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007801 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007802 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007803 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007804 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007805 NULL, node, child, NULL,
7806 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007807 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007808 return (ret);
7809}
7810
7811/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007812 * xmlSchemaPValAttrFormDefault:
7813 * @value: the value
7814 * @flags: the flags to be modified
7815 * @flagQualified: the specific flag for "qualified"
7816 *
7817 * Returns 0 if the value is valid, 1 otherwise.
7818 */
7819static int
7820xmlSchemaPValAttrFormDefault(const xmlChar *value,
7821 int *flags,
7822 int flagQualified)
7823{
7824 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7825 if ((*flags & flagQualified) == 0)
7826 *flags |= flagQualified;
7827 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007828 return (1);
7829
William M. Brack2f2a6632004-08-20 23:09:47 +00007830 return (0);
7831}
7832
7833/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007834 * xmlSchemaPValAttrBlockFinal:
7835 * @value: the value
7836 * @flags: the flags to be modified
7837 * @flagAll: the specific flag for "#all"
7838 * @flagExtension: the specific flag for "extension"
7839 * @flagRestriction: the specific flag for "restriction"
7840 * @flagSubstitution: the specific flag for "substitution"
7841 * @flagList: the specific flag for "list"
7842 * @flagUnion: the specific flag for "union"
7843 *
7844 * Validates the value of the attribute "final" and "block". The value
7845 * is converted into the specified flag values and returned in @flags.
7846 *
7847 * Returns 0 if the value is valid, 1 otherwise.
7848 */
7849
7850static int
7851xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007852 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007853 int flagAll,
7854 int flagExtension,
7855 int flagRestriction,
7856 int flagSubstitution,
7857 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007858 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007859{
7860 int ret = 0;
7861
7862 /*
7863 * TODO: This does not check for dublicate entries.
7864 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007865 if ((flags == NULL) || (value == NULL))
7866 return (-1);
7867 if (value[0] == 0)
7868 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 if (xmlStrEqual(value, BAD_CAST "#all")) {
7870 if (flagAll != -1)
7871 *flags |= flagAll;
7872 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 if (flagExtension != -1)
7874 *flags |= flagExtension;
7875 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007876 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007878 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007879 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007881 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007882 *flags |= flagUnion;
7883 }
7884 } else {
7885 const xmlChar *end, *cur = value;
7886 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007887
Daniel Veillardc0826a72004-08-10 14:17:33 +00007888 do {
7889 while (IS_BLANK_CH(*cur))
7890 cur++;
7891 end = cur;
7892 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7893 end++;
7894 if (end == cur)
7895 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007896 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007897 if (xmlStrEqual(item, BAD_CAST "extension")) {
7898 if (flagExtension != -1) {
7899 if ((*flags & flagExtension) == 0)
7900 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007902 ret = 1;
7903 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7904 if (flagRestriction != -1) {
7905 if ((*flags & flagRestriction) == 0)
7906 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 ret = 1;
7909 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7910 if (flagSubstitution != -1) {
7911 if ((*flags & flagSubstitution) == 0)
7912 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007913 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007914 ret = 1;
7915 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7916 if (flagList != -1) {
7917 if ((*flags & flagList) == 0)
7918 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007920 ret = 1;
7921 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7922 if (flagUnion != -1) {
7923 if ((*flags & flagUnion) == 0)
7924 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007925 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007926 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007928 ret = 1;
7929 if (item != NULL)
7930 xmlFree(item);
7931 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 } while ((ret == 0) && (*cur != 0));
7933 }
7934
Daniel Veillardc0826a72004-08-10 14:17:33 +00007935 return (ret);
7936}
7937
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007938static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007939xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007940 xmlSchemaIDCPtr idc,
7941 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007942 xmlAttrPtr attr,
7943 int isField)
7944{
7945 xmlNodePtr node;
7946
7947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007948 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007949 * Schema Component Constraint: Selector Value OK
7950 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007951 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007952 * in [XPath].
7953 */
7954 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007955 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007956 XML_SCHEMAP_INTERNAL,
7957 "Internal error: xmlSchemaCheckCSelectorXPath, "
7958 "the selector is not specified.\n", NULL, NULL);
7959 return (-1);
7960 }
7961 if (attr == NULL)
7962 node = idc->node;
7963 else
7964 node = (xmlNodePtr) attr;
7965 if (selector->xpath == NULL) {
7966 xmlSchemaPCustomErr(ctxt,
7967 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007969 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007970 "The XPath expression of the selector is not valid", NULL);
7971 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7972 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007973 const xmlChar **nsArray = NULL;
7974 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007975 /*
7976 * Compile the XPath expression.
7977 */
7978 /*
7979 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007980 * TODO: Call xmlPatterncompile with different options for selector/
7981 * field.
7982 */
7983 nsList = xmlGetNsList(attr->doc, attr->parent);
7984 /*
7985 * Build an array of prefixes and namespaces.
7986 */
7987 if (nsList != NULL) {
7988 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007989
7990 for (i = 0; nsList[i] != NULL; i++)
7991 count++;
7992
7993 nsArray = (const xmlChar **) xmlMalloc(
7994 (count * 2 + 1) * sizeof(const xmlChar *));
7995 if (nsArray == NULL) {
7996 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7997 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00007998 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007999 return (-1);
8000 }
8001 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008002 nsArray[2 * i] = nsList[i]->href;
8003 nsArray[2 * i + 1] = nsList[i]->prefix;
8004 }
8005 nsArray[count * 2] = NULL;
8006 xmlFree(nsList);
8007 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008008 /*
8009 * TODO: Differentiate between "selector" and "field".
8010 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008011 if (isField)
8012 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008013 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008014 else
8015 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008016 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008017 if (nsArray != NULL)
8018 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008019
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008020 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008021 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008022 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008023 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008024 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008025 "The XPath expression '%s' could not be "
8026 "compiled", selector->xpath);
8027 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008028 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008029 }
8030 return (0);
8031}
8032
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033#define ADD_ANNOTATION(annot) \
8034 xmlSchemaAnnotPtr cur = item->annot; \
8035 if (item->annot == NULL) { \
8036 item->annot = annot; \
8037 return (annot); \
8038 } \
8039 cur = item->annot; \
8040 if (cur->next != NULL) { \
8041 cur = cur->next; \
8042 } \
8043 cur->next = annot;
8044
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008045/**
8046 * xmlSchemaAssignAnnotation:
8047 * @item: the schema component
8048 * @annot: the annotation
8049 *
8050 * Adds the annotation to the given schema component.
8051 *
8052 * Returns the given annotaion.
8053 */
8054static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008055xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8056 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008057{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008058 if ((annItem == NULL) || (annot == NULL))
8059 return (NULL);
8060 switch (annItem->type) {
8061 case XML_SCHEMA_TYPE_ELEMENT: {
8062 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8063 ADD_ANNOTATION(annot)
8064 }
8065 break;
8066 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8067 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8068 ADD_ANNOTATION(annot)
8069 }
8070 break;
8071 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8072 case XML_SCHEMA_TYPE_ANY: {
8073 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8074 ADD_ANNOTATION(annot)
8075 }
8076 break;
8077 case XML_SCHEMA_TYPE_PARTICLE:
8078 case XML_SCHEMA_TYPE_IDC_KEY:
8079 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008081 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8082 ADD_ANNOTATION(annot)
8083 }
8084 break;
8085 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8086 xmlSchemaAttributeGroupPtr item =
8087 (xmlSchemaAttributeGroupPtr) annItem;
8088 ADD_ANNOTATION(annot)
8089 }
8090 break;
8091 case XML_SCHEMA_TYPE_NOTATION: {
8092 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8093 ADD_ANNOTATION(annot)
8094 }
8095 break;
8096 case XML_SCHEMA_FACET_MININCLUSIVE:
8097 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8098 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8099 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8100 case XML_SCHEMA_FACET_TOTALDIGITS:
8101 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8102 case XML_SCHEMA_FACET_PATTERN:
8103 case XML_SCHEMA_FACET_ENUMERATION:
8104 case XML_SCHEMA_FACET_WHITESPACE:
8105 case XML_SCHEMA_FACET_LENGTH:
8106 case XML_SCHEMA_FACET_MAXLENGTH:
8107 case XML_SCHEMA_FACET_MINLENGTH: {
8108 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8109 ADD_ANNOTATION(annot)
8110 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008111 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008112 case XML_SCHEMA_TYPE_SIMPLE:
8113 case XML_SCHEMA_TYPE_COMPLEX: {
8114 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8115 ADD_ANNOTATION(annot)
8116 }
8117 break;
8118 case XML_SCHEMA_TYPE_GROUP: {
8119 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8120 ADD_ANNOTATION(annot)
8121 }
8122 break;
8123 case XML_SCHEMA_TYPE_SEQUENCE:
8124 case XML_SCHEMA_TYPE_CHOICE:
8125 case XML_SCHEMA_TYPE_ALL: {
8126 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8127 ADD_ANNOTATION(annot)
8128 }
8129 break;
8130 default:
8131 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008132 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008133 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008134 "Internal error: xmlSchemaAddAnnotation, "
8135 "The item is not a annotated schema component", NULL);
8136 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008137 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008138 return (annot);
8139}
8140
8141/**
8142 * xmlSchemaParseIDCSelectorAndField:
8143 * @ctxt: a schema validation context
8144 * @schema: the schema being built
8145 * @node: a subtree containing XML Schema informations
8146 *
8147 * Parses a XML Schema identity-contraint definition's
8148 * <selector> and <field> elements.
8149 *
8150 * Returns the parsed identity-constraint definition.
8151 */
8152static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008153xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008154 xmlSchemaPtr schema,
8155 xmlSchemaIDCPtr idc,
8156 xmlNodePtr node,
8157 int isField)
8158{
8159 xmlSchemaIDCSelectPtr item;
8160 xmlNodePtr child = NULL;
8161 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008163 /*
8164 * Check for illegal attributes.
8165 */
8166 attr = node->properties;
8167 while (attr != NULL) {
8168 if (attr->ns == NULL) {
8169 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8170 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008171 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008173 }
8174 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008176 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008177 }
8178 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008179 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008180 /*
8181 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008182 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008183 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8184 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 xmlSchemaPErrMemory(ctxt,
8186 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008187 NULL);
8188 return (NULL);
8189 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008190 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008191 /*
8192 * Attribute "xpath" (mandatory).
8193 */
8194 attr = xmlSchemaGetPropNode(node, "xpath");
8195 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 xmlSchemaPMissingAttrErr(ctxt,
8197 XML_SCHEMAP_S4S_ATTR_MISSING,
8198 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008199 "name", NULL);
8200 } else {
8201 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8202 /*
8203 * URGENT TODO: "field"s have an other syntax than "selector"s.
8204 */
8205
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008206 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8207 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008208 xmlSchemaPErr(ctxt,
8209 (xmlNodePtr) attr,
8210 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008211 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008212 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008213 NULL, NULL);
8214 }
8215
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008216 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008217 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008218 /*
8219 * And now for the children...
8220 */
8221 child = node->children;
8222 if (IS_SCHEMA(child, "annotation")) {
8223 /*
8224 * Add the annotation to the parent IDC.
8225 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008227 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008228 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008230 if (child != NULL) {
8231 xmlSchemaPContentErr(ctxt,
8232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008233 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008234 NULL, "(annotation?)");
8235 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008237 return (item);
8238}
8239
8240/**
8241 * xmlSchemaParseIDC:
8242 * @ctxt: a schema validation context
8243 * @schema: the schema being built
8244 * @node: a subtree containing XML Schema informations
8245 *
8246 * Parses a XML Schema identity-contraint definition.
8247 *
8248 * Returns the parsed identity-constraint definition.
8249 */
8250static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008252 xmlSchemaPtr schema,
8253 xmlNodePtr node,
8254 xmlSchemaTypeType idcCategory,
8255 const xmlChar *targetNamespace)
8256{
8257 xmlSchemaIDCPtr item = NULL;
8258 xmlNodePtr child = NULL;
8259 xmlAttrPtr attr;
8260 const xmlChar *name = NULL;
8261 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008262
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008263 /*
8264 * Check for illegal attributes.
8265 */
8266 attr = node->properties;
8267 while (attr != NULL) {
8268 if (attr->ns == NULL) {
8269 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8270 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8271 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8272 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008274 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008275 }
8276 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008277 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008279 }
8280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008281 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008282 /*
8283 * Attribute "name" (mandatory).
8284 */
8285 attr = xmlSchemaGetPropNode(node, "name");
8286 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 xmlSchemaPMissingAttrErr(ctxt,
8288 XML_SCHEMAP_S4S_ATTR_MISSING,
8289 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008290 "name", NULL);
8291 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008292 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008293 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008294 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8295 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008296 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008297 /* Create the component. */
8298 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8299 idcCategory, node);
8300 if (item == NULL)
8301 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008302
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008303 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8305 /*
8306 * Attribute "refer" (mandatory).
8307 */
8308 attr = xmlSchemaGetPropNode(node, "refer");
8309 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008310 xmlSchemaPMissingAttrErr(ctxt,
8311 XML_SCHEMAP_S4S_ATTR_MISSING,
8312 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008313 "refer", NULL);
8314 } else {
8315 /*
8316 * Create a reference item.
8317 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008318 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 NULL, NULL);
8320 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008321 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008322 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008323 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008324 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008325 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008326 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008327 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008328 }
8329 }
8330 /*
8331 * And now for the children...
8332 */
8333 child = node->children;
8334 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008335 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008336 child = child->next;
8337 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008338 if (child == NULL) {
8339 xmlSchemaPContentErr(ctxt,
8340 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008341 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008342 "A child element is missing",
8343 "(annotation?, (selector, field+))");
8344 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008345 /*
8346 * Child element <selector>.
8347 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 if (IS_SCHEMA(child, "selector")) {
8349 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008350 item, child, 0);
8351 child = child->next;
8352 /*
8353 * Child elements <field>.
8354 */
8355 if (IS_SCHEMA(child, "field")) {
8356 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008358 item, child, 1);
8359 if (field != NULL) {
8360 field->index = item->nbFields;
8361 item->nbFields++;
8362 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008364 else
8365 item->fields = field;
8366 lastField = field;
8367 }
8368 child = child->next;
8369 } while (IS_SCHEMA(child, "field"));
8370 } else {
8371 xmlSchemaPContentErr(ctxt,
8372 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008373 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374 NULL, "(annotation?, (selector, field+))");
8375 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008376 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008377 if (child != NULL) {
8378 xmlSchemaPContentErr(ctxt,
8379 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008380 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008381 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008382 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008383
8384 return (item);
8385}
8386
Daniel Veillardc0826a72004-08-10 14:17:33 +00008387/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008388 * xmlSchemaParseElement:
8389 * @ctxt: a schema validation context
8390 * @schema: the schema being built
8391 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008392 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008393 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008394 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008395 * *WARNING* this interface is highly subject to change
8396 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 * Returns the element declaration or a particle; NULL in case
8398 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008400static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008401xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008402 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008403{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008404 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008406 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 xmlNodePtr child = NULL;
8408 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008409 int min, max, isRef = 0;
8410 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008411
8412 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8413 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008414
Daniel Veillard4255d502002-04-16 15:50:10 +00008415 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008416 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008417
8418 if (isElemRef != NULL)
8419 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008420 /*
8421 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008422 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008423 * robust.
8424 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008425 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008426 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008427 if ((topLevel) || (attr == NULL)) {
8428 if (nameAttr == NULL) {
8429 xmlSchemaPMissingAttrErr(ctxt,
8430 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008431 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008432 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008434 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008435 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008436
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008437 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008438 child = node->children;
8439 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008440 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008441 child = child->next;
8442 }
8443 /*
8444 * Skip particle part if a global declaration.
8445 */
8446 if (topLevel)
8447 goto declaration_part;
8448 /*
8449 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008450 */
8451 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8452 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8453 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008454 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8455 if (particle == NULL)
8456 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008458 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8459
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008460 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008461 const xmlChar *refNs = NULL, *ref = NULL;
8462 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008463 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008465 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008466 if (isElemRef != NULL)
8467 *isElemRef = 1;
8468
Daniel Veillardc0826a72004-08-10 14:17:33 +00008469 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008470 NULL, attr, &refNs, &ref);
8471 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008472 /*
8473 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008474 */
8475 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008476 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008477 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008478 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008479 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008480 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008482 attr = node->properties;
8483 while (attr != NULL) {
8484 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008485 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8486 xmlStrEqual(attr->name, BAD_CAST "name") ||
8487 xmlStrEqual(attr->name, BAD_CAST "id") ||
8488 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8489 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8490 {
8491 attr = attr->next;
8492 continue;
8493 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008494 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008495 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008496 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008497 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008498 "Only the attributes 'minOccurs', 'maxOccurs' and "
8499 "'id' are allowed in addition to 'ref'");
8500 break;
8501 }
8502 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8503 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008504 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008505 }
8506 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008507 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008508 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008509 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008510 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008511 if (child != NULL) {
8512 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008513 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008514 }
8515 if ((min == 0) && (max == 0))
8516 goto return_null;
8517 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008518 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008520 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008521 ref, refNs);
8522 if (refer == NULL)
8523 goto return_null;
8524 particle->children = (xmlSchemaTreeItemPtr) refer;
8525 particle->annot = annot;
8526 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008527 * Add the particle to pending components, since the reference
8528 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008529 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008530 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 return ((xmlSchemaBasicItemPtr) particle);
8532 }
8533 /*
8534 * The declaration part ===============================================
8535 */
8536declaration_part:
8537 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008538 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008539 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8540
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008541 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008542 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008543 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008544 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 * Evaluate the target namespace.
8546 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008547 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008548 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008549 } else {
8550 attr = xmlSchemaGetPropNode(node, "form");
8551 if (attr != NULL) {
8552 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8553 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008554 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008555 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008556 xmlSchemaPSimpleTypeErr(ctxt,
8557 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8558 NULL, (xmlNodePtr) attr,
8559 NULL, "(qualified | unqualified)",
8560 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008561 }
8562 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008563 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008564 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008565 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008567 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008569 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008570 * Check for illegal attributes.
8571 */
William M. Bracke7091952004-05-11 15:09:58 +00008572 attr = node->properties;
8573 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008574 if (attr->ns == NULL) {
8575 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8576 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008578 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008579 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008580 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008581 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8582 {
8583 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008584 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008585 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008587 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008588 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8592 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008593 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8594
8595 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008596 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008597 }
8598 }
8599 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600
Daniel Veillardc0826a72004-08-10 14:17:33 +00008601 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008603 }
8604 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 }
William M. Bracke7091952004-05-11 15:09:58 +00008606 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008607 * Extract/validate attributes.
8608 */
8609 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008610 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008611 * Process top attributes of global element declarations here.
8612 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008613 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8614 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008615 xmlSchemaPValAttrQName(ctxt, schema,
8616 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008618 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008619 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008620 /*
8621 * Attribute "final".
8622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008624 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008625 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8626 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8627 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8628 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008629 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8631 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008632 -1,
8633 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8634 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008636 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008637 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 attrValue, NULL, NULL, NULL);
8640 }
8641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008642 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008643 /*
8644 * Attribute "block".
8645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008646 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008647 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008648 /*
8649 * Apply default "block" values.
8650 */
8651 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8652 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8653 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8654 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8655 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8656 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008657 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008658 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8659 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008660 -1,
8661 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008662 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008663 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8664 xmlSchemaPSimpleTypeErr(ctxt,
8665 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008666 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008667 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008668 "restriction | substitution))", attrValue,
8669 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008670 }
8671 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008672 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008673 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008675 attr = xmlSchemaGetPropNode(node, "type");
8676 if (attr != NULL) {
8677 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008678 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 &(decl->namedTypeNs), &(decl->namedType));
8680 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008681 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 }
8683 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8684 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008685 if (attr != NULL) {
8686 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008687 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008688 /*
8689 * 3.3.3 : 1
8690 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 */
8692 xmlSchemaPMutualExclAttrErr(ctxt,
8693 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008694 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008695 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008696 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8697 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008698 }
William M. Bracke7091952004-05-11 15:09:58 +00008699 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008700 /*
8701 * And now for the children...
8702 */
William M. Bracke7091952004-05-11 15:09:58 +00008703 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 /*
8705 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008706 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008707 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008708 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008709 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008710 xmlSchemaPContentErr(ctxt,
8711 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008712 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008713 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008714 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008715 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008716 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008717 child = child->next;
8718 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008719 /*
8720 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008721 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008722 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008724 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008725 xmlSchemaPContentErr(ctxt,
8726 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008727 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008728 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008730 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008731 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008733 }
William M. Bracke7091952004-05-11 15:09:58 +00008734 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008735 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008736 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008737 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008738 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008739 } else if (IS_SCHEMA(child, "key")) {
8740 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008741 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008742 } else if (IS_SCHEMA(child, "keyref")) {
8743 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008744 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008745 }
8746 if (lastIDC != NULL)
8747 lastIDC->next = curIDC;
8748 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008749 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008750 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008751 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008752 }
8753 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008754 xmlSchemaPContentErr(ctxt,
8755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008756 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008757 NULL, "(annotation?, ((simpleType | complexType)?, "
8758 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008760 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008761 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008762 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008763 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764 * different layer.
8765 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008766 FREE_AND_NULL(des)
8767 if (topLevel)
8768 return ((xmlSchemaBasicItemPtr) decl);
8769 else {
8770 particle->children = (xmlSchemaTreeItemPtr) decl;
8771 return ((xmlSchemaBasicItemPtr) particle);
8772 }
8773
8774return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008775 FREE_AND_NULL(des);
8776 if (annot != NULL) {
8777 if (particle != NULL)
8778 particle->annot = NULL;
8779 if (decl != NULL)
8780 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008781 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008782 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008783 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008784}
8785
8786/**
8787 * xmlSchemaParseUnion:
8788 * @ctxt: a schema validation context
8789 * @schema: the schema being built
8790 * @node: a subtree containing XML Schema informations
8791 *
8792 * parse a XML schema Union definition
8793 * *WARNING* this interface is highly subject to change
8794 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008795 * Returns -1 in case of internal error, 0 in case of success and a positive
8796 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008797 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008798static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008799xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008800 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008801{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008802 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008803 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008804 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008805 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008806
8807 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008808 return (-1);
8809 /* Not a component, don't create it. */
8810 type = ctxt->ctxtType;
8811 /*
8812 * Mark the simple type as being of variety "union".
8813 */
8814 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008815 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008816 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8817 * then the ·simple ur-type definition·."
8818 */
8819 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008820 /*
8821 * Check for illegal attributes.
8822 */
8823 attr = node->properties;
8824 while (attr != NULL) {
8825 if (attr->ns == NULL) {
8826 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8827 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008828 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008830 }
8831 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008832 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008833 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008834 }
8835 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008836 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008837 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008838 /*
8839 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008840 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008843 if (attr != NULL) {
8844 const xmlChar *end;
8845 xmlChar *tmp;
8846 const xmlChar *localName, *nsName;
8847 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8848 xmlSchemaQNameRefPtr ref;
8849
8850 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008851 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008852 do {
8853 while (IS_BLANK_CH(*cur))
8854 cur++;
8855 end = cur;
8856 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8857 end++;
8858 if (end == cur)
8859 break;
8860 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008861 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008863 /*
8864 * Create the member type link.
8865 */
8866 link = (xmlSchemaTypeLinkPtr)
8867 xmlMalloc(sizeof(xmlSchemaTypeLink));
8868 if (link == NULL) {
8869 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8870 "allocating a type link", NULL);
8871 return (-1);
8872 }
8873 link->type = NULL;
8874 link->next = NULL;
8875 if (lastLink == NULL)
8876 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008877 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008878 lastLink->next = link;
8879 lastLink = link;
8880 /*
8881 * Create a reference item.
8882 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008883 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008884 localName, nsName);
8885 if (ref == NULL) {
8886 FREE_AND_NULL(tmp)
8887 return (-1);
8888 }
8889 /*
8890 * Assign the reference to the link, it will be resolved
8891 * later during fixup of the union simple type.
8892 */
8893 link->type = (xmlSchemaTypePtr) ref;
8894 }
8895 FREE_AND_NULL(tmp)
8896 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008897 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008898
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008900 /*
8901 * And now for the children...
8902 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008903 child = node->children;
8904 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008905 /*
8906 * Add the annotation to the simple type ancestor.
8907 */
8908 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008909 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008910 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008911 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008912 if (IS_SCHEMA(child, "simpleType")) {
8913 xmlSchemaTypePtr subtype, last = NULL;
8914
8915 /*
8916 * Anchor the member types in the "subtypes" field of the
8917 * simple type.
8918 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008920 subtype = (xmlSchemaTypePtr)
8921 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8922 if (subtype != NULL) {
8923 if (last == NULL) {
8924 type->subtypes = subtype;
8925 last = subtype;
8926 } else {
8927 last->next = subtype;
8928 last = subtype;
8929 }
8930 last->next = NULL;
8931 }
8932 child = child->next;
8933 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008934 }
8935 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008936 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008938 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008940 if ((attr == NULL) && (type->subtypes == NULL)) {
8941 /*
8942 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 * Either the memberTypes [attribute] of the <union> element must
8944 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008947 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008948 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008949 "Either the attribute 'memberTypes' or "
8950 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008952 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008953}
8954
8955/**
8956 * xmlSchemaParseList:
8957 * @ctxt: a schema validation context
8958 * @schema: the schema being built
8959 * @node: a subtree containing XML Schema informations
8960 *
8961 * parse a XML schema List definition
8962 * *WARNING* this interface is highly subject to change
8963 *
William M. Bracke7091952004-05-11 15:09:58 +00008964 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 * 1 in case of success.
8966 */
8967static xmlSchemaTypePtr
8968xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008969 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008970{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008971 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008972 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008973 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008974
8975 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8976 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008977 /* Not a component, don't create it. */
8978 type = ctxt->ctxtType;
8979 /*
8980 * Mark the type as being of variety "list".
8981 */
8982 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008984 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8985 * then the ·simple ur-type definition·."
8986 */
8987 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008988 /*
8989 * Check for illegal attributes.
8990 */
8991 attr = node->properties;
8992 while (attr != NULL) {
8993 if (attr->ns == NULL) {
8994 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8995 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008997 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008998 }
8999 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009001 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009002 }
9003 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009004 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009005
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009006 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009007
William M. Brack2f2a6632004-08-20 23:09:47 +00009008 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009009 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9010 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009011 *
9012 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9013 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009014 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009015 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9016 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009017 /*
9018 * And now for the children...
9019 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009020 child = node->children;
9021 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009022 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009023 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009024 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009025 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009026 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009027 /*
9028 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009029 * Either the itemType [attribute] or the <simpleType> [child] of
9030 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009031 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009032 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009033 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009034 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009035 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009036 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009037 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009039 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009040 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009042 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009043 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009044 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009045 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009046 "Either the attribute 'itemType' or the <simpleType> child "
9047 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009048 }
9049 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009050 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009052 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009053 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009054 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009055 (type->subtypes == NULL) &&
9056 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009058 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009059 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009060 "Either the attribute 'itemType' or the <simpleType> child "
9061 "must be present", NULL);
9062 }
9063 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009064}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009065
Daniel Veillard4255d502002-04-16 15:50:10 +00009066/**
9067 * xmlSchemaParseSimpleType:
9068 * @ctxt: a schema validation context
9069 * @schema: the schema being built
9070 * @node: a subtree containing XML Schema informations
9071 *
9072 * parse a XML schema Simple Type definition
9073 * *WARNING* this interface is highly subject to change
9074 *
William M. Bracke7091952004-05-11 15:09:58 +00009075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009076 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009077 */
9078static xmlSchemaTypePtr
9079xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009080 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009081{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009082 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009083 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009084 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009085 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009086 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009087
9088 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9089 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009090
Daniel Veillardc0826a72004-08-10 14:17:33 +00009091 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009092 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009093 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009094 xmlSchemaPMissingAttrErr(ctxt,
9095 XML_SCHEMAP_S4S_ATTR_MISSING,
9096 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009097 "name", NULL);
9098 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009099 } else {
9100 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009101 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009102 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9103 return (NULL);
9104 /*
9105 * Skip built-in types.
9106 */
9107 if (ctxt->isS4S) {
9108 xmlSchemaTypePtr biType;
9109
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009110 if (ctxt->isRedefine) {
9111 /*
9112 * REDEFINE: Disallow redefinition of built-in-types.
9113 * TODO: It seems that the spec does not say anything
9114 * about this case.
9115 */
9116 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009117 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009118 "Redefinition of built-in simple types is not "
9119 "supported", NULL);
9120 return(NULL);
9121 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009122 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9123 if (biType != NULL)
9124 return (biType);
9125 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009126 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009127 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009128 /*
9129 * TargetNamespace:
9130 * SPEC "The ·actual value· of the targetNamespace [attribute]
9131 * of the <schema> ancestor element information item if present,
9132 * otherwise ·absent·.
9133 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009134 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009135#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009136 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009137#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009138 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009139 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009140 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009141#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009142 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009143 type = xmlSchemaAddType(ctxt, schema,
9144 XML_SCHEMA_TYPE_SIMPLE,
9145 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009146 ctxt->targetNamespace, node, 0);
9147#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009148 type = xmlSchemaAddType(ctxt, schema,
9149 XML_SCHEMA_TYPE_SIMPLE,
9150 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009151#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009152 if (type == NULL)
9153 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009154 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009155 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009156 /*
9157 * Check for illegal attributes.
9158 */
9159 attr = node->properties;
9160 while (attr != NULL) {
9161 if (attr->ns == NULL) {
9162 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009164 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009165 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009166 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009167 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009168 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 }
9170 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009172 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009173 /*
9174 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009175 *
9176 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009177 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009178 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9179 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009180 if (type == NULL)
9181 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009182 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009183 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009184 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9185 /*
9186 * Check for illegal attributes.
9187 */
9188 attr = node->properties;
9189 while (attr != NULL) {
9190 if (attr->ns == NULL) {
9191 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9192 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009193 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009194 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009196 }
9197 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009198 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009199 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009200 }
9201 attr = attr->next;
9202 }
9203 /*
9204 * Attribute "final".
9205 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009206 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009208 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9209 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9210 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9211 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9212 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9213 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009214 } else {
9215 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009216 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9217 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009218 XML_SCHEMAS_TYPE_FINAL_LIST,
9219 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9220
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009221 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009223 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009224 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009225 attrValue, NULL, NULL, NULL);
9226 }
9227 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009228 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009229 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009230 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009231 /*
9232 * And now for the children...
9233 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009234 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009235
Daniel Veillardc0826a72004-08-10 14:17:33 +00009236 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009237
Daniel Veillard4255d502002-04-16 15:50:10 +00009238 child = node->children;
9239 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009240 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009242 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009243 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009244 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009245 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009246 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009247 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009248 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009249 XML_SCHEMA_TYPE_SIMPLE);
9250 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009251 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009252 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009253 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009254 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009255 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009256 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009257 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009259 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009260 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009261 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009262 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009263 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009264 /*
9265 * REDEFINE: SPEC src-redefine (5)
9266 * "Within the [children], each <simpleType> must have a
9267 * <restriction> among its [children] ... the ·actual value· of whose
9268 * base [attribute] must be the same as the ·actual value· of its own
9269 * name attribute plus target namespace;"
9270 */
9271 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9272 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009273 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009274 "<simpleType> must have a <restriction> child", NULL);
9275 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009276
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009277 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009278 return (type);
9279}
9280
Daniel Veillard4255d502002-04-16 15:50:10 +00009281/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009282 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283 * @ctxt: the parser context
9284 * @schema: the schema being built
9285 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009286 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009287 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009288 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009289 * We will return a particle component with a qname-component or
9290 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009291 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009292static xmlSchemaTreeItemPtr
9293xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9294 xmlSchemaPtr schema,
9295 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009296{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009297 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009298 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009300 const xmlChar *ref = NULL, *refNs = NULL;
9301 int min, max;
9302
9303 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009304 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009305
9306 attr = xmlSchemaGetPropNode(node, "ref");
9307 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009308 xmlSchemaPMissingAttrErr(ctxt,
9309 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009310 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009311 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009312 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009313 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009314 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009315 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009316 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009317 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009318 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009319 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009320 /*
9321 * Check for illegal attributes.
9322 */
9323 attr = node->properties;
9324 while (attr != NULL) {
9325 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009326 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9328 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9329 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009330 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009332 }
9333 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009334 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009336 }
9337 attr = attr->next;
9338 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009339 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009340 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9341 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009342 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009343 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009344 * Create a qname-reference and set as the term; it will be substituted
9345 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 */
9347 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009348 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9350 /*
9351 * And now for the children...
9352 */
9353 child = node->children;
9354 /* TODO: Is annotation even allowed for a model group reference? */
9355 if (IS_SCHEMA(child, "annotation")) {
9356 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009357 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009358 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009359 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009360 child = child->next;
9361 }
9362 if (child != NULL) {
9363 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009364 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009365 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009366 "(annotation?)");
9367 }
9368 /*
9369 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9370 */
9371 if ((min == 0) && (max == 0))
9372 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009373
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009374 return ((xmlSchemaTreeItemPtr) item);
9375}
9376
9377/**
9378 * xmlSchemaParseModelGroupDefinition:
9379 * @ctxt: a schema validation context
9380 * @schema: the schema being built
9381 * @node: a subtree containing XML Schema informations
9382 *
9383 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009384 *
9385 * Note that the contraint src-redefine (6.2) can't be applied until
9386 * references have been resolved. So we will do this at the
9387 * component fixup level.
9388 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009389 * *WARNING* this interface is highly subject to change
9390 *
9391 * Returns -1 in case of error, 0 if the declaration is improper and
9392 * 1 in case of success.
9393 */
9394static xmlSchemaModelGroupDefPtr
9395xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9396 xmlSchemaPtr schema,
9397 xmlNodePtr node)
9398{
9399 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009400 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009401 xmlAttrPtr attr;
9402 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009403
9404 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009405 return (NULL);
9406
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009407 attr = xmlSchemaGetPropNode(node, "name");
9408 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009409 xmlSchemaPMissingAttrErr(ctxt,
9410 XML_SCHEMAP_S4S_ATTR_MISSING,
9411 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009412 "name", NULL);
9413 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009414 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009415 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9416 return (NULL);
9417 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009418 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9419 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009420 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009421 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422 /*
9423 * Check for illegal attributes.
9424 */
9425 attr = node->properties;
9426 while (attr != NULL) {
9427 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009429 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009430 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009432 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009433 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009434 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009435 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009437 attr = attr->next;
9438 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009439 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009440 /*
9441 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009442 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009443 child = node->children;
9444 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009445 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009446 child = child->next;
9447 }
9448 if (IS_SCHEMA(child, "all")) {
9449 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9450 XML_SCHEMA_TYPE_ALL, 0);
9451 child = child->next;
9452 } else if (IS_SCHEMA(child, "choice")) {
9453 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9454 XML_SCHEMA_TYPE_CHOICE, 0);
9455 child = child->next;
9456 } else if (IS_SCHEMA(child, "sequence")) {
9457 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9458 XML_SCHEMA_TYPE_SEQUENCE, 0);
9459 child = child->next;
9460 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009461
9462
9463
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009464 if (child != NULL) {
9465 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009466 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009467 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009468 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009469 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009470 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009471}
9472
9473/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009474 * xmlSchemaCleanupDoc:
9475 * @ctxt: a schema validation context
9476 * @node: the root of the document.
9477 *
9478 * removes unwanted nodes in a schemas document tree
9479 */
9480static void
9481xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9482{
9483 xmlNodePtr delete, cur;
9484
9485 if ((ctxt == NULL) || (root == NULL)) return;
9486
9487 /*
9488 * Remove all the blank text nodes
9489 */
9490 delete = NULL;
9491 cur = root;
9492 while (cur != NULL) {
9493 if (delete != NULL) {
9494 xmlUnlinkNode(delete);
9495 xmlFreeNode(delete);
9496 delete = NULL;
9497 }
9498 if (cur->type == XML_TEXT_NODE) {
9499 if (IS_BLANK_NODE(cur)) {
9500 if (xmlNodeGetSpacePreserve(cur) != 1) {
9501 delete = cur;
9502 }
9503 }
9504 } else if ((cur->type != XML_ELEMENT_NODE) &&
9505 (cur->type != XML_CDATA_SECTION_NODE)) {
9506 delete = cur;
9507 goto skip_children;
9508 }
9509
9510 /*
9511 * Skip to next node
9512 */
9513 if (cur->children != NULL) {
9514 if ((cur->children->type != XML_ENTITY_DECL) &&
9515 (cur->children->type != XML_ENTITY_REF_NODE) &&
9516 (cur->children->type != XML_ENTITY_NODE)) {
9517 cur = cur->children;
9518 continue;
9519 }
9520 }
9521 skip_children:
9522 if (cur->next != NULL) {
9523 cur = cur->next;
9524 continue;
9525 }
9526
9527 do {
9528 cur = cur->parent;
9529 if (cur == NULL)
9530 break;
9531 if (cur == root) {
9532 cur = NULL;
9533 break;
9534 }
9535 if (cur->next != NULL) {
9536 cur = cur->next;
9537 break;
9538 }
9539 } while (cur != NULL);
9540 }
9541 if (delete != NULL) {
9542 xmlUnlinkNode(delete);
9543 xmlFreeNode(delete);
9544 delete = NULL;
9545 }
9546}
9547
William M. Brack2f2a6632004-08-20 23:09:47 +00009548
William M. Brack2f2a6632004-08-20 23:09:47 +00009549static void
9550xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9551{
9552 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9553 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9554
9555 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9556 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9557
9558 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9559 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9560 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9561 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9562 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9563 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9564 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9565 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9566
9567 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9568 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9569 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9570 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9571 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9572 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9573}
9574
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009575static int
9576xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009577 xmlSchemaPtr schema,
9578 xmlNodePtr node)
9579{
9580 xmlAttrPtr attr;
9581 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009582 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009583
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009584 /*
9585 * Those flags should be moved to the parser context flags,
9586 * since they are not visible at the component level. I.e.
9587 * they are used if processing schema *documents* only.
9588 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009589 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009590 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009591
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009592 /*
9593 * Since the version is of type xs:token, we won't bother to
9594 * check it.
9595 */
9596 /* REMOVED:
9597 attr = xmlSchemaGetPropNode(node, "version");
9598 if (attr != NULL) {
9599 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9600 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9601 HFAILURE;
9602 }
9603 */
9604 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9605 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009606 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009607 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9608 HFAILURE;
9609 if (res != 0) {
9610 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9611 goto exit;
9612 }
9613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009614 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009615 if (attr != NULL) {
9616 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009617 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9618 XML_SCHEMAS_QUALIF_ELEM);
9619 HFAILURE;
9620 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009621 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009624 "(qualified | unqualified)", val, NULL, NULL, NULL);
9625 }
9626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 if (attr != NULL) {
9629 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009630 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9631 XML_SCHEMAS_QUALIF_ATTR);
9632 HFAILURE;
9633 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009634 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009635 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009636 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009637 "(qualified | unqualified)", val, NULL, NULL, NULL);
9638 }
9639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009640 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009641 if (attr != NULL) {
9642 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009643 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9645 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9646 -1,
9647 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009648 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9649 HFAILURE;
9650 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 xmlSchemaPSimpleTypeErr(ctxt,
9652 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009653 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009654 "(#all | List of (extension | restriction | list | union))",
9655 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009656 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009660 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9661 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009662 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9663 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009664 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9665 HFAILURE;
9666 if (res != 0) {
9667 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009668 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009670 "(#all | List of (extension | restriction | substitution))",
9671 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009673 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009674
9675exit:
9676 if (oldErrs != ctxt->nberrors)
9677 res = ctxt->err;
9678 return(res);
9679exit_failure:
9680 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009681}
9682
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009683/**
9684 * xmlSchemaParseSchemaTopLevel:
9685 * @ctxt: a schema validation context
9686 * @schema: the schemas
9687 * @nodes: the list of top level nodes
9688 *
9689 * Returns the internal XML Schema structure built from the resource or
9690 * NULL in case of error
9691 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009692static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009693xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9694 xmlSchemaPtr schema, xmlNodePtr nodes)
9695{
9696 xmlNodePtr child;
9697 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009698 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009699
9700 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009701 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009702
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009703 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009704 child = nodes;
9705 while ((IS_SCHEMA(child, "include")) ||
9706 (IS_SCHEMA(child, "import")) ||
9707 (IS_SCHEMA(child, "redefine")) ||
9708 (IS_SCHEMA(child, "annotation"))) {
9709 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009710 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009711 if (schema->annot == NULL)
9712 schema->annot = annot;
9713 else
9714 xmlSchemaFreeAnnot(annot);
9715 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009716 tmpOldErrs = ctxt->nberrors;
9717 res = xmlSchemaParseImport(ctxt, schema, child);
9718 HFAILURE;
9719 HSTOP(ctxt);
9720 if (tmpOldErrs != ctxt->nberrors)
9721 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009722 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009723 tmpOldErrs = ctxt->nberrors;
9724 res = xmlSchemaParseInclude(ctxt, schema, child);
9725 HFAILURE;
9726 HSTOP(ctxt);
9727 if (tmpOldErrs != ctxt->nberrors)
9728 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009729 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009730 tmpOldErrs = ctxt->nberrors;
9731 res = xmlSchemaParseRedefine(ctxt, schema, child);
9732 HFAILURE;
9733 HSTOP(ctxt);
9734 if (tmpOldErrs != ctxt->nberrors)
9735 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009736 }
9737 child = child->next;
9738 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009739 /*
9740 * URGENT TODO: Change the functions to return int results.
9741 * We need especially to catch internal errors.
9742 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009743 while (child != NULL) {
9744 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009745 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009746 child = child->next;
9747 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009748 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009749 child = child->next;
9750 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009751 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009752 child = child->next;
9753 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009754 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009755 child = child->next;
9756 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009757 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009758 child = child->next;
9759 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009760 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009761 child = child->next;
9762 } else if (IS_SCHEMA(child, "notation")) {
9763 xmlSchemaParseNotation(ctxt, schema, child);
9764 child = child->next;
9765 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009766 xmlSchemaPContentErr(ctxt,
9767 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009768 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009769 NULL, "((include | import | redefine | annotation)*, "
9770 "(((simpleType | complexType | group | attributeGroup) "
9771 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009772 child = child->next;
9773 }
9774 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009775 /*
9776 * TODO: We should add all annotations.
9777 */
9778 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009779 if (schema->annot == NULL)
9780 schema->annot = annot;
9781 else
9782 xmlSchemaFreeAnnot(annot);
9783 child = child->next;
9784 }
9785 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009786exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009787 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009788 if (oldErrs != ctxt->nberrors)
9789 res = ctxt->err;
9790 return(res);
9791exit_failure:
9792 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009793}
9794
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009795static xmlSchemaSchemaRelationPtr
9796xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009797{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009798 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009799
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009800 ret = (xmlSchemaSchemaRelationPtr)
9801 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009802 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009803 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009804 return(NULL);
9805 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009806 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009807 return(ret);
9808}
9809
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009811static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009812xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009813{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009814 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009815}
9816#endif
9817
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009818static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009819xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9820{
9821 xmlSchemaRedefPtr prev;
9822
9823 while (redef != NULL) {
9824 prev = redef;
9825 redef = redef->next;
9826 xmlFree(prev);
9827 }
9828}
9829
9830static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009831xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9832{
9833 /*
9834 * After the construction context has been freed, there will be
9835 * no schema graph available any more. Only the schema buckets
9836 * will stay alive, which are put into the "schemasImports" and
9837 * "includes" slots of the xmlSchema.
9838 */
9839 if (con->buckets != NULL)
9840 xmlSchemaItemListFree(con->buckets);
9841 if (con->pending != NULL)
9842 xmlSchemaItemListFree(con->pending);
9843 if (con->substGroups != NULL)
9844 xmlHashFree(con->substGroups,
9845 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009846 if (con->redefs != NULL)
9847 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009848 if (con->dict != NULL)
9849 xmlDictFree(con->dict);
9850 xmlFree(con);
9851}
9852
9853static xmlSchemaConstructionCtxtPtr
9854xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9855{
9856 xmlSchemaConstructionCtxtPtr ret;
9857
9858 ret = (xmlSchemaConstructionCtxtPtr)
9859 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9860 if (ret == NULL) {
9861 xmlSchemaPErrMemory(NULL,
9862 "allocating schema construction context", NULL);
9863 return (NULL);
9864 }
9865 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9866
9867 ret->buckets = xmlSchemaItemListCreate();
9868 if (ret->buckets == NULL) {
9869 xmlSchemaPErrMemory(NULL,
9870 "allocating list of schema buckets", NULL);
9871 xmlFree(ret);
9872 return (NULL);
9873 }
9874 ret->pending = xmlSchemaItemListCreate();
9875 if (ret->pending == NULL) {
9876 xmlSchemaPErrMemory(NULL,
9877 "allocating list of pending global components", NULL);
9878 xmlSchemaConstructionCtxtFree(ret);
9879 return (NULL);
9880 }
9881 ret->dict = dict;
9882 xmlDictReference(dict);
9883 return(ret);
9884}
9885
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009886static xmlSchemaParserCtxtPtr
9887xmlSchemaParserCtxtCreate(void)
9888{
9889 xmlSchemaParserCtxtPtr ret;
9890
9891 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9892 if (ret == NULL) {
9893 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9894 NULL);
9895 return (NULL);
9896 }
9897 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9898 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009899 ret->attrProhibs = xmlSchemaItemListCreate();
9900 if (ret->attrProhibs == NULL) {
9901 xmlFree(ret);
9902 return(NULL);
9903 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009904 return(ret);
9905}
9906
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009907/**
9908 * xmlSchemaNewParserCtxtUseDict:
9909 * @URL: the location of the schema
9910 * @dict: the dictionary to be used
9911 *
9912 * Create an XML Schemas parse context for that file/resource expected
9913 * to contain an XML Schemas file.
9914 *
9915 * Returns the parser context or NULL in case of error
9916 */
9917static xmlSchemaParserCtxtPtr
9918xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9919{
9920 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009921
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009922 ret = xmlSchemaParserCtxtCreate();
9923 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009925 ret->dict = dict;
9926 xmlDictReference(dict);
9927 if (URL != NULL)
9928 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 return (ret);
9930}
9931
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009932static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009933xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9934{
9935 if (vctxt->pctxt == NULL) {
9936 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009937 vctxt->pctxt =
9938 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939 else
9940 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9941 if (vctxt->pctxt == NULL) {
9942 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9943 "failed to create a temp. parser context");
9944 return (-1);
9945 }
9946 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009947 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009948 vctxt->warning, vctxt->errCtxt);
9949 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9950 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009951 }
9952 return (0);
9953}
9954
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009955/**
9956 * xmlSchemaGetSchemaBucket:
9957 * @pctxt: the schema parser context
9958 * @schemaLocation: the URI of the schema document
9959 *
9960 * Returns a schema bucket if it was already parsed.
9961 *
9962 * Returns a schema bucket if it was already parsed from
9963 * @schemaLocation, NULL otherwise.
9964 */
9965static xmlSchemaBucketPtr
9966xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9967 const xmlChar *schemaLocation)
9968{
9969 xmlSchemaBucketPtr cur;
9970 xmlSchemaItemListPtr list;
9971
9972 list = pctxt->constructor->buckets;
9973 if (list->nbItems == 0)
9974 return(NULL);
9975 else {
9976 int i;
9977 for (i = 0; i < list->nbItems; i++) {
9978 cur = (xmlSchemaBucketPtr) list->items[i];
9979 /* Pointer comparison! */
9980 if (cur->schemaLocation == schemaLocation)
9981 return(cur);
9982 }
9983 }
9984 return(NULL);
9985}
9986
9987static xmlSchemaBucketPtr
9988xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9989 const xmlChar *schemaLocation,
9990 const xmlChar *targetNamespace)
9991{
9992 xmlSchemaBucketPtr cur;
9993 xmlSchemaItemListPtr list;
9994
9995 list = pctxt->constructor->buckets;
9996 if (list->nbItems == 0)
9997 return(NULL);
9998 else {
9999 int i;
10000 for (i = 0; i < list->nbItems; i++) {
10001 cur = (xmlSchemaBucketPtr) list->items[i];
10002 /* Pointer comparison! */
10003 if ((cur->origTargetNamespace == NULL) &&
10004 (cur->schemaLocation == schemaLocation) &&
10005 (cur->targetNamespace == targetNamespace))
10006 return(cur);
10007 }
10008 }
10009 return(NULL);
10010}
10011
10012
10013#define IS_BAD_SCHEMA_DOC(b) \
10014 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10015
10016static xmlSchemaBucketPtr
10017xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10018 const xmlChar *targetNamespace,
10019 int imported)
10020{
10021 xmlSchemaBucketPtr cur;
10022 xmlSchemaItemListPtr list;
10023
10024 list = pctxt->constructor->buckets;
10025 if (list->nbItems == 0)
10026 return(NULL);
10027 else {
10028 int i;
10029 for (i = 0; i < list->nbItems; i++) {
10030 cur = (xmlSchemaBucketPtr) list->items[i];
10031 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10032 (cur->origTargetNamespace == targetNamespace) &&
10033 ((imported && cur->imported) ||
10034 ((!imported) && (!cur->imported))))
10035 return(cur);
10036 }
10037 }
10038 return(NULL);
10039}
10040
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010041static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010042xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10043 xmlSchemaPtr schema,
10044 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010045{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010046 int oldFlags;
10047 xmlDocPtr oldDoc;
10048 xmlNodePtr node;
10049 int ret, oldErrs;
10050 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10051
10052 /*
10053 * Save old values; reset the *main* schema.
10054 * URGENT TODO: This is not good; move the per-document information
10055 * to the parser.
10056 */
10057 oldFlags = schema->flags;
10058 oldDoc = schema->doc;
10059 if (schema->flags != 0)
10060 xmlSchemaClearSchemaDefaults(schema);
10061 schema->doc = bucket->doc;
10062 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
10063 pctxt->schema = schema;
10064 /*
10065 * Keep the current target namespace on the parser *not* on the
10066 * main schema.
10067 */
10068 pctxt->targetNamespace = bucket->targetNamespace;
10069 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010070
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010071 if ((bucket->targetNamespace != NULL) &&
10072 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010073 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010074 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010075 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010076 pctxt->isS4S = 1;
10077 }
10078 /* Mark it as parsed, even if parsing fails. */
10079 bucket->parsed++;
10080 /* Compile the schema doc. */
10081 node = xmlDocGetRootElement(bucket->doc);
10082 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10083 if (ret != 0)
10084 goto exit;
10085 /* An empty schema; just get out. */
10086 if (node->children == NULL)
10087 goto exit;
10088 oldErrs = pctxt->nberrors;
10089 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10090 if (ret != 0)
10091 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010092 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010093 * TODO: Not nice, but I'm not 100% sure we will get always an error
10094 * as a result of the obove functions; so better rely on pctxt->err
10095 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010096 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010097 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10098 ret = pctxt->err;
10099 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010100 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010101
10102exit:
10103 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10104 /* Restore schema values. */
10105 schema->doc = oldDoc;
10106 schema->flags = oldFlags;
10107 return(ret);
10108}
10109
10110static int
10111xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10112 xmlSchemaPtr schema,
10113 xmlSchemaBucketPtr bucket)
10114{
10115 xmlSchemaParserCtxtPtr newpctxt;
10116 int res = 0;
10117
10118 if (bucket == NULL)
10119 return(0);
10120 if (bucket->parsed) {
10121 PERROR_INT("xmlSchemaParseNewDoc",
10122 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010123 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010124 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010125 if (bucket->doc == NULL) {
10126 PERROR_INT("xmlSchemaParseNewDoc",
10127 "parsing a schema doc, but there's no doc");
10128 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010129 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010130 if (pctxt->constructor == NULL) {
10131 PERROR_INT("xmlSchemaParseNewDoc",
10132 "no constructor");
10133 return(-1);
10134 }
10135 /* Create and init the temporary parser context. */
10136 newpctxt = xmlSchemaNewParserCtxtUseDict(
10137 (const char *) bucket->schemaLocation, pctxt->dict);
10138 if (newpctxt == NULL)
10139 return(-1);
10140 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010141 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010142 * TODO: Can we avoid that the parser knows about the main schema?
10143 * It would be better if he knows about the current schema bucket
10144 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010145 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010146 newpctxt->schema = schema;
10147 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010148 pctxt->errCtxt);
10149 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10150 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010151 newpctxt->counter = pctxt->counter;
10152
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010154 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10155
10156 /* Channel back errors and cleanup the temporary parser context. */
10157 if (res != 0)
10158 pctxt->err = res;
10159 pctxt->nberrors += newpctxt->nberrors;
10160 pctxt->counter = newpctxt->counter;
10161 newpctxt->constructor = NULL;
10162 /* Free the parser context. */
10163 xmlSchemaFreeParserCtxt(newpctxt);
10164 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010165}
William M. Brack2f2a6632004-08-20 23:09:47 +000010166
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010167static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010168xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10169 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010170{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010171 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010172
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010173 if (cur == NULL) {
10174 bucket->relations = rel;
10175 return;
10176 }
10177 while (cur->next != NULL)
10178 cur = cur->next;
10179 cur->next = rel;
10180}
10181
10182
10183static const xmlChar *
10184xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10185 xmlNodePtr ctxtNode)
10186{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010187 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010188 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010189 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010190 if (location != NULL) {
10191 if (ctxtNode == NULL)
10192 return(location);
10193 else {
10194 xmlChar *base, *URI;
10195 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010196
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010197 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10198 if (base == NULL) {
10199 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10200 } else {
10201 URI = xmlBuildURI(location, base);
10202 xmlFree(base);
10203 }
10204 if (URI != NULL) {
10205 ret = xmlDictLookup(dict, URI, -1);
10206 xmlFree(URI);
10207 return(ret);
10208 }
10209 }
10210 }
10211 return(NULL);
10212}
10213
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010214
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010215
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010216/**
10217 * xmlSchemaAddSchemaDoc:
10218 * @pctxt: a schema validation context
10219 * @schema: the schema being built
10220 * @node: a subtree containing XML Schema informations
10221 *
10222 * Parse an included (and to-be-redefined) XML schema document.
10223 *
10224 * Returns 0 on success, a positive error code on errors and
10225 * -1 in case of an internal or API error.
10226 */
10227
10228static int
10229xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10230 int type, /* import or include or redefine */
10231 const xmlChar *schemaLocation,
10232 xmlDocPtr schemaDoc,
10233 const char *schemaBuffer,
10234 int schemaBufferLen,
10235 xmlNodePtr invokingNode,
10236 const xmlChar *sourceTargetNamespace,
10237 const xmlChar *importNamespace,
10238 xmlSchemaBucketPtr *bucket)
10239{
10240 const xmlChar *targetNamespace = NULL;
10241 xmlSchemaSchemaRelationPtr relation = NULL;
10242 xmlDocPtr doc = NULL;
10243 int res = 0, err = 0, located = 0, preserveDoc = 0;
10244 xmlSchemaBucketPtr bkt = NULL;
10245
10246 if (bucket != NULL)
10247 *bucket = NULL;
10248
10249 switch (type) {
10250 case XML_SCHEMA_SCHEMA_IMPORT:
10251 case XML_SCHEMA_SCHEMA_MAIN:
10252 err = XML_SCHEMAP_SRC_IMPORT;
10253 break;
10254 case XML_SCHEMA_SCHEMA_INCLUDE:
10255 err = XML_SCHEMAP_SRC_INCLUDE;
10256 break;
10257 case XML_SCHEMA_SCHEMA_REDEFINE:
10258 err = XML_SCHEMAP_SRC_REDEFINE;
10259 break;
10260 }
10261
10262
10263 /* Special handling for the main schema:
10264 * skip the location and relation logic and just parse the doc.
10265 * We need just a bucket to be returned in this case.
10266 */
10267 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10268 goto doc_load;
10269
10270 /* Note that we expect the location to be an absulute URI. */
10271 if (schemaLocation != NULL) {
10272 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10273 if ((bkt != NULL) &&
10274 (pctxt->constructor->bucket == bkt)) {
10275 /* Report self-imports/inclusions/redefinitions. */
10276
10277 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10278 invokingNode, NULL,
10279 "The schema must not import/include/redefine itself",
10280 NULL, NULL);
10281 goto exit;
10282 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010283 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010284 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010285 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010286 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010287 relation = xmlSchemaSchemaRelationCreate();
10288 if (relation == NULL)
10289 return(-1);
10290 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10291 relation);
10292 relation->type = type;
10293
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010294 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010295 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010296 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010297 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010298 relation->importNamespace = importNamespace;
10299 if (schemaLocation == NULL) {
10300 /*
10301 * No location; this is just an import of the namespace.
10302 * Note that we don't assign a bucket to the relation
10303 * in this case.
10304 */
10305 goto exit;
10306 }
10307 targetNamespace = importNamespace;
10308 }
10309
10310 /* Did we already fetch the doc? */
10311 if (bkt != NULL) {
10312 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010313 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010314 /* We included/redefined and then try to import a schema. */
10315 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10316 invokingNode, NULL,
10317 "The schema document '%s' cannot be imported, since "
10318 "it was already included or redefined",
10319 schemaLocation, NULL);
10320 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010321 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010322 /* We imported and then try to include/redefine a schema. */
10323 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10324 invokingNode, NULL,
10325 "The schema document '%s' cannot be included or "
10326 "redefined, since it was already imported",
10327 schemaLocation, NULL);
10328 goto exit;
10329 }
10330 }
10331
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010332 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010333 /*
10334 * Given that the schemaLocation [attribute] is only a hint, it is open
10335 * to applications to ignore all but the first <import> for a given
10336 * namespace, regardless of the ·actual value· of schemaLocation, but
10337 * such a strategy risks missing useful information when new
10338 * schemaLocations are offered.
10339 *
10340 * We will use the first <import> that comes with a location.
10341 * Further <import>s *with* a location, will result in an error.
10342 * TODO: Better would be to just report a warning here, but
10343 * we'll try it this way until someone complains.
10344 *
10345 * Schema Document Location Strategy:
10346 * 3 Based on the namespace name, identify an existing schema document,
10347 * either as a resource which is an XML document or a <schema> element
10348 * information item, in some local schema repository;
10349 * 5 Attempt to resolve the namespace name to locate such a resource.
10350 *
10351 * NOTE: (3) and (5) are not supported.
10352 */
10353 if (bkt != NULL) {
10354 relation->bucket = bkt;
10355 goto exit;
10356 }
10357 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10358 importNamespace, 1);
10359
10360 if (bkt != NULL) {
10361 relation->bucket = bkt;
10362 if (bkt->schemaLocation == NULL) {
10363 /* First given location of the schema; load the doc. */
10364 bkt->schemaLocation = schemaLocation;
10365 } else {
10366 if (!xmlStrEqual(schemaLocation,
10367 bkt->schemaLocation)) {
10368 /*
10369 * Additional location given; just skip it.
10370 * URGENT TODO: We should report a warning here.
10371 * res = XML_SCHEMAP_SRC_IMPORT;
10372 */
10373 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10374 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10375 invokingNode, NULL,
10376 "Skipping import of schema located at '%s' for the "
10377 "namespace '%s', since this namespace was already "
10378 "imported with the schema located at '%s'",
10379 schemaLocation, importNamespace, bkt->schemaLocation);
10380 }
10381 goto exit;
10382 }
10383 }
10384 /*
10385 * No bucket + first location: load the doc and create a
10386 * bucket.
10387 */
10388 } else {
10389 /* <include> and <redefine> */
10390 if (bkt != NULL) {
10391
10392 if ((bkt->origTargetNamespace == NULL) &&
10393 (bkt->targetNamespace != sourceTargetNamespace)) {
10394 xmlSchemaBucketPtr chamel;
10395
10396 /*
10397 * Chameleon include/redefine: skip loading only if it was
10398 * aleady build for the targetNamespace of the including
10399 * schema.
10400 */
10401 /*
10402 * URGENT TODO: If the schema is a chameleon-include then copy
10403 * the components into the including schema and modify the
10404 * targetNamespace of those components, do nothing otherwise.
10405 * NOTE: This is currently worked-around by compiling the
10406 * chameleon for every destinct including targetNamespace; thus
10407 * not performant at the moment.
10408 * TODO: Check when the namespace in wildcards for chameleons
10409 * needs to be converted: before we built wildcard intersections
10410 * or after.
10411 * Answer: after!
10412 */
10413 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10414 schemaLocation, sourceTargetNamespace);
10415 if (chamel != NULL) {
10416 /* A fitting chameleon was already parsed; NOP. */
10417 relation->bucket = chamel;
10418 goto exit;
10419 }
10420 /*
10421 * We need to parse the chameleon again for a different
10422 * targetNamespace.
10423 * CHAMELEON TODO: Optimize this by only parsing the
10424 * chameleon once, and then copying the components to
10425 * the new targetNamespace.
10426 */
10427 bkt = NULL;
10428 } else {
10429 relation->bucket = bkt;
10430 goto exit;
10431 }
10432 }
10433 }
10434 if ((bkt != NULL) && (bkt->doc != NULL)) {
10435 PERROR_INT("xmlSchemaAddSchemaDoc",
10436 "trying to load a schema doc, but a doc is already "
10437 "assigned to the schema bucket");
10438 goto exit_failure;
10439 }
10440
10441doc_load:
10442 /*
10443 * Load the document.
10444 */
10445 if (schemaDoc != NULL) {
10446 doc = schemaDoc;
10447 /* Don' free this one, since it was provided by the caller. */
10448 preserveDoc = 1;
10449 /* TODO: Does the context or the doc hold the location? */
10450 if (schemaDoc->URL != NULL)
10451 schemaLocation = xmlDictLookup(pctxt->dict,
10452 schemaDoc->URL, -1);
10453
10454 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10455 xmlParserCtxtPtr parserCtxt;
10456
10457 parserCtxt = xmlNewParserCtxt();
10458 if (parserCtxt == NULL) {
10459 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10460 "allocating a parser context", NULL);
10461 goto exit_failure;
10462 }
10463 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10464 /*
10465 * TODO: Do we have to burden the schema parser dict with all
10466 * the content of the schema doc?
10467 */
10468 xmlDictFree(parserCtxt->dict);
10469 parserCtxt->dict = pctxt->dict;
10470 xmlDictReference(parserCtxt->dict);
10471 }
10472 if (schemaLocation != NULL) {
10473 /* Parse from file. */
10474 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10475 NULL, SCHEMAS_PARSE_OPTIONS);
10476 } else if (schemaBuffer != NULL) {
10477 /* Parse from memory buffer. */
10478 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10479 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10480 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10481 if (doc != NULL)
10482 doc->URL = schemaLocation;
10483 }
10484 /*
10485 * For <import>:
10486 * 2.1 The referent is (a fragment of) a resource which is an
10487 * XML document (see clause 1.1), which in turn corresponds to
10488 * a <schema> element information item in a well-formed information
10489 * set, which in turn corresponds to a valid schema.
10490 * TODO: (2.1) fragments of XML documents are not supported.
10491 *
10492 * 2.2 The referent is a <schema> element information item in
10493 * a well-formed information set, which in turn corresponds
10494 * to a valid schema.
10495 * TODO: (2.2) is not supported.
10496 */
10497 if (doc == NULL) {
10498 xmlErrorPtr lerr;
10499 lerr = xmlGetLastError();
10500 /*
10501 * Check if this a parser error, or if the document could
10502 * just not be located.
10503 * TODO: Try to find specific error codes to react only on
10504 * localisation failures.
10505 */
10506 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10507 /*
10508 * We assume a parser error here.
10509 */
10510 located = 1;
10511 /* TODO: Error code ?? */
10512 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10513 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10514 invokingNode, NULL,
10515 "Failed to parse the XML resource '%s'",
10516 schemaLocation, NULL);
10517 }
10518 }
10519 xmlFreeParserCtxt(parserCtxt);
10520 if ((doc == NULL) && located)
10521 goto exit_error;
10522 } else {
10523 xmlSchemaPErr(pctxt, NULL,
10524 XML_SCHEMAP_NOTHING_TO_PARSE,
10525 "No information for parsing was provided with the "
10526 "given schema parser context.\n",
10527 NULL, NULL);
10528 goto exit_failure;
10529 }
10530 /*
10531 * Preprocess the document.
10532 */
10533 if (doc != NULL) {
10534 xmlNodePtr docElem = NULL;
10535
10536 located = 1;
10537 docElem = xmlDocGetRootElement(doc);
10538 if (docElem == NULL) {
10539 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10540 invokingNode, NULL,
10541 "The document '%s' has no document element",
10542 schemaLocation, NULL);
10543 xmlFreeDoc(doc);
10544 doc = NULL;
10545 goto exit_error;
10546 }
10547 /*
10548 * Remove all the blank text nodes.
10549 */
10550 xmlSchemaCleanupDoc(pctxt, docElem);
10551 /*
10552 * Check the schema's top level element.
10553 */
10554 if (!IS_SCHEMA(docElem, "schema")) {
10555 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10556 invokingNode, NULL,
10557 "The XML document '%s' is not a schema document",
10558 schemaLocation, NULL);
10559 xmlFreeDoc(doc);
10560 doc = NULL;
10561 goto exit_error;
10562 }
10563 /*
10564 * Note that we don't apply a type check for the
10565 * targetNamespace value here.
10566 */
10567 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10568 "targetNamespace");
10569 }
10570
10571/* after_doc_loading: */
10572 if ((bkt == NULL) && located) {
10573 /* Only create a bucket if the schema was located. */
10574 bkt = xmlSchemaBucketCreate(pctxt, type,
10575 targetNamespace);
10576 if (bkt == NULL)
10577 goto exit_failure;
10578 }
10579 if (bkt != NULL) {
10580 bkt->schemaLocation = schemaLocation;
10581 bkt->located = located;
10582 if (doc != NULL) {
10583 bkt->doc = doc;
10584 bkt->targetNamespace = targetNamespace;
10585 bkt->origTargetNamespace = targetNamespace;
10586 if (preserveDoc)
10587 bkt->preserveDoc = 1;
10588 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010589 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010590 bkt->imported++;
10591 /*
10592 * Add it to the graph of schemas.
10593 */
10594 if (relation != NULL)
10595 relation->bucket = bkt;
10596 }
10597
10598exit:
10599 /*
10600 * Return the bucket explicitely; this is needed for the
10601 * main schema.
10602 */
10603 if (bucket != NULL)
10604 *bucket = bkt;
10605 return (0);
10606
10607exit_error:
10608 if ((doc != NULL) && (! preserveDoc)) {
10609 xmlFreeDoc(doc);
10610 if (bkt != NULL)
10611 bkt->doc = NULL;
10612 }
10613 return(pctxt->err);
10614
10615exit_failure:
10616 if ((doc != NULL) && (! preserveDoc)) {
10617 xmlFreeDoc(doc);
10618 if (bkt != NULL)
10619 bkt->doc = NULL;
10620 }
10621 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010622}
10623
William M. Brack2f2a6632004-08-20 23:09:47 +000010624/**
10625 * xmlSchemaParseImport:
10626 * @ctxt: a schema validation context
10627 * @schema: the schema being built
10628 * @node: a subtree containing XML Schema informations
10629 *
10630 * parse a XML schema Import definition
10631 * *WARNING* this interface is highly subject to change
10632 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010633 * Returns 0 in case of success, a positive error code if
10634 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010635 */
10636static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010637xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010638 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010639{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010640 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010641 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10642 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010643 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010644 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010645 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010646
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010647 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010648 return (-1);
10649
10650 /*
10651 * Check for illegal attributes.
10652 */
10653 attr = node->properties;
10654 while (attr != NULL) {
10655 if (attr->ns == NULL) {
10656 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10657 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10658 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010659 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010660 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010661 }
10662 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010663 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010665 }
10666 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010667 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010668 /*
10669 * Extract and validate attributes.
10670 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010671 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010672 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010673 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010674 xmlSchemaPSimpleTypeErr(pctxt,
10675 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010676 NULL, node,
10677 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010678 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010679 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010680 }
10681
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010682 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010683 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010684 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010685 xmlSchemaPSimpleTypeErr(pctxt,
10686 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010687 NULL, node,
10688 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010689 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010690 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010691 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010692 /*
10693 * And now for the children...
10694 */
10695 child = node->children;
10696 if (IS_SCHEMA(child, "annotation")) {
10697 /*
10698 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010699 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010700 */
10701 child = child->next;
10702 }
10703 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010704 xmlSchemaPContentErr(pctxt,
10705 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010706 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010707 "(annotation?)");
10708 }
10709 /*
10710 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010711 *
10712 * Note that it is important to use the original @targetNamespace
10713 * (or none at all), to rule out imports of schemas _with_ a
10714 * @targetNamespace if the importing schema is a chameleon schema
10715 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010716 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010717 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010718 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010719 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010720 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10721 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010722 * targetNamespace [attribute].
10723 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010724 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010725 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010726 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010727 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010728 "The value of the attribute 'namespace' must not match "
10729 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010730 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010731 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010732 }
10733 } else {
10734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010736 * <schema> must have a targetNamespace [attribute].
10737 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010738 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010739 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010740 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010741 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010742 "The attribute 'namespace' must be existent if "
10743 "the importing schema has no target namespace",
10744 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010745 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010746 }
10747 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010748 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010749 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010750 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010751 if (schemaLocation != NULL)
10752 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10753 schemaLocation, node);
10754 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010755 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010756 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010757
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010758 if (ret != 0)
10759 return(ret);
10760
10761 /*
10762 * For <import>: "It is *not* an error for the application
10763 * schema reference strategy to fail."
10764 * So just don't parse if no schema document was found.
10765 * Note that we will get no bucket if the schema could not be
10766 * located or if there was no schemaLocation.
10767 */
10768 if ((bucket == NULL) && (schemaLocation != NULL)) {
10769 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10770 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10771 node, NULL,
10772 "Failed to locate a schema at location '%s'. "
10773 "Skipping the import", schemaLocation, NULL, NULL);
10774 }
10775
10776 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10777 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10778 }
10779
10780 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010781}
10782
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010783static int
10784xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10785 xmlSchemaPtr schema,
10786 xmlNodePtr node,
10787 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010788 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010789{
10790 xmlAttrPtr attr;
10791
10792 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10793 (schemaLocation == NULL))
10794 return (-1);
10795
10796 *schemaLocation = NULL;
10797 /*
10798 * Check for illegal attributes.
10799 * Applies for both <include> and <redefine>.
10800 */
10801 attr = node->properties;
10802 while (attr != NULL) {
10803 if (attr->ns == NULL) {
10804 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10805 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10806 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010807 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010808 }
10809 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10810 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010811 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010812 }
10813 attr = attr->next;
10814 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010815 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010816 /*
10817 * Preliminary step, extract the URI-Reference and make an URI
10818 * from the base.
10819 */
10820 /*
10821 * Attribute "schemaLocation" is mandatory.
10822 */
10823 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10824 if (attr != NULL) {
10825 xmlChar *base = NULL;
10826 xmlChar *uri = NULL;
10827
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010828 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010829 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10830 (const xmlChar **) schemaLocation) != 0)
10831 goto exit_error;
10832 base = xmlNodeGetBase(node->doc, node);
10833 if (base == NULL) {
10834 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10835 } else {
10836 uri = xmlBuildURI(*schemaLocation, base);
10837 xmlFree(base);
10838 }
10839 if (uri == NULL) {
10840 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10841 "could not build an URI from the schemaLocation")
10842 goto exit_failure;
10843 }
10844 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10845 xmlFree(uri);
10846 } else {
10847 xmlSchemaPMissingAttrErr(pctxt,
10848 XML_SCHEMAP_S4S_ATTR_MISSING,
10849 NULL, node, "schemaLocation", NULL);
10850 goto exit_error;
10851 }
10852 /*
10853 * Report self-inclusion and self-redefinition.
10854 */
10855 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010856 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010857 xmlSchemaPCustomErr(pctxt,
10858 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010859 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010860 "The schema document '%s' cannot redefine itself.",
10861 *schemaLocation);
10862 } else {
10863 xmlSchemaPCustomErr(pctxt,
10864 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010865 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010866 "The schema document '%s' cannot include itself.",
10867 *schemaLocation);
10868 }
10869 goto exit_error;
10870 }
10871
10872 return(0);
10873exit_error:
10874 return(pctxt->err);
10875exit_failure:
10876 return(-1);
10877}
10878
10879static int
10880xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10881 xmlSchemaPtr schema,
10882 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010883 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010884{
10885 xmlNodePtr child = NULL;
10886 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010887 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010888 int isChameleon = 0, wasChameleon = 0;
10889 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010890
10891 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10892 return (-1);
10893
10894 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010895 * Parse attributes. Note that the returned schemaLocation will
10896 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010897 */
10898 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010899 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010901 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010902 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010903 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010904 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010905 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10906 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010907 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010908 return(res);
10909 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010910 * If we get no schema bucket back, then this means that the schema
10911 * document could not be located or was broken XML or was not
10912 * a schema document.
10913 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010914 if ((bucket == NULL) || (bucket->doc == NULL)) {
10915 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10916 /*
10917 * WARNING for <include>:
10918 * We will raise an error if the schema cannot be located
10919 * for inclusions, since the that was the feedback from the
10920 * schema people. I.e. the following spec piece will *not* be
10921 * satisfied:
10922 * SPEC src-include: "It is not an error for the ·actual value· of the
10923 * schemaLocation [attribute] to fail to resolve it all, in which
10924 * case no corresponding inclusion is performed.
10925 * So do we need a warning report here?"
10926 */
10927 res = XML_SCHEMAP_SRC_INCLUDE;
10928 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10929 node, NULL,
10930 "Failed to load the document '%s' for inclusion",
10931 schemaLocation, NULL);
10932 } else {
10933 /*
10934 * NOTE: This was changed to raise an error even if no redefinitions
10935 * are specified.
10936 *
10937 * SPEC src-redefine (1)
10938 * "If there are any element information items among the [children]
10939 * other than <annotation> then the ·actual value· of the
10940 * schemaLocation [attribute] must successfully resolve."
10941 * TODO: Ask the WG if a the location has always to resolve
10942 * here as well!
10943 */
10944 res = XML_SCHEMAP_SRC_REDEFINE;
10945 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10946 node, NULL,
10947 "Failed to load the document '%s' for redefinition",
10948 schemaLocation, NULL);
10949 }
10950 } else {
10951 /*
10952 * Check targetNamespace sanity before parsing the new schema.
10953 * TODO: Note that we won't check further content if the
10954 * targetNamespace was bad.
10955 */
10956 if (bucket->origTargetNamespace != NULL) {
10957 /*
10958 * SPEC src-include (2.1)
10959 * "SII has a targetNamespace [attribute], and its ·actual
10960 * value· is identical to the ·actual value· of the targetNamespace
10961 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10962 */
10963 if (pctxt->targetNamespace == NULL) {
10964 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10965 XML_SCHEMAP_SRC_INCLUDE,
10966 node, NULL,
10967 "The target namespace of the included/redefined schema "
10968 "'%s' has to be absent, since the including/redefining "
10969 "schema has no target namespace",
10970 schemaLocation, NULL);
10971 goto exit_error;
10972 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10973 pctxt->targetNamespace)) {
10974 /* TODO: Change error function. */
10975 xmlSchemaPCustomErrExt(pctxt,
10976 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010977 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010978 "The target namespace '%s' of the included/redefined "
10979 "schema '%s' differs from '%s' of the "
10980 "including/redefining schema",
10981 bucket->origTargetNamespace, schemaLocation,
10982 pctxt->targetNamespace);
10983 goto exit_error;
10984 }
10985 } else if (pctxt->targetNamespace != NULL) {
10986 /*
10987 * Chameleons: the original target namespace will
10988 * differ from the resulting namespace.
10989 */
10990 isChameleon = 1;
10991 if (bucket->parsed &&
10992 (bucket->targetNamespace != pctxt->targetNamespace)) {
10993 /*
10994 * This is a sanity check, I dunno yet if this can happen.
10995 */
10996 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10997 "trying to use an already parsed schema for a "
10998 "different targetNamespace");
10999 return(-1);
11000 }
11001 bucket->targetNamespace = pctxt->targetNamespace;
11002 }
11003 }
11004 /*
11005 * Parse the schema.
11006 */
11007 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11008 if (isChameleon) {
11009 /* TODO: Get rid of this flag on the schema itself. */
11010 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11011 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11012 } else
11013 wasChameleon = 1;
11014 }
11015 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11016 /* Restore chameleon flag. */
11017 if (isChameleon && (!wasChameleon))
11018 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11019 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011020 /*
11021 * And now for the children...
11022 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011023 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011024 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011025 /*
11026 * Parse (simpleType | complexType | group | attributeGroup))*
11027 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011028 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011029 /*
11030 * How to proceed if the redefined schema was not located?
11031 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011032 pctxt->isRedefine = 1;
11033 while (IS_SCHEMA(child, "annotation") ||
11034 IS_SCHEMA(child, "simpleType") ||
11035 IS_SCHEMA(child, "complexType") ||
11036 IS_SCHEMA(child, "group") ||
11037 IS_SCHEMA(child, "attributeGroup")) {
11038 if (IS_SCHEMA(child, "annotation")) {
11039 /*
11040 * TODO: discard or not?
11041 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011042 } else if (IS_SCHEMA(child, "simpleType")) {
11043 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11044 } else if (IS_SCHEMA(child, "complexType")) {
11045 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011046 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011047 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011048 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011049 xmlSchemaParseModelGroupDefinition(pctxt,
11050 schema, child);
11051 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011052 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011053 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11054 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011055 }
11056 child = child->next;
11057 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011058 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011059 pctxt->isRedefine = 0;
11060 } else {
11061 if (IS_SCHEMA(child, "annotation")) {
11062 /*
11063 * TODO: discard or not?
11064 */
11065 child = child->next;
11066 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011067 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011068 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011069 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011070 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11071 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011072 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011073 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11074 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011075 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011076 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011077 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011078 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011079 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011080 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011081
11082exit_error:
11083 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011084}
11085
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011086static int
11087xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11088 xmlNodePtr node)
11089{
11090 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011091#ifndef ENABLE_REDEFINE
11092 TODO
11093 return(0);
11094#endif
11095 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11096 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011097 if (res != 0)
11098 return(res);
11099 return(0);
11100}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011101
11102static int
11103xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11104 xmlNodePtr node)
11105{
11106 int res;
11107
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011108 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11109 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011110 if (res != 0)
11111 return(res);
11112 return(0);
11113}
11114
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011115/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011116 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011117 * @ctxt: a schema validation context
11118 * @schema: the schema being built
11119 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011120 * @type: the "compositor" type
11121 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011122 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011123 * parse a XML schema Sequence definition.
11124 * Applies parts of:
11125 * Schema Representation Constraint:
11126 * Redefinition Constraints and Semantics (src-redefine)
11127 * (6.1), (6.1.1), (6.1.2)
11128 *
11129 * Schema Component Constraint:
11130 * All Group Limited (cos-all-limited) (2)
11131 * TODO: Actually this should go to component-level checks,
11132 * but is done here due to performance. Move it to an other layer
11133 * is schema construction via an API is implemented.
11134 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011135 * *WARNING* this interface is highly subject to change
11136 *
William M. Bracke7091952004-05-11 15:09:58 +000011137 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011138 * 1 in case of success.
11139 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011140static xmlSchemaTreeItemPtr
11141xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11142 xmlNodePtr node, xmlSchemaTypeType type,
11143 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011144{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011145 xmlSchemaModelGroupPtr item;
11146 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011147 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011148 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011149 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011150
11151 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011152 return (NULL);
11153 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011154 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011155 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011156 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 if (item == NULL)
11158 return (NULL);
11159
11160 if (withParticle) {
11161 if (type == XML_SCHEMA_TYPE_ALL) {
11162 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011163 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 } else {
11165 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011166 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11167 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11168 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011170 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11171 /*
11172 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 */
11174 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11175 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011176 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011177 particle->children = (xmlSchemaTreeItemPtr) item;
11178 /*
11179 * Check for illegal attributes.
11180 */
11181 attr = node->properties;
11182 while (attr != NULL) {
11183 if (attr->ns == NULL) {
11184 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11185 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11186 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011187 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011189 }
11190 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011191 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011192 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011193 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011194 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011195 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 } else {
11197 /*
11198 * Check for illegal attributes.
11199 */
11200 attr = node->properties;
11201 while (attr != NULL) {
11202 if (attr->ns == NULL) {
11203 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011204 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011206 }
11207 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011208 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 }
11211 attr = attr->next;
11212 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011213 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011214
William M. Brack2f2a6632004-08-20 23:09:47 +000011215 /*
11216 * Extract and validate attributes.
11217 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011218 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011219 /*
11220 * And now for the children...
11221 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011222 child = node->children;
11223 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011224 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011227 if (type == XML_SCHEMA_TYPE_ALL) {
11228 xmlSchemaParticlePtr part, last = NULL;
11229
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011230 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011231 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011232 schema, child, &isElemRef, 0);
11233 /*
11234 * SPEC cos-all-limited (2)
11235 * "The {max occurs} of all the particles in the {particles}
11236 * of the ('all') group must be 0 or 1.
11237 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011239 if (isElemRef)
11240 hasRefs++;
11241 if (part->minOccurs > 1) {
11242 xmlSchemaPCustomErr(ctxt,
11243 XML_SCHEMAP_COS_ALL_LIMITED,
11244 NULL, child,
11245 "Invalid value for minOccurs (must be 0 or 1)",
11246 NULL);
11247 /* Reset to 1. */
11248 part->minOccurs = 1;
11249 }
11250 if (part->maxOccurs > 1) {
11251 xmlSchemaPCustomErr(ctxt,
11252 XML_SCHEMAP_COS_ALL_LIMITED,
11253 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 "Invalid value for maxOccurs (must be 0 or 1)",
11255 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011256 /* Reset to 1. */
11257 part->maxOccurs = 1;
11258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 if (last == NULL)
11260 item->children = (xmlSchemaTreeItemPtr) part;
11261 else
11262 last->next = (xmlSchemaTreeItemPtr) part;
11263 last = part;
11264 }
11265 child = child->next;
11266 }
11267 if (child != NULL) {
11268 xmlSchemaPContentErr(ctxt,
11269 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011270 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 "(annotation?, (annotation?, element*)");
11272 }
11273 } else {
11274 /* choice + sequence */
11275 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11276
11277 while ((IS_SCHEMA(child, "element")) ||
11278 (IS_SCHEMA(child, "group")) ||
11279 (IS_SCHEMA(child, "any")) ||
11280 (IS_SCHEMA(child, "choice")) ||
11281 (IS_SCHEMA(child, "sequence"))) {
11282
11283 if (IS_SCHEMA(child, "element")) {
11284 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011285 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11286 if (part && isElemRef)
11287 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011288 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011289 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011291 if (part != NULL)
11292 hasRefs++;
11293 /*
11294 * Handle redefinitions.
11295 */
11296 if (ctxt->isRedefine && ctxt->redef &&
11297 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11298 part && part->children)
11299 {
11300 if ((xmlSchemaGetQNameRefName(part->children) ==
11301 ctxt->redef->refName) &&
11302 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11303 ctxt->redef->refTargetNs))
11304 {
11305 /*
11306 * SPEC src-redefine:
11307 * (6.1) "If it has a <group> among its contents at
11308 * some level the ·actual value· of whose ref
11309 * [attribute] is the same as the ·actual value· of
11310 * its own name attribute plus target namespace, then
11311 * all of the following must be true:"
11312 * (6.1.1) "It must have exactly one such group."
11313 */
11314 if (ctxt->redefCounter != 0) {
11315 xmlChar *str = NULL;
11316
11317 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11318 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11319 "The redefining model group definition "
11320 "'%s' must not contain more than one "
11321 "reference to the redefined definition",
11322 xmlSchemaFormatQName(&str,
11323 ctxt->redef->refTargetNs,
11324 ctxt->redef->refName),
11325 NULL);
11326 FREE_AND_NULL(str)
11327 part = NULL;
11328 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11329 ((WXS_PARTICLE(part))->maxOccurs != 1))
11330 {
11331 xmlChar *str = NULL;
11332 /*
11333 * SPEC src-redefine:
11334 * (6.1.2) "The ·actual value· of both that
11335 * group's minOccurs and maxOccurs [attribute]
11336 * must be 1 (or ·absent·).
11337 */
11338 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11339 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11340 "The redefining model group definition "
11341 "'%s' must not contain a reference to the "
11342 "redefined definition with a "
11343 "maxOccurs/minOccurs other than 1",
11344 xmlSchemaFormatQName(&str,
11345 ctxt->redef->refTargetNs,
11346 ctxt->redef->refName),
11347 NULL);
11348 FREE_AND_NULL(str)
11349 part = NULL;
11350 }
11351 ctxt->redef->reference = WXS_BASIC_CAST part;
11352 ctxt->redefCounter++;
11353 }
11354 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011356 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 xmlSchemaParseAny(ctxt, schema, child);
11358 } else if (IS_SCHEMA(child, "choice")) {
11359 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11360 XML_SCHEMA_TYPE_CHOICE, 1);
11361 } else if (IS_SCHEMA(child, "sequence")) {
11362 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11363 XML_SCHEMA_TYPE_SEQUENCE, 1);
11364 }
11365 if (part != NULL) {
11366 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011367 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011368 else
11369 last->next = part;
11370 last = part;
11371 }
11372 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011373 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011374 if (child != NULL) {
11375 xmlSchemaPContentErr(ctxt,
11376 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011377 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011378 "(annotation?, (element | group | choice | sequence | any)*)");
11379 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011380 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011381 if ((max == 0) && (min == 0))
11382 return (NULL);
11383 if (hasRefs) {
11384 /*
11385 * We need to resolve references.
11386 */
11387 WXS_ADD_PENDING(ctxt, item);
11388 }
11389 if (withParticle)
11390 return ((xmlSchemaTreeItemPtr) particle);
11391 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011392 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011393}
11394
11395/**
11396 * xmlSchemaParseRestriction:
11397 * @ctxt: a schema validation context
11398 * @schema: the schema being built
11399 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011400 *
11401 * parse a XML schema Restriction definition
11402 * *WARNING* this interface is highly subject to change
11403 *
11404 * Returns the type definition or NULL in case of error
11405 */
11406static xmlSchemaTypePtr
11407xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011409{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011411 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011412 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011413
11414 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11415 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011416 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011417 type = ctxt->ctxtType;
11418 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011419
11420 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011421 * Check for illegal attributes.
11422 */
11423 attr = node->properties;
11424 while (attr != NULL) {
11425 if (attr->ns == NULL) {
11426 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11427 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011428 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011429 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011430 }
11431 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011433 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011434 }
11435 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 /*
11438 * Extract and validate attributes.
11439 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011440 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011441 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011442 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011443 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011444 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011445 * Extract the base type. The "base" attribute is mandatory if inside
11446 * a complex type or if redefining.
11447 *
11448 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 * among its [children]), the simple type definition which is
11450 * the {content type} of the type definition ·resolved· to by
11451 * the ·actual value· of the base [attribute]"
11452 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011453 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011454 &(type->baseNs), &(type->base)) == 0)
11455 {
11456 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11457 xmlSchemaPMissingAttrErr(ctxt,
11458 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011459 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011460 } else if ((ctxt->isRedefine) &&
11461 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11462 {
11463 if (type->base == NULL) {
11464 xmlSchemaPMissingAttrErr(ctxt,
11465 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011466 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011467 } else if ((! xmlStrEqual(type->base, type->name)) ||
11468 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11469 {
11470 xmlChar *str1 = NULL, *str2 = NULL;
11471 /*
11472 * REDEFINE: SPEC src-redefine (5)
11473 * "Within the [children], each <simpleType> must have a
11474 * <restriction> among its [children] ... the ·actual value· of
11475 * whose base [attribute] must be the same as the ·actual value·
11476 * of its own name attribute plus target namespace;"
11477 */
11478 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011479 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011480 "value '%s' of the 'base' attribute does not match the "
11481 "type's designation '%s'",
11482 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11483 xmlSchemaFormatQName(&str1, type->targetNamespace,
11484 type->name), NULL);
11485 FREE_AND_NULL(str1);
11486 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011487 /* Avoid confusion and erase the values. */
11488 type->base = NULL;
11489 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011490 }
11491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011492 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011493 /*
11494 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011495 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011496 child = node->children;
11497 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498 /*
11499 * Add the annotation to the simple type ancestor.
11500 */
11501 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011502 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011503 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011504 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011505 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11506 /*
11507 * Corresponds to <simpleType><restriction><simpleType>.
11508 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011509 if (IS_SCHEMA(child, "simpleType")) {
11510 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011511 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011512 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 * Either the base [attribute] or the simpleType [child] of the
11514 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011515 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011516 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011517 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011518 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 "The attribute 'base' and the <simpleType> child are "
11520 "mutually exclusive", NULL);
11521 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011522 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011523 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011525 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011526 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011527 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011529 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 "Either the attribute 'base' or a <simpleType> child "
11531 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011533 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11534 /*
11535 * Corresponds to <complexType><complexContent><restriction>...
11536 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 * Model groups <all>, <choice> and <sequence>.
11539 */
11540 if (IS_SCHEMA(child, "all")) {
11541 type->subtypes = (xmlSchemaTypePtr)
11542 xmlSchemaParseModelGroup(ctxt, schema, child,
11543 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 } else if (IS_SCHEMA(child, "choice")) {
11546 type->subtypes = (xmlSchemaTypePtr)
11547 xmlSchemaParseModelGroup(ctxt,
11548 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11549 child = child->next;
11550 } else if (IS_SCHEMA(child, "sequence")) {
11551 type->subtypes = (xmlSchemaTypePtr)
11552 xmlSchemaParseModelGroup(ctxt, schema, child,
11553 XML_SCHEMA_TYPE_SEQUENCE, 1);
11554 child = child->next;
11555 /*
11556 * Model group reference <group>.
11557 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011558 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011559 type->subtypes = (xmlSchemaTypePtr)
11560 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011561 /*
11562 * Note that the reference will be resolved in
11563 * xmlSchemaResolveTypeReferences();
11564 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 child = child->next;
11566 }
11567 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011568 /*
11569 * Corresponds to <complexType><simpleContent><restriction>...
11570 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011571 * "1.1 the simple type definition corresponding to the <simpleType>
11572 * among the [children] of <restriction> if there is one;"
11573 */
11574 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575 /*
11576 * We will store the to-be-restricted simple type in
11577 * type->contentTypeDef *temporarily*.
11578 */
11579 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011580 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011581 if ( type->contentTypeDef == NULL)
11582 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011583 child = child->next;
11584 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011585 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011586
11587 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 /*
11591 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011592 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011598 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11600 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011601 * *Single Facet Value*
11602 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011603 while ((IS_SCHEMA(child, "minInclusive")) ||
11604 (IS_SCHEMA(child, "minExclusive")) ||
11605 (IS_SCHEMA(child, "maxInclusive")) ||
11606 (IS_SCHEMA(child, "maxExclusive")) ||
11607 (IS_SCHEMA(child, "totalDigits")) ||
11608 (IS_SCHEMA(child, "fractionDigits")) ||
11609 (IS_SCHEMA(child, "pattern")) ||
11610 (IS_SCHEMA(child, "enumeration")) ||
11611 (IS_SCHEMA(child, "whiteSpace")) ||
11612 (IS_SCHEMA(child, "length")) ||
11613 (IS_SCHEMA(child, "maxLength")) ||
11614 (IS_SCHEMA(child, "minLength"))) {
11615 facet = xmlSchemaParseFacet(ctxt, schema, child);
11616 if (facet != NULL) {
11617 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011618 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011619 else
11620 lastfacet->next = facet;
11621 lastfacet = facet;
11622 lastfacet->next = NULL;
11623 }
11624 child = child->next;
11625 }
11626 /*
11627 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628 */
11629 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011630 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11631
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011632 facet = type->facets;
11633 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011634 facetLink = (xmlSchemaFacetLinkPtr)
11635 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011636 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011637 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638 xmlFree(facetLink);
11639 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011640 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011641 facetLink->facet = facet;
11642 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011643 if (lastFacetLink == NULL)
11644 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011645 else
11646 lastFacetLink->next = facetLink;
11647 lastFacetLink = facetLink;
11648 facet = facet->next;
11649 } while (facet != NULL);
11650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011651 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011652 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11653 /*
11654 * Attribute uses/declarations.
11655 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011656 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11657 (xmlSchemaItemListPtr *) &(type->attrUses),
11658 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11659 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011660 /*
11661 * Attribute wildcard.
11662 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011663 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011664 type->attributeWildcard =
11665 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011666 child = child->next;
11667 }
11668 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011669 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011670 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11671 xmlSchemaPContentErr(ctxt,
11672 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011673 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011674 "annotation?, (group | all | choice | sequence)?, "
11675 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011676 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011677 xmlSchemaPContentErr(ctxt,
11678 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011679 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011680 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11681 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11682 "length | minLength | maxLength | enumeration | whiteSpace | "
11683 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11684 } else {
11685 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011686 xmlSchemaPContentErr(ctxt,
11687 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011688 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011689 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11690 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11691 "length | minLength | maxLength | enumeration | whiteSpace | "
11692 "pattern)*))");
11693 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011694 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011695 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011696}
11697
11698/**
11699 * xmlSchemaParseExtension:
11700 * @ctxt: a schema validation context
11701 * @schema: the schema being built
11702 * @node: a subtree containing XML Schema informations
11703 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011704 * Parses an <extension>, which is found inside a
11705 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011706 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011707 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011708 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011709 */
11710static xmlSchemaTypePtr
11711xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011712 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011713{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011714 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011715 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011716 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011717
11718 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11719 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011720 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 type = ctxt->ctxtType;
11722 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011723
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 /*
11725 * Check for illegal attributes.
11726 */
11727 attr = node->properties;
11728 while (attr != NULL) {
11729 if (attr->ns == NULL) {
11730 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11731 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011732 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011733 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011734 }
11735 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011736 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011738 }
11739 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011740 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011741
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011742 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011743
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011744 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011746 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011747 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11748 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011750 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751 XML_SCHEMAP_S4S_ATTR_MISSING,
11752 NULL, node, "base", NULL);
11753 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011754 /*
11755 * And now for the children...
11756 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011757 child = node->children;
11758 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011759 /*
11760 * Add the annotation to the type ancestor.
11761 */
11762 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011763 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011764 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011765 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011766 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11767 /*
11768 * Corresponds to <complexType><complexContent><extension>... and:
11769 *
11770 * Model groups <all>, <choice>, <sequence> and <group>.
11771 */
11772 if (IS_SCHEMA(child, "all")) {
11773 type->subtypes = (xmlSchemaTypePtr)
11774 xmlSchemaParseModelGroup(ctxt, schema,
11775 child, XML_SCHEMA_TYPE_ALL, 1);
11776 child = child->next;
11777 } else if (IS_SCHEMA(child, "choice")) {
11778 type->subtypes = (xmlSchemaTypePtr)
11779 xmlSchemaParseModelGroup(ctxt, schema,
11780 child, XML_SCHEMA_TYPE_CHOICE, 1);
11781 child = child->next;
11782 } else if (IS_SCHEMA(child, "sequence")) {
11783 type->subtypes = (xmlSchemaTypePtr)
11784 xmlSchemaParseModelGroup(ctxt, schema,
11785 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11786 child = child->next;
11787 } else if (IS_SCHEMA(child, "group")) {
11788 type->subtypes = (xmlSchemaTypePtr)
11789 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011790 /*
11791 * Note that the reference will be resolved in
11792 * xmlSchemaResolveTypeReferences();
11793 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011794 child = child->next;
11795 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011796 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011797 if (child != NULL) {
11798 /*
11799 * Attribute uses/declarations.
11800 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011801 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11802 (xmlSchemaItemListPtr *) &(type->attrUses),
11803 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11804 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011805 /*
11806 * Attribute wildcard.
11807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011808 if (IS_SCHEMA(child, "anyAttribute")) {
11809 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011810 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11811 child = child->next;
11812 }
11813 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011814 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011815 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11816 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817 xmlSchemaPContentErr(ctxt,
11818 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011819 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011820 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011821 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011822 } else {
11823 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824 xmlSchemaPContentErr(ctxt,
11825 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011826 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011827 "(annotation?, ((attribute | attributeGroup)*, "
11828 "anyAttribute?))");
11829 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011830 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011831 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011832}
11833
11834/**
11835 * xmlSchemaParseSimpleContent:
11836 * @ctxt: a schema validation context
11837 * @schema: the schema being built
11838 * @node: a subtree containing XML Schema informations
11839 *
11840 * parse a XML schema SimpleContent definition
11841 * *WARNING* this interface is highly subject to change
11842 *
11843 * Returns the type definition or NULL in case of error
11844 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011845static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011846xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011847 xmlSchemaPtr schema, xmlNodePtr node,
11848 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011849{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011850 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011851 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011852 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011853
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011854 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11855 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011856 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011857 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011858 /* Not a component, don't create it. */
11859 type = ctxt->ctxtType;
11860 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11861 /*
11862 * Check for illegal attributes.
11863 */
11864 attr = node->properties;
11865 while (attr != NULL) {
11866 if (attr->ns == NULL) {
11867 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011868 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011869 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011870 }
11871 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011872 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011873 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011874 }
11875 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011876 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011877
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011878 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011879
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011880 /*
11881 * And now for the children...
11882 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011883 child = node->children;
11884 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011885 /*
11886 * Add the annotation to the complex type ancestor.
11887 */
11888 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011889 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011890 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011891 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011892 if (child == NULL) {
11893 xmlSchemaPContentErr(ctxt,
11894 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011895 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011896 "(annotation?, (restriction | extension))");
11897 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011898 if (child == NULL) {
11899 xmlSchemaPContentErr(ctxt,
11900 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011901 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011902 "(annotation?, (restriction | extension))");
11903 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011904 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011905 xmlSchemaParseRestriction(ctxt, schema, child,
11906 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011907 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011909 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011910 xmlSchemaParseExtension(ctxt, schema, child,
11911 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011912 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011913 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915 if (child != NULL) {
11916 xmlSchemaPContentErr(ctxt,
11917 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011918 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011919 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011920 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011921 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011922}
11923
11924/**
11925 * xmlSchemaParseComplexContent:
11926 * @ctxt: a schema validation context
11927 * @schema: the schema being built
11928 * @node: a subtree containing XML Schema informations
11929 *
11930 * parse a XML schema ComplexContent definition
11931 * *WARNING* this interface is highly subject to change
11932 *
11933 * Returns the type definition or NULL in case of error
11934 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011935static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011936xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011937 xmlSchemaPtr schema, xmlNodePtr node,
11938 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011939{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011940 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011941 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011942 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011943
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011944 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11945 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011946 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011947 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011948 /* Not a component, don't create it. */
11949 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011950 /*
11951 * Check for illegal attributes.
11952 */
11953 attr = node->properties;
11954 while (attr != NULL) {
11955 if (attr->ns == NULL) {
11956 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011957 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011958 {
11959 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011960 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011961 }
11962 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11963 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011964 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011965 }
11966 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011968
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011969 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011970
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011971 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011972 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011973 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011974 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011975 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11976 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011977 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011978 child = node->children;
11979 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011980 /*
11981 * Add the annotation to the complex type ancestor.
11982 */
11983 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011984 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011985 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011986 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011987 if (child == NULL) {
11988 xmlSchemaPContentErr(ctxt,
11989 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011990 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011991 NULL, "(annotation?, (restriction | extension))");
11992 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011993 if (child == NULL) {
11994 xmlSchemaPContentErr(ctxt,
11995 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011996 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011997 NULL, "(annotation?, (restriction | extension))");
11998 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011999 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012000 xmlSchemaParseRestriction(ctxt, schema, child,
12001 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012002 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012003 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012004 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012005 xmlSchemaParseExtension(ctxt, schema, child,
12006 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012007 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012008 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012009 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012010 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012011 xmlSchemaPContentErr(ctxt,
12012 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012013 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012014 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012015 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012016 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012017}
12018
12019/**
12020 * xmlSchemaParseComplexType:
12021 * @ctxt: a schema validation context
12022 * @schema: the schema being built
12023 * @node: a subtree containing XML Schema informations
12024 *
12025 * parse a XML schema Complex Type definition
12026 * *WARNING* this interface is highly subject to change
12027 *
12028 * Returns the type definition or NULL in case of error
12029 */
12030static xmlSchemaTypePtr
12031xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012032 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012034 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012035 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012036 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012037 xmlAttrPtr attr;
12038 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012039#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012040 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012041#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012042 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012043
Daniel Veillard4255d502002-04-16 15:50:10 +000012044
12045 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12046 return (NULL);
12047
Daniel Veillard01fa6152004-06-29 17:04:39 +000012048 ctxtType = ctxt->ctxtType;
12049
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012050 if (topLevel) {
12051 attr = xmlSchemaGetPropNode(node, "name");
12052 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012053 xmlSchemaPMissingAttrErr(ctxt,
12054 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012055 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012056 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012057 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12058 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012059 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012061
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012062 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012063 /*
12064 * Parse as local complex type definition.
12065 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012066#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012067 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012068 type = xmlSchemaAddType(ctxt, schema,
12069 XML_SCHEMA_TYPE_COMPLEX,
12070 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012071 ctxt->targetNamespace, node, 0);
12072#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012073 type = xmlSchemaAddType(ctxt, schema,
12074 XML_SCHEMA_TYPE_COMPLEX,
12075 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012076#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012077 if (type == NULL)
12078 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012079 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012080 type->node = node;
12081 type->type = XML_SCHEMA_TYPE_COMPLEX;
12082 /*
12083 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012084 */
12085 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012086 /*
12087 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012088 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012089 type = xmlSchemaAddType(ctxt, schema,
12090 XML_SCHEMA_TYPE_COMPLEX,
12091 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012092 if (type == NULL)
12093 return (NULL);
12094 type->node = node;
12095 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012097 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012098 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012099 /*
12100 * Handle attributes.
12101 */
12102 attr = node->properties;
12103 while (attr != NULL) {
12104 if (attr->ns == NULL) {
12105 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12106 /*
12107 * Attribute "id".
12108 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012109 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012110 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12111 /*
12112 * Attribute "mixed".
12113 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012114 if (xmlSchemaPGetBoolNodeValue(ctxt,
12115 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12117 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012118 /*
12119 * Attributes of global complex type definitions.
12120 */
12121 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12122 /* Pass. */
12123 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12124 /*
12125 * Attribute "abstract".
12126 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012127 if (xmlSchemaPGetBoolNodeValue(ctxt,
12128 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012129 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12130 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12131 /*
12132 * Attribute "final".
12133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012134 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012135 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012136 if (xmlSchemaPValAttrBlockFinal(attrValue,
12137 &(type->flags),
12138 -1,
12139 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12140 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12141 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012142 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012143 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012144 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012145 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012147 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012148 } else
12149 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012150 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12151 /*
12152 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 */
12154 attrValue = xmlSchemaGetNodeContent(ctxt,
12155 (xmlNodePtr) attr);
12156 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012157 -1,
12158 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012160 -1, -1, -1) != 0) {
12161 xmlSchemaPSimpleTypeErr(ctxt,
12162 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012163 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012165 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 } else
12167 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012168 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012170 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172 } else {
12173 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012175 }
12176 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012177 xmlSchemaPIllegalAttrErr(ctxt,
12178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012179 }
12180 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012182 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012183 /*
12184 * Apply default "block" values.
12185 */
12186 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12187 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12188 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12189 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12190 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012191 if (! final) {
12192 /*
12193 * Apply default "block" values.
12194 */
12195 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12196 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12197 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12198 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12199 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012200 /*
12201 * And now for the children...
12202 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012203 child = node->children;
12204 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012205 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012206 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012207 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012208 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012209 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012211 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012213 * Specifying mixed='true' when the <simpleContent>
12214 * alternative is chosen has no effect
12215 */
William M. Bracke7091952004-05-11 15:09:58 +000012216 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12217 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012218 xmlSchemaParseSimpleContent(ctxt, schema, child,
12219 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012220 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012221 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012222 /*
12223 * <complexType><complexContent>...
12224 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012225 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012226 xmlSchemaParseComplexContent(ctxt, schema, child,
12227 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012229 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012230 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012231 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12232 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012233 * SPEC
12234 * "...the third alternative (neither <simpleContent> nor
12235 * <complexContent>) is chosen. This case is understood as shorthand
12236 * for complex content restricting the ·ur-type definition·, and the
12237 * details of the mappings should be modified as necessary.
12238 */
12239 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12240 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012241 /*
12242 * Parse model groups.
12243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012244 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012245 type->subtypes = (xmlSchemaTypePtr)
12246 xmlSchemaParseModelGroup(ctxt, schema, child,
12247 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012248 child = child->next;
12249 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012250 type->subtypes = (xmlSchemaTypePtr)
12251 xmlSchemaParseModelGroup(ctxt, schema, child,
12252 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012253 child = child->next;
12254 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012255 type->subtypes = (xmlSchemaTypePtr)
12256 xmlSchemaParseModelGroup(ctxt, schema, child,
12257 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012258 child = child->next;
12259 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012260 type->subtypes = (xmlSchemaTypePtr)
12261 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012262 /*
12263 * Note that the reference will be resolved in
12264 * xmlSchemaResolveTypeReferences();
12265 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012266 child = child->next;
12267 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012268 /*
12269 * Parse attribute decls/refs.
12270 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012271 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12272 (xmlSchemaItemListPtr *) &(type->attrUses),
12273 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12274 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012275 /*
12276 * Parse attribute wildcard.
12277 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012278 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012279 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12280 child = child->next;
12281 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012282 }
12283 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012284 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012286 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012287 NULL, "(annotation?, (simpleContent | complexContent | "
12288 "((group | all | choice | sequence)?, ((attribute | "
12289 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012290 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012291 /*
12292 * REDEFINE: SPEC src-redefine (5)
12293 */
12294 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12295 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012296 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012297 "<complexType> must have a <restriction> or <extension> "
12298 "grand-child", NULL);
12299 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012300 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012301 return (type);
12302}
12303
Daniel Veillard4255d502002-04-16 15:50:10 +000012304/************************************************************************
12305 * *
12306 * Validating using Schemas *
12307 * *
12308 ************************************************************************/
12309
12310/************************************************************************
12311 * *
12312 * Reading/Writing Schemas *
12313 * *
12314 ************************************************************************/
12315
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012316#if 0 /* Will be enabled if it is clear what options are needed. */
12317/**
12318 * xmlSchemaParserCtxtSetOptions:
12319 * @ctxt: a schema parser context
12320 * @options: a combination of xmlSchemaParserOption
12321 *
12322 * Sets the options to be used during the parse.
12323 *
12324 * Returns 0 in case of success, -1 in case of an
12325 * API error.
12326 */
12327static int
12328xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12329 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012331{
12332 int i;
12333
12334 if (ctxt == NULL)
12335 return (-1);
12336 /*
12337 * WARNING: Change the start value if adding to the
12338 * xmlSchemaParseOption.
12339 */
12340 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12341 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012342 return (-1);
12343 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012344 }
12345 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012346 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347}
12348
12349/**
12350 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012351 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012352 *
12353 * Returns the option combination of the parser context.
12354 */
12355static int
12356xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012357
12358{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012359 if (ctxt == NULL)
12360 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 else
12362 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012363}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012364#endif
12365
Daniel Veillard4255d502002-04-16 15:50:10 +000012366/**
12367 * xmlSchemaNewParserCtxt:
12368 * @URL: the location of the schema
12369 *
12370 * Create an XML Schemas parse context for that file/resource expected
12371 * to contain an XML Schemas file.
12372 *
12373 * Returns the parser context or NULL in case of error
12374 */
12375xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012376xmlSchemaNewParserCtxt(const char *URL)
12377{
Daniel Veillard4255d502002-04-16 15:50:10 +000012378 xmlSchemaParserCtxtPtr ret;
12379
12380 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012381 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012382
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012383 ret = xmlSchemaParserCtxtCreate();
12384 if (ret == NULL)
12385 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012386 ret->dict = xmlDictCreate();
12387 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012388 return (ret);
12389}
12390
12391/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012392 * xmlSchemaNewMemParserCtxt:
12393 * @buffer: a pointer to a char array containing the schemas
12394 * @size: the size of the array
12395 *
12396 * Create an XML Schemas parse context for that memory buffer expected
12397 * to contain an XML Schemas file.
12398 *
12399 * Returns the parser context or NULL in case of error
12400 */
12401xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012402xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12403{
Daniel Veillard6045c902002-10-09 21:13:59 +000012404 xmlSchemaParserCtxtPtr ret;
12405
12406 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012407 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012408 ret = xmlSchemaParserCtxtCreate();
12409 if (ret == NULL)
12410 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012411 ret->buffer = buffer;
12412 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012413 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012414 return (ret);
12415}
12416
12417/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012418 * xmlSchemaNewDocParserCtxt:
12419 * @doc: a preparsed document tree
12420 *
12421 * Create an XML Schemas parse context for that document.
12422 * NB. The document may be modified during the parsing process.
12423 *
12424 * Returns the parser context or NULL in case of error
12425 */
12426xmlSchemaParserCtxtPtr
12427xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12428{
12429 xmlSchemaParserCtxtPtr ret;
12430
12431 if (doc == NULL)
12432 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012433 ret = xmlSchemaParserCtxtCreate();
12434 if (ret == NULL)
12435 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012436 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012437 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012438 /* The application has responsibility for the document */
12439 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012440
12441 return (ret);
12442}
12443
12444/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012445 * xmlSchemaFreeParserCtxt:
12446 * @ctxt: the schema parser context
12447 *
12448 * Free the resources associated to the schema parser context
12449 */
12450void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012451xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12452{
Daniel Veillard4255d502002-04-16 15:50:10 +000012453 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012454 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012455 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012456 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012457 if (ctxt->vctxt != NULL) {
12458 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12459 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012460 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12461 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12462 ctxt->constructor = NULL;
12463 ctxt->ownsConstructor = 0;
12464 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012465 if (ctxt->attrProhibs != NULL)
12466 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012467 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012468 xmlFree(ctxt);
12469}
12470
12471/************************************************************************
12472 * *
12473 * Building the content models *
12474 * *
12475 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012476
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012477static void
12478xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012479 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012480{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012481 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012482 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012483 xmlSchemaSubstGroupPtr substGroup;
12484 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012485
12486 elemDecl = (xmlSchemaElementPtr) particle->children;
12487 /*
12488 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012489 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012490 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012491 if (end == NULL)
12492 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012493 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012494 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012495 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012496 XML_SCHEMAP_INTERNAL,
12497 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12498 "declaration is marked having a subst. group but none "
12499 "available.\n", elemDecl->name, NULL);
12500 return;
12501 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012502 if (counter >= 0) {
12503 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012504 * NOTE that we put the declaration in, even if it's abstract.
12505 * However, an error will be raised during *validation* if an element
12506 * information item shall be validated against an abstract element
12507 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012508 */
12509 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12510 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12511 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12512 /*
12513 * Add subst. group members.
12514 */
12515 for (i = 0; i < substGroup->members->nbItems; i++) {
12516 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12517 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12518 member->name, member->targetNamespace, member);
12519 }
12520 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012521 /*
12522 * NOTE that we put the declaration in, even if it's abstract,
12523 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012524 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012525 xmlAutomataNewTransition2(pctxt->am,
12526 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012527 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12528 /*
12529 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012531 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012532 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012533 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12534 member->name, member->targetNamespace,
12535 1, 1, member);
12536 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012537 }
12538 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012539 xmlAutomataStatePtr hop;
12540 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12541 UNBOUNDED : particle->maxOccurs - 1;
12542 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12543
12544 counter =
12545 xmlAutomataNewCounter(pctxt->am, minOccurs,
12546 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012547 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012549 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012550 xmlAutomataNewTransition2(pctxt->am,
12551 start, NULL,
12552 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012553 hop);
12554 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012555 * Add subst. group members.
12556 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012557 for (i = 0; i < substGroup->members->nbItems; i++) {
12558 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12559 xmlAutomataNewEpsilon(pctxt->am,
12560 xmlAutomataNewTransition2(pctxt->am,
12561 start, NULL,
12562 member->name, member->targetNamespace, member),
12563 hop);
12564 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012565 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12566 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12567 }
12568 if (particle->minOccurs == 0)
12569 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012571}
12572
12573static void
12574xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12575 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012577 if (((xmlSchemaElementPtr) particle->children)->flags &
12578 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012579 /*
12580 * Substitution groups.
12581 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012582 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012583 } else {
12584 xmlSchemaElementPtr elemDecl;
12585 xmlAutomataStatePtr start;
12586
12587 elemDecl = (xmlSchemaElementPtr) particle->children;
12588
12589 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012590 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012591 if (particle->maxOccurs == 1) {
12592 start = ctxt->state;
12593 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012594 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12595 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12596 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012597 /* Special case. */
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012598 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012599 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012600 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12601 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12602 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012603 } else {
12604 int counter;
12605 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12606 UNBOUNDED : particle->maxOccurs - 1;
12607 int minOccurs = particle->minOccurs < 1 ?
12608 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012609
12610 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012611 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12612 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12613 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12614 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12615 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12616 NULL, counter);
12617 }
12618 if (particle->minOccurs == 0)
12619 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12620 }
12621}
12622
Daniel Veillard4255d502002-04-16 15:50:10 +000012623/**
12624 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012625 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012626 * @particle: the particle component
12627 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012628 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012629 * Create the automaton for the {content type} of a complex type.
12630 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012631 */
12632static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012633xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012634 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012635{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012636 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012637 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012638 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012639 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012640 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012641 /*
12642 * Just return in this case. A missing "term" of the particle
12643 * might arise due to an invalid "term" component.
12644 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012645 return;
12646 }
12647
12648 switch (particle->children->type) {
12649 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012650 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012652 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012653
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012654 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012656 start = pctxt->state;
12657 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658
12659 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012660 if (wild->any == 1) {
12661 /*
12662 * We need to add both transitions:
12663 *
12664 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012666 pctxt->state =
12667 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012668 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012669 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012670 /*
12671 * 2. the {"*"} for elements in no namespace.
12672 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012673 pctxt->state =
12674 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012675 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012676 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012677
12678 } else if (wild->nsSet != NULL) {
12679 ns = wild->nsSet;
12680 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012681 pctxt->state = start;
12682 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12683 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12684 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012685 ns = ns->next;
12686 } while (ns != NULL);
12687
12688 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012689 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12690 start, end, BAD_CAST "*", wild->negNsSet->value,
12691 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012692 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012693 } else {
12694 int counter;
12695 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012696 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012697 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012698 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012699 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012700
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012701 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12702 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012703 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012704 pctxt->state =
12705 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012706 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012707 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12708 pctxt->state =
12709 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012710 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012711 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012712 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012713 ns = wild->nsSet;
12714 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012715 pctxt->state =
12716 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012717 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012718 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012719 ns = ns->next;
12720 } while (ns != NULL);
12721
12722 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012723 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012724 start, hop, BAD_CAST "*", wild->negNsSet->value,
12725 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012726 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012727 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12728 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012730 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012731 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012732 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012733 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012734 break;
12735 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012736 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012738 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012739 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012740 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012741
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012742 /*
12743 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012744 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012745 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012746 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12747 sub = particle->children->children;
12748 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012749 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012750 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012751 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012752 }
12753 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012754 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012755
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012756 if (particle->maxOccurs >= UNBOUNDED) {
12757 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012758 xmlAutomataStatePtr tmp;
12759 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012760
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012761 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012762 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012763 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012764
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012765 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012766 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012767
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012768 sub = particle->children->children;
12769 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012770 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012771 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012772 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012773 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012774 tmp = pctxt->state;
12775 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012776 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012777 pctxt->state =
12778 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012779 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012780
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012781 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012782 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012783 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012784 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012785
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012786 sub = particle->children->children;
12787 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012788 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012789 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012790 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012791 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012792 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012793 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012794 /*
12795 * epsilon needed to block previous trans from
12796 * being allowed to enter back from another
12797 * construct
12798 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012799 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12800 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012801 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012802 xmlAutomataNewEpsilon(pctxt->am,
12803 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012804 }
12805 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012806 } else if ((particle->maxOccurs > 1)
12807 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012808 xmlAutomataStatePtr tmp;
12809 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012810
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012811 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012812 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012813 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012814
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012815 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012816 particle->minOccurs - 1,
12817 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012818
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012819 sub = particle->children->children;
12820 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012821 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012822 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012823 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012824 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012825 tmp = pctxt->state;
12826 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012827 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012828 pctxt->state =
12829 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012830 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012831 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012832 xmlAutomataNewEpsilon(pctxt->am,
12833 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012834 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012835 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012836 sub = particle->children->children;
12837 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012838 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012839 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012840 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012841 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012842 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012843 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12844 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012845 }
12846 }
12847 }
12848 break;
12849 }
12850 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012851 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012852 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012853
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012854 start = pctxt->state;
12855 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012856
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012857 /*
12858 * iterate over the subtypes and remerge the end with an
12859 * epsilon transition
12860 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012861 if (particle->maxOccurs == 1) {
12862 sub = particle->children->children;
12863 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012864 pctxt->state = start;
12865 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012866 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012867 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012868 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012869 }
12870 } else {
12871 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012872 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012873 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12874 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012875 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012876 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012877
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012878 /*
12879 * use a counter to keep track of the number of transtions
12880 * which went through the choice.
12881 */
12882 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012883 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12884 hop = xmlAutomataNewState(pctxt->am);
12885 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012886
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012887 sub = particle->children->children;
12888 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012889 pctxt->state = base;
12890 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012891 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012892 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012893 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012894 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012895 xmlAutomataNewEpsilon(pctxt->am, start, base);
12896 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12897 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012898 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012899 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012900 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012901 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012902 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012903 break;
12904 }
12905 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012906 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012907 xmlSchemaParticlePtr sub;
12908 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012909 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012911 sub = (xmlSchemaParticlePtr) particle->children->children;
12912 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012913 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012914 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012915 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012916 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012917
12918 elemDecl = (xmlSchemaElementPtr) sub->children;
12919 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012920 PERROR_INT("xmlSchemaBuildAContentModel",
12921 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012922 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012923 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012924 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012925 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012926 * {particles} of the group must be 0 or 1; this is
12927 * already ensured during the parse of the content of
12928 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012929 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012930 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12931 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012932
Daniel Veillarda980bef2005-07-18 21:34:03 +000012933 /*
12934 * This is an abstract group, we need to share
12935 * the same counter for all the element transitions
12936 * derived from the group
12937 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012938 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012939 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012940 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12941 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012942 } else {
12943 if ((sub->minOccurs == 1) &&
12944 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012945 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12946 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012947 elemDecl->name,
12948 elemDecl->targetNamespace,
12949 1, 1, elemDecl);
12950 } else if ((sub->minOccurs == 0) &&
12951 (sub->maxOccurs == 1)) {
12952
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012953 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12954 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012955 elemDecl->name,
12956 elemDecl->targetNamespace,
12957 0,
12958 1,
12959 elemDecl);
12960 }
12961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012962 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012963 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012964 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012965 pctxt->state =
12966 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012967 break;
12968 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012969 case XML_SCHEMA_TYPE_GROUP:
12970 /*
12971 * If we hit a model group definition, then this means that
12972 * it was empty, thus was not substituted for the containing
12973 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012974 * TODO: But the group should be substituted and not occur at
12975 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012976 */
12977 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012978 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012979 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12980 "xmlSchemaBuildAContentModel",
12981 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012982 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012983 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012984 }
12985}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012986
Daniel Veillard4255d502002-04-16 15:50:10 +000012987/**
12988 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012989 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012990 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012991 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012992 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012993 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012994 */
12995static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012996xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012997 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012998{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012999 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13000 (type->contModel != NULL) ||
13001 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13002 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013003 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013004
13005#ifdef DEBUG_CONTENT
13006 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013007 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013008#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013009 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013010 ctxt->am = xmlNewAutomata();
13011 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013012 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013013 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013014 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013015 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013016 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013017 /*
13018 * Build the automaton.
13019 */
13020 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013021 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013022 type->contModel = xmlAutomataCompile(ctxt->am);
13023 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013024 xmlSchemaPCustomErr(ctxt,
13025 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013026 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013027 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013028 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013029 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013030 XML_SCHEMAP_NOT_DETERMINISTIC,
13031 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013032 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013033 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013034 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013035#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013036 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013037 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013038 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013039#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013040 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013041 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013042 xmlFreeAutomata(ctxt->am);
13043 ctxt->am = NULL;
13044}
13045
13046/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013047 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013048 * @elem: the schema element context
13049 * @ctxt: the schema parser context
13050 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013051 * Resolves the references of an element declaration
13052 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013053 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013054 */
13055static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013056xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13057 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013058{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013059 if ((ctxt == NULL) || (elemDecl == NULL) ||
13060 ((elemDecl != NULL) &&
13061 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013062 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013063 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013064
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013065 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013066 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013067
13068 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013069 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013071 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013072 elemDecl->namedTypeNs);
13073 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013074 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013075 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013076 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013077 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078 XML_SCHEMA_TYPE_BASIC, "type definition");
13079 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013080 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013081 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013082 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013083 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013084
Daniel Veillardc0826a72004-08-10 14:17:33 +000013085 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013086 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013087 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013088 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013089 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13090 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091 if (substHead == NULL) {
13092 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013093 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013094 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013095 "substitutionGroup", elemDecl->substGroup,
13096 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013098 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013099 /*
13100 * Set the "substitution group affiliation".
13101 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013102 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013103 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013104 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013105 * The type definitions is set to:
13106 * SPEC "...the {type definition} of the element
13107 * declaration ·resolved· to by the ·actual value·
13108 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013109 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013110 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013111 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013112 }
13113 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013114 /*
13115 * SPEC "The definition of anyType serves as the default type definition
13116 * for element declarations whose XML representation does not specify one."
13117 */
13118 if ((elemDecl->subtypes == NULL) &&
13119 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013120 (elemDecl->substGroup == NULL))
13121 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013122}
13123
13124/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013125 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013126 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013127 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013128 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013129 * Checks and builds the "member type definitions" property of the union
13130 * simple type. This handles part (1), part (2) is done in
13131 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13132 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013133 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013134 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013135static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013136xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13137 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013138{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013139
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013140 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013142
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013143 /*
13144 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13145 * define the explicit members as the type definitions ·resolved·
13146 * to by the items in the ·actual value· of the memberTypes [attribute],
13147 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013148 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013149 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013150 /*
13151 * Resolve references.
13152 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013153 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013154 lastLink = NULL;
13155 while (link != NULL) {
13156 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013158 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13159 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13160
13161 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013162 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013163 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013164 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013165 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13166 /*
13167 * Remove the member type link.
13168 */
13169 if (lastLink == NULL)
13170 type->memberTypes = link->next;
13171 else
13172 lastLink->next = link->next;
13173 newLink = link;
13174 link = link->next;
13175 xmlFree(newLink);
13176 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013178 lastLink = link;
13179 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013180 }
13181 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013182 /*
13183 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013184 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013186 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13188 if (link == NULL) {
13189 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13190 return (-1);
13191 }
13192 link->type = memberType;
13193 link->next = NULL;
13194 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013195 type->memberTypes = link;
13196 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013197 lastLink->next = link;
13198 lastLink = link;
13199 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013200 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013201 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013202}
13203
Daniel Veillard4255d502002-04-16 15:50:10 +000013204/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013205 * xmlSchemaIsDerivedFromBuiltInType:
13206 * @ctxt: the schema parser context
13207 * @type: the type definition
13208 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013209 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013210 *
13211 * Returns 1 if the type has the given value type, or
13212 * is derived from such a type.
13213 */
William M. Brack803812b2004-06-03 02:11:24 +000013214static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013216{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013217 if (type == NULL)
13218 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013219 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013220 return (0);
13221 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13222 if (type->builtInType == valType)
13223 return(1);
13224 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13225 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13226 return (0);
13227 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013228 }
13229 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013230}
13231
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013232#if 0
13233/**
13234 * xmlSchemaIsDerivedFromBuiltInType:
13235 * @ctxt: the schema parser context
13236 * @type: the type definition
13237 * @valType: the value type
13238 *
13239 *
13240 * Returns 1 if the type has the given value type, or
13241 * is derived from such a type.
13242 */
13243static int
13244xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13245{
13246 if (type == NULL)
13247 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013248 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013249 return (0);
13250 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13251 if (type->builtInType == valType)
13252 return(1);
13253 return (0);
13254 } else
13255 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13256
13257 return (0);
13258}
13259#endif
13260
13261static xmlSchemaTypePtr
13262xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13263{
13264 if (type == NULL)
13265 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013266 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013267 return (NULL);
13268 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013269 return(type);
13270 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271}
13272
Daniel Veillard3646d642004-06-02 19:19:14 +000013273/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013274 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 * @type: the simpleType definition
13276 *
13277 * Returns the primitive type of the given type or
13278 * NULL in case of error.
13279 */
13280static xmlSchemaTypePtr
13281xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13282{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013283
Daniel Veillard01fa6152004-06-29 17:04:39 +000013284 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013285 /*
13286 * Note that anySimpleType is actually not a primitive type
13287 * but we need that here.
13288 */
13289 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13290 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 return (type);
13292 type = type->baseType;
13293 }
13294
13295 return (NULL);
13296}
13297
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013298#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013299/**
13300 * xmlSchemaGetBuiltInTypeAncestor:
13301 * @type: the simpleType definition
13302 *
13303 * Returns the primitive type of the given type or
13304 * NULL in case of error.
13305 */
13306static xmlSchemaTypePtr
13307xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13308{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013309 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013310 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013311 while (type != NULL) {
13312 if (type->type == XML_SCHEMA_TYPE_BASIC)
13313 return (type);
13314 type = type->baseType;
13315 }
13316
13317 return (NULL);
13318}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013319#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013320
Daniel Veillard01fa6152004-06-29 17:04:39 +000013321/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013322 * xmlSchemaCloneWildcardNsConstraints:
13323 * @ctxt: the schema parser context
13324 * @dest: the destination wildcard
13325 * @source: the source wildcard
13326 *
13327 * Clones the namespace constraints of source
13328 * and assignes them to dest.
13329 * Returns -1 on internal error, 0 otherwise.
13330 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013331static int
13332xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013333 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013334 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013335{
13336 xmlSchemaWildcardNsPtr cur, tmp, last;
13337
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013338 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013339 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013340 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013341 cur = source->nsSet;
13342 last = NULL;
13343 while (cur != NULL) {
13344 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13345 if (tmp == NULL)
13346 return(-1);
13347 tmp->value = cur->value;
13348 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013349 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013350 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013351 last->next = tmp;
13352 last = tmp;
13353 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013354 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013355 if (dest->negNsSet != NULL)
13356 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013357 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013358 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13359 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013360 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013361 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013362 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013363 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013364 return(0);
13365}
13366
Daniel Veillard50355f02004-06-08 17:52:16 +000013367/**
13368 * xmlSchemaUnionWildcards:
13369 * @ctxt: the schema parser context
13370 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013371 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013372 *
13373 * Unions the namespace constraints of the given wildcards.
13374 * @completeWild will hold the resulting union.
13375 * Returns a positive error code on failure, -1 in case of an
13376 * internal error, 0 otherwise.
13377 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013378static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013379xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013380 xmlSchemaWildcardPtr completeWild,
13381 xmlSchemaWildcardPtr curWild)
13382{
13383 xmlSchemaWildcardNsPtr cur, curB, tmp;
13384
13385 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013386 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013387 * value.
13388 */
13389 if ((completeWild->any == curWild->any) &&
13390 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13391 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013392
Daniel Veillard3646d642004-06-02 19:19:14 +000013393 if ((completeWild->negNsSet == NULL) ||
13394 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013395
Daniel Veillard3646d642004-06-02 19:19:14 +000013396 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013397 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013398
13399 /*
13400 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013401 */
13402 cur = completeWild->nsSet;
13403 while (cur != NULL) {
13404 found = 0;
13405 curB = curWild->nsSet;
13406 while (curB != NULL) {
13407 if (cur->value == curB->value) {
13408 found = 1;
13409 break;
13410 }
13411 curB = curB->next;
13412 }
13413 if (!found)
13414 break;
13415 cur = cur->next;
13416 }
13417 if (found)
13418 return(0);
13419 } else
13420 return(0);
13421 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013422 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013423 /*
13424 * 2 If either O1 or O2 is any, then any must be the value
13425 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013426 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013427 if (completeWild->any == 0) {
13428 completeWild->any = 1;
13429 if (completeWild->nsSet != NULL) {
13430 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13431 completeWild->nsSet = NULL;
13432 }
13433 if (completeWild->negNsSet != NULL) {
13434 xmlFree(completeWild->negNsSet);
13435 completeWild->negNsSet = NULL;
13436 }
13437 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013438 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013439 }
13440 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013441 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013442 * then the union of those sets must be the value.
13443 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013445 int found;
13446 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447
Daniel Veillard3646d642004-06-02 19:19:14 +000013448 cur = curWild->nsSet;
13449 start = completeWild->nsSet;
13450 while (cur != NULL) {
13451 found = 0;
13452 curB = start;
13453 while (curB != NULL) {
13454 if (cur->value == curB->value) {
13455 found = 1;
13456 break;
13457 }
13458 curB = curB->next;
13459 }
13460 if (!found) {
13461 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013462 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013463 return (-1);
13464 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013466 completeWild->nsSet = tmp;
13467 }
13468 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469 }
13470
Daniel Veillard3646d642004-06-02 19:19:14 +000013471 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013473 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013474 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013475 * or ·absent·), then a pair of not and ·absent· must be the value.
13476 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013477 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013478 (curWild->negNsSet != NULL) &&
13479 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13480 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013481
13482 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013485 * 5.
13486 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013488 (completeWild->negNsSet->value != NULL) &&
13489 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013491 (curWild->negNsSet->value != NULL) &&
13492 (completeWild->nsSet != NULL))) {
13493
13494 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495
Daniel Veillard3646d642004-06-02 19:19:14 +000013496 if (completeWild->nsSet != NULL) {
13497 cur = completeWild->nsSet;
13498 curB = curWild->negNsSet;
13499 } else {
13500 cur = curWild->nsSet;
13501 curB = completeWild->negNsSet;
13502 }
13503 nsFound = 0;
13504 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013506 absentFound = 1;
13507 else if (cur->value == curB->value)
13508 nsFound = 1;
13509 if (nsFound && absentFound)
13510 break;
13511 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013512 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013513
13514 if (nsFound && absentFound) {
13515 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013517 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013519 completeWild->any = 1;
13520 if (completeWild->nsSet != NULL) {
13521 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13522 completeWild->nsSet = NULL;
13523 }
13524 if (completeWild->negNsSet != NULL) {
13525 xmlFree(completeWild->negNsSet);
13526 completeWild->negNsSet = NULL;
13527 }
13528 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 /*
13530 * 5.2 If the set S includes the negated namespace name
13531 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013532 * be the value.
13533 */
13534 if (completeWild->nsSet != NULL) {
13535 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13536 completeWild->nsSet = NULL;
13537 }
13538 if (completeWild->negNsSet == NULL) {
13539 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13540 if (completeWild->negNsSet == NULL)
13541 return (-1);
13542 }
13543 completeWild->negNsSet->value = NULL;
13544 } else if ((!nsFound) && absentFound) {
13545 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013547 * namespace name, then the union is not expressible.
13548 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013549 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013550 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013551 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013552 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013553 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013554 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013555 /*
13556 * 5.4 If the set S does not include either the negated namespace
13557 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013558 * and a namespace name must be the value.
13559 */
13560 if (completeWild->negNsSet == NULL) {
13561 if (completeWild->nsSet != NULL) {
13562 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13563 completeWild->nsSet = NULL;
13564 }
13565 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13566 if (completeWild->negNsSet == NULL)
13567 return (-1);
13568 completeWild->negNsSet->value = curWild->negNsSet->value;
13569 }
13570 }
13571 return (0);
13572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013574 * 6.
13575 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013576 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013577 (completeWild->negNsSet->value == NULL) &&
13578 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013579 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013580 (curWild->negNsSet->value == NULL) &&
13581 (completeWild->nsSet != NULL))) {
13582
13583 if (completeWild->nsSet != NULL) {
13584 cur = completeWild->nsSet;
13585 } else {
13586 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013588 while (cur != NULL) {
13589 if (cur->value == NULL) {
13590 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 * value.
13593 */
13594 completeWild->any = 1;
13595 if (completeWild->nsSet != NULL) {
13596 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13597 completeWild->nsSet = NULL;
13598 }
13599 if (completeWild->negNsSet != NULL) {
13600 xmlFree(completeWild->negNsSet);
13601 completeWild->negNsSet = NULL;
13602 }
13603 return (0);
13604 }
13605 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013606 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013607 if (completeWild->negNsSet == NULL) {
13608 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013609 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013610 * and ·absent· must be the value.
13611 */
13612 if (completeWild->nsSet != NULL) {
13613 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13614 completeWild->nsSet = NULL;
13615 }
13616 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13617 if (completeWild->negNsSet == NULL)
13618 return (-1);
13619 completeWild->negNsSet->value = NULL;
13620 }
13621 return (0);
13622 }
13623 return (0);
13624
13625}
13626
Daniel Veillard50355f02004-06-08 17:52:16 +000013627/**
13628 * xmlSchemaIntersectWildcards:
13629 * @ctxt: the schema parser context
13630 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013632 *
13633 * Intersects the namespace constraints of the given wildcards.
13634 * @completeWild will hold the resulting intersection.
13635 * Returns a positive error code on failure, -1 in case of an
13636 * internal error, 0 otherwise.
13637 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013638static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013640 xmlSchemaWildcardPtr completeWild,
13641 xmlSchemaWildcardPtr curWild)
13642{
William M. Brack803812b2004-06-03 02:11:24 +000013643 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013644
13645 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013647 * value.
13648 */
13649 if ((completeWild->any == curWild->any) &&
13650 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13651 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652
Daniel Veillard3646d642004-06-02 19:19:14 +000013653 if ((completeWild->negNsSet == NULL) ||
13654 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655
Daniel Veillard3646d642004-06-02 19:19:14 +000013656 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013657 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013658
13659 /*
13660 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013661 */
13662 cur = completeWild->nsSet;
13663 while (cur != NULL) {
13664 found = 0;
13665 curB = curWild->nsSet;
13666 while (curB != NULL) {
13667 if (cur->value == curB->value) {
13668 found = 1;
13669 break;
13670 }
13671 curB = curB->next;
13672 }
13673 if (!found)
13674 break;
13675 cur = cur->next;
13676 }
13677 if (found)
13678 return(0);
13679 } else
13680 return(0);
13681 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013682 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013683 /*
13684 * 2 If either O1 or O2 is any, then the other must be the value.
13685 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013686 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013687 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013689 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013690 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013692 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13693 * name or ·absent·) and the other is a set of (namespace names or
13694 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013695 * the set, minus ·absent· if it was in the set, must be the value.
13696 */
13697 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13698 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13699 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 if (completeWild->nsSet == NULL) {
13702 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013703 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013704 return(-1);
13705 } else
13706 neg = curWild->negNsSet->value;
13707 /*
13708 * Remove absent and negated.
13709 */
13710 prev = NULL;
13711 cur = completeWild->nsSet;
13712 while (cur != NULL) {
13713 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013715 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013716 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013717 prev->next = cur->next;
13718 xmlFree(cur);
13719 break;
13720 }
13721 prev = cur;
13722 cur = cur->next;
13723 }
13724 if (neg != NULL) {
13725 prev = NULL;
13726 cur = completeWild->nsSet;
13727 while (cur != NULL) {
13728 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013729 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013730 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013731 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013732 prev->next = cur->next;
13733 xmlFree(cur);
13734 break;
13735 }
13736 prev = cur;
13737 cur = cur->next;
13738 }
13739 }
13740
13741 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013742 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013743 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013744 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013745 * then the intersection of those sets must be the value.
13746 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013747 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013748 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013749
Daniel Veillard3646d642004-06-02 19:19:14 +000013750 cur = completeWild->nsSet;
13751 prev = NULL;
13752 while (cur != NULL) {
13753 found = 0;
13754 curB = curWild->nsSet;
13755 while (curB != NULL) {
13756 if (cur->value == curB->value) {
13757 found = 1;
13758 break;
13759 }
13760 curB = curB->next;
13761 }
13762 if (!found) {
13763 if (prev == NULL)
13764 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013766 prev->next = cur->next;
13767 tmp = cur->next;
13768 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013769 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013770 continue;
13771 }
13772 prev = cur;
13773 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 }
13775
Daniel Veillard3646d642004-06-02 19:19:14 +000013776 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013777 }
13778 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013779 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 */
13781 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013782 (curWild->negNsSet != NULL) &&
13783 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013785 (curWild->negNsSet->value != NULL)) {
13786
13787 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013789 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013790 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 }
13792 /*
13793 * 6 If the one is a negation of a namespace name and the other
13794 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013795 * of a namespace name must be the value.
13796 */
13797 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13798 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 (completeWild->negNsSet->value == NULL)) {
13800 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013801 }
13802 return(0);
13803}
13804
Daniel Veillard50355f02004-06-08 17:52:16 +000013805/**
13806 * xmlSchemaIsWildcardNsConstraintSubset:
13807 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013808 * @sub: the first wildcard
13809 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013810 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013811 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13812 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013813 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013814 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013815 */
13816static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013817xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13818 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013819{
Daniel Veillard50355f02004-06-08 17:52:16 +000013820 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013821 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013822 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013823 if (super->any)
13824 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013825 /*
13826 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13827 * 2.2 super must be a pair of not and the same value.
13828 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013829 if ((sub->negNsSet != NULL) &&
13830 (super->negNsSet != NULL) &&
13831 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013832 return (0);
13833 /*
13834 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013835 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013836 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013837 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013839 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013840 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013841 xmlSchemaWildcardNsPtr cur, curB;
13842 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013844 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013845 while (cur != NULL) {
13846 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013847 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013848 while (curB != NULL) {
13849 if (cur->value == curB->value) {
13850 found = 1;
13851 break;
13852 }
13853 curB = curB->next;
13854 }
13855 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013856 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013857 cur = cur->next;
13858 }
13859 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013860 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013861 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013862 xmlSchemaWildcardNsPtr cur;
13863 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013864 * 3.2.2 super must be a pair of not and a namespace name or
13865 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013866 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013867 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013869 if (cur->value == super->negNsSet->value)
13870 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013871 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013872 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013873 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013874 }
13875 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013876 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013877}
13878
Daniel Veillard50355f02004-06-08 17:52:16 +000013879static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013880xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013881 int *fixed,
13882 const xmlChar **value,
13883 xmlSchemaValPtr *val)
13884{
13885 *fixed = 0;
13886 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013887 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013888 *val = NULL;
13889
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013890 if (attruse->defValue != NULL) {
13891 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013892 if (val != NULL)
13893 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013894 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013895 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013896 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013897 } else if ((attruse->attrDecl != NULL) &&
13898 (attruse->attrDecl->defValue != NULL)) {
13899 *value = attruse->attrDecl->defValue;
13900 if (val != NULL)
13901 *val = attruse->attrDecl->defVal;
13902 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013903 *fixed = 1;
13904 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013906 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013907}
Daniel Veillard3646d642004-06-02 19:19:14 +000013908/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013910 * @wild: the wildcard
13911 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013912 *
13913 * Validation Rule: Wildcard allows Namespace Name
13914 * (cvc-wildcard-namespace)
13915 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013916 * Returns 0 if the given namespace matches the wildcard,
13917 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013918 */
13919static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13921 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013922{
13923 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013924 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013925
13926 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013927 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013928 else if (wild->nsSet != NULL) {
13929 xmlSchemaWildcardNsPtr cur;
13930
13931 cur = wild->nsSet;
13932 while (cur != NULL) {
13933 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013934 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013935 cur = cur->next;
13936 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013938 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013939 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013940
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013941 return(1);
13942}
13943
13944#define XML_SCHEMA_ACTION_DERIVE 0
13945#define XML_SCHEMA_ACTION_REDEFINE 1
13946
13947#define WXS_ACTION_STR(a) \
13948((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13949
13950/*
13951* Schema Component Constraint:
13952* Derivation Valid (Restriction, Complex)
13953* derivation-ok-restriction (2) - (4)
13954*
13955* ATTENTION:
13956* In XML Schema 1.1 this will be:
13957* Validation Rule:
13958* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13959*
13960*/
13961static int
13962xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13963 int action,
13964 xmlSchemaBasicItemPtr item,
13965 xmlSchemaBasicItemPtr baseItem,
13966 xmlSchemaItemListPtr uses,
13967 xmlSchemaItemListPtr baseUses,
13968 xmlSchemaWildcardPtr wild,
13969 xmlSchemaWildcardPtr baseWild)
13970{
13971 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013972 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013973 const xmlChar *bEffValue;
13974 int effFixed;
13975
13976 if (uses != NULL) {
13977 for (i = 0; i < uses->nbItems; i++) {
13978 cur = uses->items[i];
13979 found = 0;
13980 if (baseUses == NULL)
13981 goto not_found;
13982 for (j = 0; j < baseUses->nbItems; j++) {
13983 bcur = baseUses->items[j];
13984 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13985 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13986 (WXS_ATTRUSE_DECL_TNS(cur) ==
13987 WXS_ATTRUSE_DECL_TNS(bcur)))
13988 {
13989 /*
13990 * (2.1) "If there is an attribute use in the {attribute
13991 * uses} of the {base type definition} (call this B) whose
13992 * {attribute declaration} has the same {name} and {target
13993 * namespace}, then all of the following must be true:"
13994 */
13995 found = 1;
13996
13997 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13998 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
13999 {
14000 xmlChar *str = NULL;
14001 /*
14002 * (2.1.1) "one of the following must be true:"
14003 * (2.1.1.1) "B's {required} is false."
14004 * (2.1.1.2) "R's {required} is true."
14005 */
14006 xmlSchemaPAttrUseErr4(pctxt,
14007 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14008 WXS_ITEM_NODE(item), item, cur,
14009 "The 'optional' attribute use is inconsistent "
14010 "with the corresponding 'required' attribute use of "
14011 "the %s %s",
14012 WXS_ACTION_STR(action),
14013 xmlSchemaGetComponentDesignation(&str, baseItem),
14014 NULL, NULL);
14015 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014016 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014017 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014018 WXS_ATTRUSE_TYPEDEF(cur),
14019 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14020 {
14021 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14022
14023 /*
14024 * SPEC (2.1.2) "R's {attribute declaration}'s
14025 * {type definition} must be validly derived from
14026 * B's {type definition} given the empty set as
14027 * defined in Type Derivation OK (Simple) (§3.14.6)."
14028 */
14029 xmlSchemaPAttrUseErr4(pctxt,
14030 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14031 WXS_ITEM_NODE(item), item, cur,
14032 "The attribute declaration's %s "
14033 "is not validly derived from "
14034 "the corresponding %s of the "
14035 "attribute declaration in the %s %s",
14036 xmlSchemaGetComponentDesignation(&strA,
14037 WXS_ATTRUSE_TYPEDEF(cur)),
14038 xmlSchemaGetComponentDesignation(&strB,
14039 WXS_ATTRUSE_TYPEDEF(bcur)),
14040 WXS_ACTION_STR(action),
14041 xmlSchemaGetComponentDesignation(&strC, baseItem));
14042 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14043 FREE_AND_NULL(strA);
14044 FREE_AND_NULL(strB);
14045 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014046 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014047 } else {
14048 /*
14049 * 2.1.3 [Definition:] Let the effective value
14050 * constraint of an attribute use be its {value
14051 * constraint}, if present, otherwise its {attribute
14052 * declaration}'s {value constraint} .
14053 */
14054 xmlSchemaGetEffectiveValueConstraint(bcur,
14055 &effFixed, &bEffValue, NULL);
14056 /*
14057 * 2.1.3 ... one of the following must be true
14058 *
14059 * 2.1.3.1 B's ·effective value constraint· is
14060 * ·absent· or default.
14061 */
14062 if ((bEffValue != NULL) &&
14063 (effFixed == 1)) {
14064 const xmlChar *rEffValue = NULL;
14065
14066 xmlSchemaGetEffectiveValueConstraint(bcur,
14067 &effFixed, &rEffValue, NULL);
14068 /*
14069 * 2.1.3.2 R's ·effective value constraint· is
14070 * fixed with the same string as B's.
14071 * MAYBE TODO: Compare the computed values.
14072 * Hmm, it says "same string" so
14073 * string-equality might really be sufficient.
14074 */
14075 if ((effFixed == 0) ||
14076 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14077 {
14078 xmlChar *str = NULL;
14079
14080 xmlSchemaPAttrUseErr4(pctxt,
14081 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14082 WXS_ITEM_NODE(item), item, cur,
14083 "The effective value constraint of the "
14084 "attribute use is inconsistent with "
14085 "its correspondent in the %s %s",
14086 WXS_ACTION_STR(action),
14087 xmlSchemaGetComponentDesignation(&str,
14088 baseItem),
14089 NULL, NULL);
14090 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014091 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014092 }
14093 }
14094 }
14095 break;
14096 }
14097 }
14098not_found:
14099 if (!found) {
14100 /*
14101 * (2.2) "otherwise the {base type definition} must have an
14102 * {attribute wildcard} and the {target namespace} of the
14103 * R's {attribute declaration} must be ·valid· with respect
14104 * to that wildcard, as defined in Wildcard allows Namespace
14105 * Name (§3.10.4)."
14106 */
14107 if ((baseWild == NULL) ||
14108 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14109 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14110 {
14111 xmlChar *str = NULL;
14112
14113 xmlSchemaPAttrUseErr4(pctxt,
14114 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14115 WXS_ITEM_NODE(item), item, cur,
14116 "Neither a matching attribute use, "
14117 "nor a matching wildcard exists in the %s %s",
14118 WXS_ACTION_STR(action),
14119 xmlSchemaGetComponentDesignation(&str, baseItem),
14120 NULL, NULL);
14121 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014122 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014123 }
14124 }
14125 }
14126 }
14127 /*
14128 * SPEC derivation-ok-restriction (3):
14129 * (3) "For each attribute use in the {attribute uses} of the {base type
14130 * definition} whose {required} is true, there must be an attribute
14131 * use with an {attribute declaration} with the same {name} and
14132 * {target namespace} as its {attribute declaration} in the {attribute
14133 * uses} of the complex type definition itself whose {required} is true.
14134 */
14135 if (baseUses != NULL) {
14136 for (j = 0; j < baseUses->nbItems; j++) {
14137 bcur = baseUses->items[j];
14138 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14139 continue;
14140 found = 0;
14141 if (uses != NULL) {
14142 for (i = 0; i < uses->nbItems; i++) {
14143 cur = uses->items[i];
14144 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14145 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14146 (WXS_ATTRUSE_DECL_TNS(cur) ==
14147 WXS_ATTRUSE_DECL_TNS(bcur))) {
14148 found = 1;
14149 break;
14150 }
14151 }
14152 }
14153 if (!found) {
14154 xmlChar *strA = NULL, *strB = NULL;
14155
14156 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14157 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14158 NULL, item,
14159 "A matching attribute use for the "
14160 "'required' %s of the %s %s is missing",
14161 xmlSchemaGetComponentDesignation(&strA, bcur),
14162 WXS_ACTION_STR(action),
14163 xmlSchemaGetComponentDesignation(&strB, baseItem),
14164 NULL);
14165 FREE_AND_NULL(strA);
14166 FREE_AND_NULL(strB);
14167 }
14168 }
14169 }
14170 /*
14171 * derivation-ok-restriction (4)
14172 */
14173 if (wild != NULL) {
14174 /*
14175 * (4) "If there is an {attribute wildcard}, all of the
14176 * following must be true:"
14177 */
14178 if (baseWild == NULL) {
14179 xmlChar *str = NULL;
14180
14181 /*
14182 * (4.1) "The {base type definition} must also have one."
14183 */
14184 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14185 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14186 NULL, item,
14187 "The %s has an attribute wildcard, "
14188 "but the %s %s '%s' does not have one",
14189 WXS_ITEM_TYPE_NAME(item),
14190 WXS_ACTION_STR(action),
14191 WXS_ITEM_TYPE_NAME(baseItem),
14192 xmlSchemaGetComponentQName(&str, baseItem));
14193 FREE_AND_NULL(str);
14194 return(pctxt->err);
14195 } else if ((baseWild->any == 0) &&
14196 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14197 {
14198 xmlChar *str = NULL;
14199 /*
14200 * (4.2) "The complex type definition's {attribute wildcard}'s
14201 * {namespace constraint} must be a subset of the {base type
14202 * definition}'s {attribute wildcard}'s {namespace constraint},
14203 * as defined by Wildcard Subset (§3.10.6)."
14204 */
14205 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14206 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14207 NULL, item,
14208 "The attribute wildcard is not a valid "
14209 "subset of the wildcard in the %s %s '%s'",
14210 WXS_ACTION_STR(action),
14211 WXS_ITEM_TYPE_NAME(baseItem),
14212 xmlSchemaGetComponentQName(&str, baseItem),
14213 NULL);
14214 FREE_AND_NULL(str);
14215 return(pctxt->err);
14216 }
14217 /* 4.3 Unless the {base type definition} is the ·ur-type
14218 * definition·, the complex type definition's {attribute
14219 * wildcard}'s {process contents} must be identical to or
14220 * stronger than the {base type definition}'s {attribute
14221 * wildcard}'s {process contents}, where strict is stronger
14222 * than lax is stronger than skip.
14223 */
14224 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14225 (wild->processContents < baseWild->processContents)) {
14226 xmlChar *str = NULL;
14227 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14228 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14229 NULL, baseItem,
14230 "The {process contents} of the attribute wildcard is "
14231 "weaker than the one 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 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014240 return(0);
14241}
14242
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014243
14244static int
14245xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14246 xmlSchemaBasicItemPtr item,
14247 xmlSchemaWildcardPtr *completeWild,
14248 xmlSchemaItemListPtr list,
14249 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014250/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014251 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014252 * @ctxt: the schema parser context
14253 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014254 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014255 *
14256 * Builds the wildcard and the attribute uses on the given complex type.
14257 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014258 *
14259 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14260 * strings, so recheck this if we start to hardcode some schemata, since
14261 * they might not be in the same dict.
14262 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014263 */
14264static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014265xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014266 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014267{
14268 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014269 xmlSchemaAttributeUsePtr use;
14270 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014271
Daniel Veillard01fa6152004-06-29 17:04:39 +000014272 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014273 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014274 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014275 return (-1);
14276 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014277 baseType = type->baseType;
14278 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014279 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014280 return(-1);
14281
14282 uses = type->attrUses;
14283 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014284 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014285 * Expand attribute group references. And build the 'complete'
14286 * wildcard, i.e. intersect multiple wildcards.
14287 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014288 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014289 if (uses != NULL) {
14290 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014291 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014292 * This one will transfer all attr. prohibitions
14293 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014294 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014295 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14296 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14297 pctxt->attrProhibs) == -1)
14298 {
14299 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14300 "failed to expand attributes");
14301 }
14302 if (pctxt->attrProhibs->nbItems != 0)
14303 prohibs = pctxt->attrProhibs;
14304 } else {
14305 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14306 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14307 NULL) == -1)
14308 {
14309 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14310 "failed to expand attributes");
14311 }
14312 }
14313 }
14314 /*
14315 * Inherit the attribute uses of the base type.
14316 */
14317 if (baseUses != NULL) {
14318 int i, j;
14319 xmlSchemaAttributeUseProhibPtr pro;
14320
14321 if (WXS_IS_RESTRICTION(type)) {
14322 int usesCount;
14323 xmlSchemaAttributeUsePtr tmp;
14324
14325 if (uses != NULL)
14326 usesCount = uses->nbItems;
14327 else
14328 usesCount = 0;
14329
14330 /* Restriction. */
14331 for (i = 0; i < baseUses->nbItems; i++) {
14332 use = baseUses->items[i];
14333 if (prohibs) {
14334 /*
14335 * Filter out prohibited uses.
14336 */
14337 for (j = 0; j < prohibs->nbItems; j++) {
14338 pro = prohibs->items[j];
14339 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14340 (WXS_ATTRUSE_DECL_TNS(use) ==
14341 pro->targetNamespace))
14342 {
14343 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014344 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014345 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014346 }
14347 if (usesCount) {
14348 /*
14349 * Filter out existing uses.
14350 */
14351 for (j = 0; j < usesCount; j++) {
14352 tmp = uses->items[j];
14353 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14354 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14355 (WXS_ATTRUSE_DECL_TNS(use) ==
14356 WXS_ATTRUSE_DECL_TNS(tmp)))
14357 {
14358 goto inherit_next;
14359 }
14360 }
14361 }
14362 if (uses == NULL) {
14363 type->attrUses = xmlSchemaItemListCreate();
14364 if (type->attrUses == NULL)
14365 goto exit_failure;
14366 uses = type->attrUses;
14367 }
14368 xmlSchemaItemListAddSize(uses, 2, use);
14369inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014370 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014371 } else {
14372 /* Extension. */
14373 for (i = 0; i < baseUses->nbItems; i++) {
14374 use = baseUses->items[i];
14375 if (uses == NULL) {
14376 type->attrUses = xmlSchemaItemListCreate();
14377 if (type->attrUses == NULL)
14378 goto exit_failure;
14379 uses = type->attrUses;
14380 }
14381 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14382 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014383 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014384 }
14385 /*
14386 * Shrink attr. uses.
14387 */
14388 if (uses) {
14389 if (uses->nbItems == 0) {
14390 xmlSchemaItemListFree(uses);
14391 type->attrUses = NULL;
14392 }
14393 /*
14394 * TODO: We could shrink the size of the array
14395 * to fit the actual number of items.
14396 */
14397 }
14398 /*
14399 * Compute the complete wildcard.
14400 */
14401 if (WXS_IS_EXTENSION(type)) {
14402 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014403 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014404 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14405 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014406 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014407 if (type->attributeWildcard != NULL) {
14408 /*
14409 * Union the complete wildcard with the base wildcard.
14410 * SPEC {attribute wildcard}
14411 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14412 * and {annotation} are those of the ·complete wildcard·,
14413 * and whose {namespace constraint} is the intensional union
14414 * of the {namespace constraint} of the ·complete wildcard·
14415 * and of the ·base wildcard·, as defined in Attribute
14416 * Wildcard Union (§3.10.6)."
14417 */
14418 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14419 baseType->attributeWildcard) == -1)
14420 goto exit_failure;
14421 } else {
14422 /*
14423 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14424 * then the ·base wildcard·."
14425 */
14426 type->attributeWildcard = baseType->attributeWildcard;
14427 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014428 } else {
14429 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014430 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14431 * ·complete wildcard"
14432 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014433 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014434 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014435 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014436 /*
14437 * SPEC {attribute wildcard}
14438 * (3.1) "If the <restriction> alternative is chosen, then the
14439 * ·complete wildcard·;"
14440 * NOOP
14441 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014442 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014443
Daniel Veillard3646d642004-06-02 19:19:14 +000014444 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014445
14446exit_failure:
14447 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014448}
14449
14450/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014451 * xmlSchemaTypeFinalContains:
14452 * @schema: the schema
14453 * @type: the type definition
14454 * @final: the final
14455 *
14456 * Evaluates if a type definition contains the given "final".
14457 * This does take "finalDefault" into account as well.
14458 *
14459 * Returns 1 if the type does containt the given "final",
14460 * 0 otherwise.
14461 */
14462static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014463xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014464{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014465 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014466 return (0);
14467 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014468 return (1);
14469 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014470 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014471}
14472
14473/**
14474 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14475 * @type: the Union Simple Type
14476 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014477 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014478 * returns NULL otherwise.
14479 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014480static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014481xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14482{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014483 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014484 if (type->memberTypes != NULL)
14485 return (type->memberTypes);
14486 else
14487 type = type->baseType;
14488 }
14489 return (NULL);
14490}
14491
14492/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014493 * xmlSchemaGetParticleTotalRangeMin:
14494 * @particle: the particle
14495 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014496 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014497 * (all and sequence) + (choice)
14498 *
14499 * Returns the minimun Effective Total Range.
14500 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014501static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014502xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014503{
14504 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014505 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014506 return (0);
14507 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014508 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014509 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014510 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014511
14512 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014513 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014514 while (part != NULL) {
14515 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14516 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014517 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014518 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014519 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014520 if (cur == 0)
14521 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014522 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014523 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014524 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014525 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014526 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014527 } else {
14528 /* <all> and <sequence> */
14529 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014530 xmlSchemaParticlePtr part =
14531 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014532
14533 if (part == NULL)
14534 return (0);
14535 do {
14536 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14537 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014538 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014539 else
14540 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014541 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014542 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014543 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014544 }
14545}
14546
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014547/**
14548 * xmlSchemaGetParticleTotalRangeMax:
14549 * @particle: the particle
14550 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014551 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014552 * (all and sequence) + (choice)
14553 *
14554 * Returns the maximum Effective Total Range.
14555 */
14556static int
14557xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14558{
14559 if ((particle->children == NULL) ||
14560 (particle->children->children == NULL))
14561 return (0);
14562 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14563 int max = -1, cur;
14564 xmlSchemaParticlePtr part =
14565 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014566
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014567 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14568 if (part->children == NULL)
14569 continue;
14570 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14571 (part->children->type == XML_SCHEMA_TYPE_ANY))
14572 cur = part->maxOccurs;
14573 else
14574 cur = xmlSchemaGetParticleTotalRangeMax(part);
14575 if (cur == UNBOUNDED)
14576 return (UNBOUNDED);
14577 if ((max < cur) || (max == -1))
14578 max = cur;
14579 }
14580 /* TODO: Handle overflows? */
14581 return (particle->maxOccurs * max);
14582 } else {
14583 /* <all> and <sequence> */
14584 int sum = 0, cur;
14585 xmlSchemaParticlePtr part =
14586 (xmlSchemaParticlePtr) particle->children->children;
14587
14588 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14589 if (part->children == NULL)
14590 continue;
14591 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14592 (part->children->type == XML_SCHEMA_TYPE_ANY))
14593 cur = part->maxOccurs;
14594 else
14595 cur = xmlSchemaGetParticleTotalRangeMax(part);
14596 if (cur == UNBOUNDED)
14597 return (UNBOUNDED);
14598 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14599 return (UNBOUNDED);
14600 sum += cur;
14601 }
14602 /* TODO: Handle overflows? */
14603 return (particle->maxOccurs * sum);
14604 }
14605}
14606
14607/**
14608 * xmlSchemaIsParticleEmptiable:
14609 * @particle: the particle
14610 *
14611 * Schema Component Constraint: Particle Emptiable
14612 * Checks whether the given particle is emptiable.
14613 *
14614 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014615 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014616static int
14617xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14618{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014619 /*
14620 * SPEC (1) "Its {min occurs} is 0."
14621 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014622 if ((particle == NULL) || (particle->minOccurs == 0) ||
14623 (particle->children == NULL))
14624 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014625 /*
14626 * SPEC (2) "Its {term} is a group and the minimum part of the
14627 * effective total range of that group, [...] is 0."
14628 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014629 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014630 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014631 return (1);
14632 }
14633 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014634}
14635
14636/**
14637 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014638 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014639 * @type: the derived simple type definition
14640 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014641 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014642 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014643 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014644 * Type Derivation OK (Simple) (cos-st-derived-OK)
14645 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014646 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014647 * derived from @baseType.
14648 *
14649 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014650 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014651static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014652xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014653 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014654 xmlSchemaTypePtr baseType,
14655 int subset)
14656{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014657 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 * 1 They are the same type definition.
14659 * TODO: The identy check might have to be more complex than this.
14660 */
14661 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014662 return (0);
14663 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 * 2.1 restriction is not in the subset, or in the {final}
14665 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014666 *
14667 * NOTE that this will be used also via "xsi:type".
14668 *
14669 * TODO: Revise this, it looks strange. How can the "type"
14670 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014671 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014672 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014673 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014674 return(-1);
14675 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014676 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014677 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014678 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014679 (xmlSchemaTypeFinalContains(type->baseType,
14680 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14681 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 }
14683 /* 2.2 */
14684 if (type->baseType == baseType) {
14685 /*
14686 * 2.2.1 D's ·base type definition· is B.
14687 */
14688 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014689 }
14690 /*
14691 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14692 * and is validly derived from B given the subset, as defined by this
14693 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014694 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014695 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014696 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014697 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014698 return (0);
14699 }
14700 /*
14701 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 * definition·.
14703 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014704 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14705 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014706 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014707 }
14708 /*
14709 * 2.2.4 B's {variety} is union and D is validly derived from a type
14710 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014711 * defined by this constraint.
14712 *
14713 * NOTE: This seems not to involve built-in types, since there is no
14714 * built-in Union Simple Type.
14715 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014716 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014717 xmlSchemaTypeLinkPtr cur;
14718
14719 cur = baseType->memberTypes;
14720 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014721 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014722 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014723 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014724 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014725 type, cur->type, subset) == 0)
14726 {
14727 /*
14728 * It just has to be validly derived from at least one
14729 * member-type.
14730 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014731 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014732 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014733 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014734 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014735 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014736 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14737}
14738
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014739/**
14740 * xmlSchemaCheckTypeDefCircularInternal:
14741 * @pctxt: the schema parser context
14742 * @ctxtType: the type definition
14743 * @ancestor: an ancestor of @ctxtType
14744 *
14745 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 *
14748 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14749 * circular, 0 otherwise.
14750 */
14751static int
14752xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14753 xmlSchemaTypePtr ctxtType,
14754 xmlSchemaTypePtr ancestor)
14755{
14756 int ret;
14757
14758 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14759 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014760
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761 if (ctxtType == ancestor) {
14762 xmlSchemaPCustomErr(pctxt,
14763 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014764 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014765 "The definition is circular", NULL);
14766 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14767 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014768 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14769 /*
14770 * Avoid inifinite recursion on circular types not yet checked.
14771 */
14772 return (0);
14773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014774 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14775 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14776 ancestor->baseType);
14777 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14778 return (ret);
14779}
14780
14781/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014782 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014783 * @item: the complex/simple type definition
14784 * @ctxt: the parser context
14785 * @name: the name
14786 *
14787 * Checks for circular type definitions.
14788 */
14789static void
14790xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014791 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014792{
14793 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014794 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14795 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014796 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014797 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14798 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014799}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014800
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014801/*
14802* Simple Type Definition Representation OK (src-simple-type) 4
14803*
14804* "4 Circular union type definition is disallowed. That is, if the
14805* <union> alternative is chosen, there must not be any entries in the
14806* memberTypes [attribute] at any depth which resolve to the component
14807* corresponding to the <simpleType>."
14808*
14809* Note that this should work on the *representation* of a component,
14810* thus assumes any union types in the member types not being yet
14811* substituted. At this stage we need the variety of the types
14812* to be already computed.
14813*/
14814static int
14815xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14816 xmlSchemaTypePtr ctxType,
14817 xmlSchemaTypeLinkPtr members)
14818{
14819 xmlSchemaTypeLinkPtr member;
14820 xmlSchemaTypePtr memberType;
14821
14822 member = members;
14823 while (member != NULL) {
14824 memberType = member->type;
14825 while ((memberType != NULL) &&
14826 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14827 if (memberType == ctxType) {
14828 xmlSchemaPCustomErr(pctxt,
14829 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014830 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014831 "The union type definition is circular", NULL);
14832 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14833 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014834 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014835 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14836 {
14837 int res;
14838 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14839 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14840 ctxType,
14841 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14842 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14843 if (res != 0)
14844 return(res);
14845 }
14846 memberType = memberType->baseType;
14847 }
14848 member = member->next;
14849 }
14850 return(0);
14851}
14852
14853static int
14854xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14855 xmlSchemaTypePtr type)
14856{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014857 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014858 return(0);
14859 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14860 type->memberTypes));
14861}
14862
Daniel Veillard01fa6152004-06-29 17:04:39 +000014863/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014864 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014865 * @item: the complex/simple type definition
14866 * @ctxt: the parser context
14867 * @name: the name
14868 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014869 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014870 */
14871static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014872xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014873 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014874{
14875 if (typeDef == NULL)
14876 return;
14877
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014878 /*
14879 * Resolve the base type.
14880 */
14881 if (typeDef->baseType == NULL) {
14882 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14883 typeDef->base, typeDef->baseNs);
14884 if (typeDef->baseType == NULL) {
14885 xmlSchemaPResCompAttrErr(ctxt,
14886 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014887 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014888 "base", typeDef->base, typeDef->baseNs,
14889 XML_SCHEMA_TYPE_SIMPLE, NULL);
14890 return;
14891 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014892 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014893 if (WXS_IS_SIMPLE(typeDef)) {
14894 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014895 /*
14896 * Resolve the memberTypes.
14897 */
14898 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14899 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014900 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014901 /*
14902 * Resolve the itemType.
14903 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014904 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14905
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014906 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014907 typeDef->base, typeDef->baseNs);
14908
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014909 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014910 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14911 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014912 typeDef->subtypes = NULL;
14913 xmlSchemaPResCompAttrErr(ctxt,
14914 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014915 WXS_BASIC_CAST typeDef, typeDef->node,
14916 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 XML_SCHEMA_TYPE_SIMPLE, NULL);
14918 }
14919 }
14920 return;
14921 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014922 }
14923 /*
14924 * The ball of letters below means, that if we have a particle
14925 * which has a QName-helper component as its {term}, we want
14926 * to resolve it...
14927 */
14928 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14929 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14930 XML_SCHEMA_TYPE_PARTICLE) &&
14931 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14932 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14933 XML_SCHEMA_EXTRA_QNAMEREF))
14934 {
14935 xmlSchemaQNameRefPtr ref =
14936 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14937 xmlSchemaModelGroupDefPtr groupDef;
14938
14939 /*
14940 * URGENT TODO: Test this.
14941 */
14942 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14943 /*
14944 * Resolve the MG definition reference.
14945 */
14946 groupDef =
14947 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14948 ref->itemType, ref->name, ref->targetNamespace);
14949 if (groupDef == NULL) {
14950 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14951 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14952 "ref", ref->name, ref->targetNamespace, ref->itemType,
14953 NULL);
14954 /* Remove the particle. */
14955 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14956 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14957 /* Remove the particle. */
14958 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14959 else {
14960 /*
14961 * Assign the MG definition's {model group} to the
14962 * particle's {term}.
14963 */
14964 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14965
14966 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14967 /*
14968 * SPEC cos-all-limited (1.2)
14969 * "1.2 the {term} property of a particle with
14970 * {max occurs}=1 which is part of a pair which constitutes
14971 * the {content type} of a complex type definition."
14972 */
14973 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14974 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14975 /* TODO: error code */
14976 XML_SCHEMAP_COS_ALL_LIMITED,
14977 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14978 "The particle's {max occurs} must be 1, since the "
14979 "reference resolves to an 'all' model group",
14980 NULL, NULL);
14981 }
14982 }
14983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014984 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014985}
14986
14987
14988
14989/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014990 * xmlSchemaCheckSTPropsCorrect:
14991 * @ctxt: the schema parser context
14992 * @type: the simple type definition
14993 *
14994 * Checks st-props-correct.
14995 *
14996 * Returns 0 if the properties are correct,
14997 * if not, a positive error code and -1 on internal
14998 * errors.
14999 */
15000static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015001xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015002 xmlSchemaTypePtr type)
15003{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015004 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015005 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015006
Daniel Veillardc0826a72004-08-10 14:17:33 +000015007 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015008 /*
15009 * Schema Component Constraint: Simple Type Definition Properties Correct
15010 *
15011 * NOTE: This is somehow redundant, since we actually built a simple type
15012 * to have all the needed information; this acts as an self test.
15013 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015014 /* Base type: If the datatype has been ·derived· by ·restriction·
15015 * then the Simple Type Definition component from which it is ·derived·,
15016 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015017 */
15018 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015019 /*
15020 * TODO: Think about: "modulo the impact of Missing
15021 * Sub-components (§5.3)."
15022 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015023 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015024 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015025 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015026 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015027 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015028
Daniel Veillard01fa6152004-06-29 17:04:39 +000015029 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015030 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015031 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015032 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015033 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015034 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015035 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015036 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015037 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15038 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015039 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015040 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015041 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015042 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015044 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015045 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015046 "the simple ur-type definition as base type, not '%s'",
15047 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015048 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015049 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15050 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015051 /*
15052 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015054 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15055 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015056 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015057 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015058 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015059 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015060 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15061 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015062 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015063
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015064 /*
15065 * 3 The {final} of the {base type definition} must not contain restriction.
15066 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015067 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015068 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15069 xmlSchemaPCustomErr(ctxt,
15070 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015071 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015072 "The 'final' of its base type '%s' must not contain "
15073 "'restriction'",
15074 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015075 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015076 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015078
15079 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015080 * 2 All simple type definitions must be derived ultimately from the ·simple
15081 * ur-type definition (so· circular definitions are disallowed). That is, it
15082 * must be possible to reach a built-in primitive datatype or the ·simple
15083 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015084 *
15085 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015086 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015087 return (0);
15088}
15089
15090/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015091 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015092 * @ctxt: the schema parser context
15093 * @type: the simple type definition
15094 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015095 * Schema Component Constraint:
15096 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15097
15098 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015099 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015100 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015101 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015102 * a positive error code otherwise.
15103 */
15104static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015105xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015106 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015107{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015108 xmlChar *str = NULL;
15109
Daniel Veillard01fa6152004-06-29 17:04:39 +000015110 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015111 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15112 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015113 return (-1);
15114 }
15115
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015116 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015117 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015118 /*
15119 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015120 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015121 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015122 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015123 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015124 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015125 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015126 "The base type '%s' is not an atomic simple type",
15127 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015128 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015129 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15130 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015131 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015132 * restriction.
15133 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015134 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015135 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015136 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015137 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015138 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015139 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015140 "The final of its base type '%s' must not contain 'restriction'",
15141 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015142 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015143 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15144 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015145
15146 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015147 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015148 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015149 * Primitive datatypes.
15150 */
15151 if (type->facets != NULL) {
15152 xmlSchemaFacetPtr facet;
15153 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015154
Daniel Veillard01fa6152004-06-29 17:04:39 +000015155 primitive = xmlSchemaGetPrimitiveType(type);
15156 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015157 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15158 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015159 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015160 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015161 facet = type->facets;
15162 do {
15163 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015164 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015165 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015166 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015167 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015168 }
15169 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015170 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015171 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015172 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015173 }
15174 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015175 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15176 * of the {base type definition} (call this BF),then the DF's {value}
15177 * must be a valid restriction of BF's {value} as defined in
15178 * [XML Schemas: Datatypes]."
15179 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015181 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015182 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015183 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015184 xmlSchemaTypePtr itemType = NULL;
15185
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015186 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015187 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015188 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15189 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015190 return (-1);
15191 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015192 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015193 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015194 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015195 * 2.1 The {item type definition} must have a {variety} of atomic or
15196 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015197 * must be atomic).
15198 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015199 if ((! WXS_IS_ATOMIC(itemType)) &&
15200 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015201 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015202 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015203 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015204 "The item type '%s' does not have a variety of atomic or union",
15205 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015206 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015207 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015208 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015209 xmlSchemaTypeLinkPtr member;
15210
15211 member = itemType->memberTypes;
15212 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015213 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015214 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015215 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015216 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015217 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015218 "member type '%s' of this item type is not atomic",
15219 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015220 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015221 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15222 }
15223 member = member->next;
15224 }
15225 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015226
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015227 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015228 xmlSchemaFacetPtr facet;
15229 /*
15230 * This is the case if we have: <simpleType><list ..
15231 */
15232 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015233 * 2.3.1
15234 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015235 * contain list.
15236 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015237 if (xmlSchemaTypeFinalContains(itemType,
15238 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15239 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015240 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015241 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015242 "The final of its item type '%s' must not contain 'list'",
15243 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015244 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015245 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15246 }
15247 /*
15248 * 2.3.1.2 The {facets} must only contain the whiteSpace
15249 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015250 * OPTIMIZE TODO: the S4S already disallows any facet
15251 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015252 */
15253 if (type->facets != NULL) {
15254 facet = type->facets;
15255 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015256 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015257 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015258 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015259 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015260 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15261 }
15262 facet = facet->next;
15263 } while (facet != NULL);
15264 }
15265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015266 * MAYBE TODO: (Hmm, not really) Datatypes states:
15267 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15268 * whose ·lexical space· allows space (such as string or anyURI)or
15269 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015270 * ·lexical space· allows space.
15271 */
15272 } else {
15273 /*
15274 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015275 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015276 */
15277 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015278 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015279 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15280 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015281 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015282 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015283 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015284 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 "The base type '%s' must be a list type",
15286 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015287 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015288 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15289 }
15290 /*
15291 * 2.3.2.2 The {final} of the {base type definition} must not
15292 * contain restriction.
15293 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015294 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015295 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015296 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015297 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015298 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015299 "The 'final' of the base type '%s' must not contain 'restriction'",
15300 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015301 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015302 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15303 }
15304 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015305 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015306 * from the {base type definition}'s {item type definition} given
15307 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15308 */
15309 {
15310 xmlSchemaTypePtr baseItemType;
15311
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015312 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015313 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015314 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15315 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015316 return (-1);
15317 }
15318 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015319 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015320 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015321 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015322 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015323 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015324 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015325 "The item type '%s' is not validly derived from "
15326 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015327 xmlSchemaGetComponentQName(&str, itemType),
15328 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15329 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015330
15331 FREE_AND_NULL(str)
15332 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015333 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015334 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15335 }
15336 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015337
Daniel Veillard01fa6152004-06-29 17:04:39 +000015338 if (type->facets != NULL) {
15339 xmlSchemaFacetPtr facet;
15340 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341 /*
15342 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015343 * and enumeration facet components are allowed among the {facets}.
15344 */
15345 facet = type->facets;
15346 do {
15347 switch (facet->type) {
15348 case XML_SCHEMA_FACET_LENGTH:
15349 case XML_SCHEMA_FACET_MINLENGTH:
15350 case XML_SCHEMA_FACET_MAXLENGTH:
15351 case XML_SCHEMA_FACET_WHITESPACE:
15352 /*
15353 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015354 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015355 */
15356 case XML_SCHEMA_FACET_PATTERN:
15357 case XML_SCHEMA_FACET_ENUMERATION:
15358 break;
15359 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015360 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015361 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015362 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015363 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015364 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015365 * invalid facets.
15366 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015367 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015369 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015370 facet = facet->next;
15371 } while (facet != NULL);
15372 if (ok == 0)
15373 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15374 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015375 * SPEC (2.3.2.5) (same as 1.3.2)
15376 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015377 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015378 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015380 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015381 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015382 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015383 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015384 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015385 * atomic or list.
15386 */
15387 xmlSchemaTypeLinkPtr member;
15388
15389 member = type->memberTypes;
15390 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015391 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015392 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015394 if ((! WXS_IS_ATOMIC(member->type)) &&
15395 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015396 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015397 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015398 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015399 "The member type '%s' is neither an atomic, nor a list type",
15400 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015401 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015402 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15403 }
15404 member = member->next;
15405 }
15406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015407 * 3.3.1 If the {base type definition} is the ·simple ur-type
15408 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015409 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015410 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015411 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015412 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015413 * {final} which does not contain union.
15414 */
15415 member = type->memberTypes;
15416 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015417 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015418 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015419 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015420 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015421 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015422 "The 'final' of member type '%s' contains 'union'",
15423 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015424 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015425 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15426 }
15427 member = member->next;
15428 }
15429 /*
15430 * 3.3.1.2 The {facets} must be empty.
15431 */
15432 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015433 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015434 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015435 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015436 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015437 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15438 }
15439 } else {
15440 /*
15441 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015442 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015443 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015444 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015445 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015446 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015447 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015448 "The base type '%s' is not a union type",
15449 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015450 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015451 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15452 }
15453 /*
15454 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15455 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015456 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015457 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015458 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015459 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015460 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015461 "The 'final' of its base type '%s' must not contain 'restriction'",
15462 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015463 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015464 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15465 }
15466 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467 * 3.3.2.3 The {member type definitions}, in order, must be validly
15468 * derived from the corresponding type definitions in the {base
15469 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015470 * as defined in Type Derivation OK (Simple) (§3.14.6).
15471 */
15472 {
15473 xmlSchemaTypeLinkPtr baseMember;
15474
15475 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015476 * OPTIMIZE: if the type is restricting, it has no local defined
15477 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015478 * thus a check for equality can be skipped.
15479 */
15480 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015481 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015482 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015483 * types of it's base type. This check seems not necessary with
15484 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015485 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015486 */
15487 if (type->memberTypes != NULL) {
15488 member = type->memberTypes;
15489 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015490 if ((member == NULL) && (baseMember != NULL)) {
15491 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15492 "different number of member types in base");
15493 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015494 while (member != NULL) {
15495 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015496 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15497 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015498 }
15499 if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015500 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015501 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015502 xmlChar *strBMT = NULL, *strBT = NULL;
15503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015504 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015505 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015506 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015507 "The member type %s is not validly "
15508 "derived from its corresponding member "
15509 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015510 xmlSchemaGetComponentQName(&str, member->type),
15511 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15512 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015513 FREE_AND_NULL(str)
15514 FREE_AND_NULL(strBMT)
15515 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015516 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015517 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015518 member = member->next;
15519 baseMember = baseMember->next;
15520 }
15521 }
15522 }
15523 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015524 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015525 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015526 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015527 if (type->facets != NULL) {
15528 xmlSchemaFacetPtr facet;
15529 int ok = 1;
15530
15531 facet = type->facets;
15532 do {
15533 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15534 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015535 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015536 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015537 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015538 ok = 0;
15539 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015540 facet = facet->next;
15541 } while (facet != NULL);
15542 if (ok == 0)
15543 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015544
Daniel Veillard01fa6152004-06-29 17:04:39 +000015545 }
15546 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015547 * SPEC (3.3.2.5) (same as 1.3.2)
15548 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015549 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015550 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015551 */
15552 }
15553 }
15554
15555 return (0);
15556}
15557
15558/**
15559 * xmlSchemaCheckSRCSimpleType:
15560 * @ctxt: the schema parser context
15561 * @type: the simple type definition
15562 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015563 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015564 *
15565 * Returns 0 if the constraints are satisfied,
15566 * if not a positive error code and -1 on internal
15567 * errors.
15568 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015569#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015570static int
15571xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15572 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015573{
15574 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015575 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015576 * must satisfy the conditions set out in Constraints on Simple Type
15577 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015578 */
15579 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015580 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015581 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015582 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015583 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015584 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015585 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015586 /*
15587 *
15588 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015589 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015590 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015591 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015592 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015593 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015594 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015595 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015596 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015597 /*
15598 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015599 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015600 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015601 return (0);
15602}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015603#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015604
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015605static int
15606xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15607{
15608 if (ctxt->vctxt == NULL) {
15609 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15610 if (ctxt->vctxt == NULL) {
15611 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015612 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015613 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015614 "failed to create a temp. validation context.\n",
15615 NULL, NULL);
15616 return (-1);
15617 }
15618 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015619 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015620 ctxt->error, ctxt->warning, ctxt->errCtxt);
15621 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15622 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015623 }
15624 return (0);
15625}
15626
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015627static int
15628xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15629 xmlNodePtr node,
15630 xmlSchemaTypePtr type,
15631 const xmlChar *value,
15632 xmlSchemaValPtr *retVal,
15633 int fireErrors,
15634 int normalize,
15635 int isNormalized);
15636
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015637/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015638 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015639 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015640 * @type: the simple type definition
15641 * @value: the default value
15642 * @node: an optional node (the holder of the value)
15643 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015644 * Schema Component Constraint: Element Default Valid (Immediate)
15645 * (cos-valid-default)
15646 * This will be used by the parser only. For the validator there's
15647 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015648 *
15649 * Returns 0 if the constraints are satisfied,
15650 * if not, a positive error code and -1 on internal
15651 * errors.
15652 */
15653static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15655 xmlNodePtr node,
15656 xmlSchemaTypePtr type,
15657 const xmlChar *value,
15658 xmlSchemaValPtr *val)
15659{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015660 int ret = 0;
15661
15662 /*
15663 * cos-valid-default:
15664 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015665 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015666 * definition the appropriate case among the following must be true:
15667 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015668 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015669 /*
15670 * Complex type.
15671 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015672 * SPEC (2.1) "its {content type} must be a simple type definition
15673 * or mixed."
15674 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015676 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015677 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015678 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15679 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015680 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015681 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015682 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015683 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015684 "For a string to be a valid default, the type definition "
15685 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015687 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15688 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015689 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015691 * 1 If the type definition is a simple type definition, then the string
15692 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015693 * Valid (§3.14.4).
15694 *
15695 * AND
15696 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015697 * 2.2.1 If the {content type} is a simple type definition, then the
15698 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015699 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015700 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015701 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015702 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015703 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015704 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015705 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015706 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015707 else
15708 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015709
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015710 if (ret < 0) {
15711 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15712 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015714
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015715 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015716}
15717
15718/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015719 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015720 * @ctxt: the schema parser context
15721 * @type: the complex type definition
15722 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015723 *.(4.6) Constraints on Complex Type Definition Schema Components
15724 * Schema Component Constraint:
15725 * Complex Type Definition Properties Correct (ct-props-correct)
15726 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015727 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015728 * Returns 0 if the constraints are satisfied, a positive
15729 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015730 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015731static int
15732xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15733 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015734{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015735 /*
15736 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15737 *
15738 * SPEC (1) "The values of the properties of a complex type definition must
15739 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015740 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015741 * Sub-components (§5.3)."
15742 */
15743 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015744 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015745 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 /*
15747 * SPEC (2) "If the {base type definition} is a simple type definition,
15748 * the {derivation method} must be extension."
15749 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015750 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015752 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015753 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015754 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015755 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015756 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015757 /*
15758 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15759 * definition·. That is, it must be possible to reach the ·ur-type
15760 * definition by repeatedly following the {base type definition}."
15761 *
15762 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015763 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015764 /*
15765 * NOTE that (4) and (5) need the following:
15766 * - attribute uses need to be already inherited (apply attr. prohibitions)
15767 * - attribute group references need to be expanded already
15768 * - simple types need to be typefixed already
15769 */
15770 if (type->attrUses &&
15771 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15772 {
15773 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15774 xmlSchemaAttributeUsePtr use, tmp;
15775 int i, j, hasId = 0;
15776
15777 for (i = uses->nbItems -1; i >= 0; i--) {
15778 use = uses->items[i];
15779
15780 /*
15781 * SPEC ct-props-correct
15782 * (4) "Two distinct attribute declarations in the
15783 * {attribute uses} must not have identical {name}s and
15784 * {target namespace}s."
15785 */
15786 if (i > 0) {
15787 for (j = i -1; j >= 0; j--) {
15788 tmp = uses->items[j];
15789 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15790 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15791 (WXS_ATTRUSE_DECL_TNS(use) ==
15792 WXS_ATTRUSE_DECL_TNS(tmp)))
15793 {
15794 xmlChar *str = NULL;
15795
15796 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15797 XML_SCHEMAP_AG_PROPS_CORRECT,
15798 NULL, WXS_BASIC_CAST type,
15799 "Duplicate %s",
15800 xmlSchemaGetComponentDesignation(&str, use),
15801 NULL);
15802 FREE_AND_NULL(str);
15803 /*
15804 * Remove the duplicate.
15805 */
15806 if (xmlSchemaItemListRemove(uses, i) == -1)
15807 goto exit_failure;
15808 goto next_use;
15809 }
15810 }
15811 }
15812 /*
15813 * SPEC ct-props-correct
15814 * (5) "Two distinct attribute declarations in the
15815 * {attribute uses} must not have {type definition}s which
15816 * are or are derived from ID."
15817 */
15818 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15819 if (xmlSchemaIsDerivedFromBuiltInType(
15820 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15821 {
15822 if (hasId) {
15823 xmlChar *str = NULL;
15824
15825 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15826 XML_SCHEMAP_AG_PROPS_CORRECT,
15827 NULL, WXS_BASIC_CAST type,
15828 "There must not exist more than one attribute "
15829 "declaration of type 'xs:ID' "
15830 "(or derived from 'xs:ID'). The %s violates this "
15831 "constraint",
15832 xmlSchemaGetComponentDesignation(&str, use),
15833 NULL);
15834 FREE_AND_NULL(str);
15835 if (xmlSchemaItemListRemove(uses, i) == -1)
15836 goto exit_failure;
15837 }
15838
15839 hasId = 1;
15840 }
15841 }
15842next_use: {}
15843 }
15844 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015845 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015846exit_failure:
15847 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015848}
15849
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015850static int
15851xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15852 xmlSchemaTypePtr typeB)
15853{
15854 /*
15855 * TODO: This should implement component-identity
15856 * in the future.
15857 */
15858 if ((typeA == NULL) || (typeB == NULL))
15859 return (0);
15860 return (typeA == typeB);
15861}
15862
15863/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015864 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015865 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015866 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015867 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015868 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015869 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015870 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015871 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15872 *
15873 * STATUS: completed
15874 *
15875 * Returns 0 if the constraints are satisfied, or 1
15876 * if not.
15877 */
15878static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015879xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015880 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015881 xmlSchemaTypePtr baseType,
15882 int set)
15883{
15884 int equal = xmlSchemaAreEqualTypes(type, baseType);
15885 /* TODO: Error codes. */
15886 /*
15887 * SPEC "For a complex type definition (call it D, for derived)
15888 * to be validly derived from a type definition (call this
15889 * B, for base) given a subset of {extension, restriction}
15890 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015891 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015892 if (! equal) {
15893 /*
15894 * SPEC (1) "If B and D are not the same type definition, then the
15895 * {derivation method} of D must not be in the subset."
15896 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015897 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15898 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015899 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015900 } else {
15901 /*
15902 * SPEC (2.1) "B and D must be the same type definition."
15903 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015904 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015905 }
15906 /*
15907 * SPEC (2.2) "B must be D's {base type definition}."
15908 */
15909 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015910 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015911 /*
15912 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15913 * definition·."
15914 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015915 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015916 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015917
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015918 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015919 /*
15920 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15921 * must be validly derived from B given the subset as defined by this
15922 * constraint."
15923 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015924 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015925 baseType, set));
15926 } else {
15927 /*
15928 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15929 * must be validly derived from B given the subset as defined in Type
15930 * Derivation OK (Simple) (§3.14.6).
15931 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015932 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015933 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015934 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015935}
15936
15937/**
15938 * xmlSchemaCheckCOSDerivedOK:
15939 * @type: the derived simple type definition
15940 * @baseType: the base type definition
15941 *
15942 * Calls:
15943 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015944 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015945 * Checks wheter @type can be validly derived from @baseType.
15946 *
15947 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015948 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015949static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015950xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015951 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015952 xmlSchemaTypePtr baseType,
15953 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015954{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015955 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015956 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015957 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015958 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015959}
15960
William M. Brack2f2a6632004-08-20 23:09:47 +000015961/**
15962 * xmlSchemaCheckCOSCTExtends:
15963 * @ctxt: the schema parser context
15964 * @type: the complex type definition
15965 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015966 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015967 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015968 * Derivation Valid (Extension) (cos-ct-extends)
15969 *
15970 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015971 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015972 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015973 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015974 *
15975 * Returns 0 if the constraints are satisfied, a positive
15976 * error code if not and -1 if an internal error occured.
15977 */
15978static int
15979xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15980 xmlSchemaTypePtr type)
15981{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015982 xmlSchemaTypePtr base = type->baseType;
15983 /*
15984 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15985 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015986 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015987 /*
15988 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015989 * then all of the following must be true:"
15990 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015991 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015992 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015993 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015994 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015995 */
15996 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15997 xmlSchemaPCustomErr(ctxt,
15998 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015999 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016000 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016001 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016002 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16003 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016004
16005 /*
16006 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16007 * since they are automatically satisfied through the
16008 * inheriting mechanism.
16009 * Note that even if redefining components, the inheriting mechanism
16010 * is used.
16011 */
16012#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016013 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016014 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016015 * uses}
16016 * of the complex type definition itself, that is, for every attribute
16017 * use in the {attribute uses} of the {base type definition}, there
16018 * must be an attribute use in the {attribute uses} of the complex
16019 * type definition itself whose {attribute declaration} has the same
16020 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016021 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016022 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016023 if (base->attrUses != NULL) {
16024 int i, j, found;
16025 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016026
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016027 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16028 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16029 found = 0;
16030 if (type->attrUses != NULL) {
16031 use = (WXS_LIST_CAST type->attrUses)->items[j];
16032 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16033 {
16034 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16035 WXS_ATTRUSE_DECL_NAME(buse)) &&
16036 (WXS_ATTRUSE_DECL_TNS(use) ==
16037 WXS_ATTRUSE_DECL_TNS(buse)) &&
16038 (WXS_ATTRUSE_TYPEDEF(use) ==
16039 WXS_ATTRUSE_TYPEDEF(buse))
16040 {
16041 found = 1;
16042 break;
16043 }
16044 }
16045 }
16046 if (! found) {
16047 xmlChar *str = NULL;
16048
16049 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16050 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16051 NULL, WXS_BASIC_CAST type,
16052 /*
16053 * TODO: The report does not indicate that also the
16054 * type needs to be the same.
16055 */
16056 "This type is missing a matching correspondent "
16057 "for its {base type}'s %s in its {attribute uses}",
16058 xmlSchemaGetComponentDesignation(&str,
16059 buse->children),
16060 NULL);
16061 FREE_AND_NULL(str)
16062 }
16063 }
16064 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016065 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016066 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16067 * definition must also have one, and the base type definition's
16068 * {attribute wildcard}'s {namespace constraint} must be a subset
16069 * of the complex type definition's {attribute wildcard}'s {namespace
16070 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016071 */
16072
16073 /*
16074 * MAYBE TODO: Enable if ever needed. But this will be needed only
16075 * if created the type via a schema construction API.
16076 */
16077 if (base->attributeWildcard != NULL) {
16078 if (type->attributeWilcard == NULL) {
16079 xmlChar *str = NULL;
16080
16081 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16082 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16083 NULL, type,
16084 "The base %s has an attribute wildcard, "
16085 "but this type is missing an attribute wildcard",
16086 xmlSchemaGetComponentDesignation(&str, base));
16087 FREE_AND_NULL(str)
16088
16089 } else if (xmlSchemaCheckCOSNSSubset(
16090 base->attributeWildcard, type->attributeWildcard))
16091 {
16092 xmlChar *str = NULL;
16093
16094 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16095 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16096 NULL, type,
16097 "The attribute wildcard is not a valid "
16098 "superset of the one in the base %s",
16099 xmlSchemaGetComponentDesignation(&str, base));
16100 FREE_AND_NULL(str)
16101 }
16102 }
16103#endif
16104 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016105 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016106 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016107 if ((type->contentTypeDef != NULL) &&
16108 (type->contentTypeDef == base->contentTypeDef)) {
16109 /*
16110 * SPEC (1.4.1) "The {content type} of the {base type definition}
16111 * and the {content type} of the complex type definition itself
16112 * must be the same simple type definition"
16113 * PASS
16114 */
16115 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16116 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16117 /*
16118 * SPEC (1.4.2) "The {content type} of both the {base type
16119 * definition} and the complex type definition itself must
16120 * be empty."
16121 * PASS
16122 */
16123 } else {
16124 /*
16125 * SPEC (1.4.3) "All of the following must be true:"
16126 */
16127 if (type->subtypes == NULL) {
16128 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016129 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016130 * definition itself must specify a particle.
16131 */
16132 xmlSchemaPCustomErr(ctxt,
16133 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016134 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016135 "The content type must specify a particle", NULL);
16136 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16137 }
16138 /*
16139 * SPEC (1.4.3.2) "One of the following must be true:"
16140 */
16141 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16142 /*
16143 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16144 * definition} must be empty.
16145 * PASS
16146 */
16147 } else {
16148 /*
16149 * SPEC (1.4.3.2.2) "All of the following must be true:"
16150 */
16151 if ((type->contentType != base->contentType) ||
16152 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16153 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16154 /*
16155 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16156 * or both must be element-only."
16157 */
16158 xmlSchemaPCustomErr(ctxt,
16159 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016160 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 "The content type of both, the type and its base "
16162 "type, must either 'mixed' or 'element-only'", NULL);
16163 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016164 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016165 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016166 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016167 * complex type definition must be a ·valid extension·
16168 * of the {base type definition}'s particle, as defined
16169 * in Particle Valid (Extension) (§3.9.6)."
16170 *
16171 * NOTE that we won't check "Particle Valid (Extension)",
16172 * since it is ensured by the derivation process in
16173 * xmlSchemaTypeFixup(). We need to implement this when heading
16174 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016175 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016176 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016177 }
16178 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016179 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016180 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016181 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016182 } else {
16183 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016184 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016185 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016186 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016187 if (type->contentTypeDef != base) {
16188 /*
16189 * SPEC (2.1) "The {content type} must be the same simple type
16190 * definition."
16191 */
16192 xmlSchemaPCustomErr(ctxt,
16193 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016194 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 "The content type must be the simple base type", NULL);
16196 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16197 }
16198 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16199 /*
16200 * SPEC (2.2) "The {final} of the {base type definition} must not
16201 * contain extension"
16202 * NOTE that this is the same as (1.1).
16203 */
16204 xmlSchemaPCustomErr(ctxt,
16205 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016206 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016207 "The 'final' of the base type definition "
16208 "contains 'extension'", NULL);
16209 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016210 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016211 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016212 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016213}
16214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215/**
16216 * xmlSchemaCheckDerivationOKRestriction:
16217 * @ctxt: the schema parser context
16218 * @type: the complex type definition
16219 *
16220 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016221 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016222 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16223 *
16224 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016226 * (5.4.2) ???
16227 *
16228 * ATTENTION:
16229 * In XML Schema 1.1 this will be:
16230 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016231 *
16232 * Returns 0 if the constraints are satisfied, a positive
16233 * error code if not and -1 if an internal error occured.
16234 */
16235static int
16236xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16237 xmlSchemaTypePtr type)
16238{
16239 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016240
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016241 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016242 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016243 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016244 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016245 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016246 if (! WXS_IS_COMPLEX(base)) {
16247 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16248 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16249 type->node, WXS_BASIC_CAST type,
16250 "The base type must be a complex type", NULL, NULL);
16251 return(ctxt->err);
16252 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016253 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16254 /*
16255 * SPEC (1) "The {base type definition} must be a complex type
16256 * definition whose {final} does not contain restriction."
16257 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016258 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16259 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16260 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016261 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016262 "contains 'restriction'", NULL, NULL);
16263 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 }
16265 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016266 * SPEC (2), (3) and (4)
16267 * Those are handled in a separate function, since the
16268 * same constraints are needed for redefinition of
16269 * attribute groups as well.
16270 */
16271 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16272 XML_SCHEMA_ACTION_DERIVE,
16273 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16274 type->attrUses, base->attrUses,
16275 type->attributeWildcard,
16276 base->attributeWildcard) == -1)
16277 {
16278 return(-1);
16279 }
16280 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016281 * SPEC (5) "One of the following must be true:"
16282 */
16283 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16284 /*
16285 * SPEC (5.1) "The {base type definition} must be the
16286 * ·ur-type definition·."
16287 * PASS
16288 */
16289 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16290 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16291 /*
16292 * SPEC (5.2.1) "The {content type} of the complex type definition
16293 * must be a simple type definition"
16294 *
16295 * SPEC (5.2.2) "One of the following must be true:"
16296 */
16297 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016298 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16299 {
16300 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016301 /*
16302 * SPEC (5.2.2.1) "The {content type} of the {base type
16303 * definition} must be a simple type definition from which
16304 * the {content type} is validly derived given the empty
16305 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016306 *
16307 * ATTENTION TODO: This seems not needed if the type implicitely
16308 * derived from the base type.
16309 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016310 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016311 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16312 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016313 if (err != 0) {
16314 xmlChar *strA = NULL, *strB = NULL;
16315
16316 if (err == -1)
16317 return(-1);
16318 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16319 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16320 NULL, WXS_BASIC_CAST type,
16321 "The {content type} %s is not validly derived from the "
16322 "base type's {content type} %s",
16323 xmlSchemaGetComponentDesignation(&strA,
16324 type->contentTypeDef),
16325 xmlSchemaGetComponentDesignation(&strB,
16326 base->contentTypeDef));
16327 FREE_AND_NULL(strA);
16328 FREE_AND_NULL(strB);
16329 return(ctxt->err);
16330 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16332 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016333 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016334 /*
16335 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16336 * and have a particle which is ·emptiable· as defined in
16337 * Particle Emptiable (§3.9.6)."
16338 * PASS
16339 */
16340 } else {
16341 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016342 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16343 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016344 "The content type of the base type must be either "
16345 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016346 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016347 }
16348 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16349 /*
16350 * SPEC (5.3.1) "The {content type} of the complex type itself must
16351 * be empty"
16352 */
16353 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016355 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016356 * definition} must also be empty."
16357 * PASS
16358 */
16359 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16360 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16361 xmlSchemaIsParticleEmptiable(
16362 (xmlSchemaParticlePtr) base->subtypes)) {
16363 /*
16364 * SPEC (5.3.2.2) "The {content type} of the {base type
16365 * definition} must be elementOnly or mixed and have a particle
16366 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16367 * PASS
16368 */
16369 } else {
16370 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016371 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16372 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016373 "The content type of the base type must be either "
16374 "empty or 'mixed' (or 'elements-only') and an emptiable "
16375 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016376 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 }
16378 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016379 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 /*
16381 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16382 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016383 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016384 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016385 /*
16386 * SPEC (5.4.1.2) "The {content type} of the complex type
16387 * definition itself and of the {base type definition} must be
16388 * mixed"
16389 */
16390 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016391 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16392 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 "If the content type is 'mixed', then the content type of the "
16394 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016395 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016396 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016397 /*
16398 * SPEC (5.4.2) "The particle of the complex type definition itself
16399 * must be a ·valid restriction· of the particle of the {content
16400 * type} of the {base type definition} as defined in Particle Valid
16401 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016402 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016403 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016405 } else {
16406 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016407 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16408 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016410 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016411 }
16412 return (0);
16413}
16414
16415/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016416 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016417 * @ctxt: the schema parser context
16418 * @type: the complex type definition
16419 *
16420 * (3.4.6) Constraints on Complex Type Definition Schema Components
16421 *
16422 * Returns 0 if the constraints are satisfied, a positive
16423 * error code if not and -1 if an internal error occured.
16424 */
16425static int
16426xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16427 xmlSchemaTypePtr type)
16428{
16429 int ret;
16430 /*
16431 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016432 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16434 if (ret != 0)
16435 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016436 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016437 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16438 else
16439 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16440 return (ret);
16441}
16442
16443/**
16444 * xmlSchemaCheckSRCCT:
16445 * @ctxt: the schema parser context
16446 * @type: the complex type definition
16447 *
16448 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016449 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016450 * Complex Type Definition Representation OK (src-ct)
16451 *
16452 * Returns 0 if the constraints are satisfied, a positive
16453 * error code if not and -1 if an internal error occured.
16454 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016455static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016456xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016457 xmlSchemaTypePtr type)
16458{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016459 xmlSchemaTypePtr base;
16460 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016461
16462 /*
16463 * TODO: Adjust the error codes here, as I used
16464 * XML_SCHEMAP_SRC_CT_1 only yet.
16465 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016466 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016467 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016468 /*
16469 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016470 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016471 * must be a complex type definition;
16472 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016473 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016474 xmlChar *str = NULL;
16475 xmlSchemaPCustomErr(ctxt,
16476 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016477 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016478 "If using <complexContent>, the base type is expected to be "
16479 "a complex type. The base type '%s' is a simple type",
16480 xmlSchemaFormatQName(&str, base->targetNamespace,
16481 base->name));
16482 FREE_AND_NULL(str)
16483 return (XML_SCHEMAP_SRC_CT_1);
16484 }
16485 } else {
16486 /*
16487 * SPEC
16488 * 2 If the <simpleContent> alternative is chosen, all of the
16489 * following must be true:
16490 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16491 * base [attribute] must be one of the following:
16492 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016493 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016494 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016495 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016496 /*
16497 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016498 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016499 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016500 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016501 xmlSchemaPCustomErr(ctxt,
16502 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016503 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016504 "If using <simpleContent> and <restriction>, the base "
16505 "type must be a complex type. The base type '%s' is "
16506 "a simple type",
16507 xmlSchemaFormatQName(&str, base->targetNamespace,
16508 base->name));
16509 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016510 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016511 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016512 } else {
16513 /* Base type is a complex type. */
16514 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16515 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16516 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016517 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016518 * simple type definition;
16519 * PASS
16520 */
16521 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016523 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016524 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016525 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016526 type->name);
16527 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016528 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016529 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016530 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016531
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016532 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016533 * 2.1.2 only if the <restriction> alternative is also
16534 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016535 * is mixed and a particle emptiable.
16536 */
16537 if (! xmlSchemaIsParticleEmptiable(
16538 (xmlSchemaParticlePtr) base->subtypes)) {
16539 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016540 } else
16541 /*
16542 * Attention: at this point the <simpleType> child is in
16543 * ->contentTypeDef (put there during parsing).
16544 */
16545 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016546 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016547 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548 * 2.2 If clause 2.1.2 above is satisfied, then there
16549 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016550 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016551 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016552 /* TODO: Change error code to ..._SRC_CT_2_2. */
16553 xmlSchemaPCustomErr(ctxt,
16554 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016555 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 "A <simpleType> is expected among the children "
16557 "of <restriction>, if <simpleContent> is used and "
16558 "the base type '%s' is a complex type",
16559 xmlSchemaFormatQName(&str, base->targetNamespace,
16560 base->name));
16561 FREE_AND_NULL(str)
16562 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016563 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016564 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016565 ret = XML_SCHEMAP_SRC_CT_1;
16566 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016567 }
16568 if (ret > 0) {
16569 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016570 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016571 xmlSchemaPCustomErr(ctxt,
16572 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016573 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016574 "If <simpleContent> and <restriction> is used, the "
16575 "base type must be a simple type or a complex type with "
16576 "mixed content and particle emptiable. The base type "
16577 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016578 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016579 base->name));
16580 } else {
16581 xmlSchemaPCustomErr(ctxt,
16582 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016583 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016584 "If <simpleContent> and <extension> is used, the "
16585 "base type must be a simple type. The base type '%s' "
16586 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016587 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016588 base->name));
16589 }
16590 FREE_AND_NULL(str)
16591 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016592 }
16593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016594 * SPEC (3) "The corresponding complex type definition component must
16595 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016596 * Definition Schema Components (§3.4.6);"
16597 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016598 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016599 /*
16600 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016601 * above for {attribute wildcard} is satisfied, the intensional
16602 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016603 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016604 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016605 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016606 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016607}
William M. Brack2f2a6632004-08-20 23:09:47 +000016608
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016609#ifdef ENABLE_PARTICLE_RESTRICTION
16610/**
16611 * xmlSchemaCheckParticleRangeOK:
16612 * @ctxt: the schema parser context
16613 * @type: the complex type definition
16614 *
16615 * (3.9.6) Constraints on Particle Schema Components
16616 * Schema Component Constraint:
16617 * Occurrence Range OK (range-ok)
16618 *
16619 * STATUS: complete
16620 *
16621 * Returns 0 if the constraints are satisfied, a positive
16622 * error code if not and -1 if an internal error occured.
16623 */
16624static int
16625xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16626 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016627{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016628 if (rmin < bmin)
16629 return (1);
16630 if ((bmax != UNBOUNDED) &&
16631 (rmax > bmax))
16632 return (1);
16633 return (0);
16634}
16635
16636/**
16637 * xmlSchemaCheckRCaseNameAndTypeOK:
16638 * @ctxt: the schema parser context
16639 * @r: the restricting element declaration particle
16640 * @b: the base element declaration particle
16641 *
16642 * (3.9.6) Constraints on Particle Schema Components
16643 * Schema Component Constraint:
16644 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16645 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016646 *
16647 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016648 * MISSING (3.2.3)
16649 * CLARIFY: (3.2.2)
16650 *
16651 * Returns 0 if the constraints are satisfied, a positive
16652 * error code if not and -1 if an internal error occured.
16653 */
16654static int
16655xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16656 xmlSchemaParticlePtr r,
16657 xmlSchemaParticlePtr b)
16658{
16659 xmlSchemaElementPtr elemR, elemB;
16660
16661 /* TODO: Error codes (rcase-NameAndTypeOK). */
16662 elemR = (xmlSchemaElementPtr) r->children;
16663 elemB = (xmlSchemaElementPtr) b->children;
16664 /*
16665 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16666 * the same."
16667 */
16668 if ((elemR != elemB) &&
16669 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16670 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16671 return (1);
16672 /*
16673 * SPEC (2) "R's occurrence range is a valid restriction of B's
16674 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16675 */
16676 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16677 b->minOccurs, b->maxOccurs) != 0)
16678 return (1);
16679 /*
16680 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16681 * {scope} are global."
16682 */
16683 if (elemR == elemB)
16684 return (0);
16685 /*
16686 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16687 */
16688 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16689 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16690 return (1);
16691 /*
16692 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16693 * or is not fixed, or R's declaration's {value constraint} is fixed
16694 * with the same value."
16695 */
16696 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16697 ((elemR->value == NULL) ||
16698 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16699 /* TODO: Equality of the initial value or normalized or canonical? */
16700 (! xmlStrEqual(elemR->value, elemB->value))))
16701 return (1);
16702 /*
16703 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16704 * definitions} is a subset of B's declaration's {identity-constraint
16705 * definitions}, if any."
16706 */
16707 if (elemB->idcs != NULL) {
16708 /* TODO */
16709 }
16710 /*
16711 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16712 * superset of B's declaration's {disallowed substitutions}."
16713 */
16714 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16715 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16716 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16717 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16718 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16719 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16720 return (1);
16721 /*
16722 * SPEC (3.2.5) "R's {type definition} is validly derived given
16723 * {extension, list, union} from B's {type definition}"
16724 *
16725 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16726 * set, if the corresponding constraints handle "restriction" and
16727 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016728 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016729 */
16730 {
16731 int set = 0;
16732
16733 set |= SUBSET_EXTENSION;
16734 set |= SUBSET_LIST;
16735 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016736 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016737 elemB->subtypes, set) != 0)
16738 return (1);
16739 }
16740 return (0);
16741}
16742
16743/**
16744 * xmlSchemaCheckRCaseNSCompat:
16745 * @ctxt: the schema parser context
16746 * @r: the restricting element declaration particle
16747 * @b: the base wildcard particle
16748 *
16749 * (3.9.6) Constraints on Particle Schema Components
16750 * Schema Component Constraint:
16751 * Particle Derivation OK (Elt:Any -- NSCompat)
16752 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016753 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016754 * STATUS: complete
16755 *
16756 * Returns 0 if the constraints are satisfied, a positive
16757 * error code if not and -1 if an internal error occured.
16758 */
16759static int
16760xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16761 xmlSchemaParticlePtr r,
16762 xmlSchemaParticlePtr b)
16763{
16764 /* TODO:Error codes (rcase-NSCompat). */
16765 /*
16766 * SPEC "For an element declaration particle to be a ·valid restriction·
16767 * of a wildcard particle all of the following must be true:"
16768 *
16769 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16770 * with respect to the wildcard's {namespace constraint} as defined by
16771 * Wildcard allows Namespace Name (§3.10.4)."
16772 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016773 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016774 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16775 return (1);
16776 /*
16777 * SPEC (2) "R's occurrence range is a valid restriction of B's
16778 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16779 */
16780 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16781 b->minOccurs, b->maxOccurs) != 0)
16782 return (1);
16783
16784 return (0);
16785}
16786
16787/**
16788 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16789 * @ctxt: the schema parser context
16790 * @r: the restricting element declaration particle
16791 * @b: the base model group particle
16792 *
16793 * (3.9.6) Constraints on Particle Schema Components
16794 * Schema Component Constraint:
16795 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16796 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016797 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016798 * STATUS: TODO
16799 *
16800 * Returns 0 if the constraints are satisfied, a positive
16801 * error code if not and -1 if an internal error occured.
16802 */
16803static int
16804xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16805 xmlSchemaParticlePtr r,
16806 xmlSchemaParticlePtr b)
16807{
16808 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16809 TODO
16810 return (0);
16811}
16812
16813/**
16814 * xmlSchemaCheckRCaseNSSubset:
16815 * @ctxt: the schema parser context
16816 * @r: the restricting wildcard particle
16817 * @b: the base wildcard particle
16818 *
16819 * (3.9.6) Constraints on Particle Schema Components
16820 * Schema Component Constraint:
16821 * Particle Derivation OK (Any:Any -- NSSubset)
16822 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016823 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016824 * STATUS: complete
16825 *
16826 * Returns 0 if the constraints are satisfied, a positive
16827 * error code if not and -1 if an internal error occured.
16828 */
16829static int
16830xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16831 xmlSchemaParticlePtr r,
16832 xmlSchemaParticlePtr b,
16833 int isAnyTypeBase)
16834{
16835 /* TODO: Error codes (rcase-NSSubset). */
16836 /*
16837 * SPEC (1) "R's occurrence range is a valid restriction of B's
16838 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16839 */
16840 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16841 b->minOccurs, b->maxOccurs))
16842 return (1);
16843 /*
16844 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16845 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16846 */
16847 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16848 (xmlSchemaWildcardPtr) b->children))
16849 return (1);
16850 /*
16851 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16852 * definition·, R's {process contents} must be identical to or stronger
16853 * than B's {process contents}, where strict is stronger than lax is
16854 * stronger than skip."
16855 */
16856 if (! isAnyTypeBase) {
16857 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16858 ((xmlSchemaWildcardPtr) b->children)->processContents)
16859 return (1);
16860 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016861
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016862 return (0);
16863}
16864
16865/**
16866 * xmlSchemaCheckCOSParticleRestrict:
16867 * @ctxt: the schema parser context
16868 * @type: the complex type definition
16869 *
16870 * (3.9.6) Constraints on Particle Schema Components
16871 * Schema Component Constraint:
16872 * Particle Valid (Restriction) (cos-particle-restrict)
16873 *
16874 * STATUS: TODO
16875 *
16876 * Returns 0 if the constraints are satisfied, a positive
16877 * error code if not and -1 if an internal error occured.
16878 */
16879static int
16880xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16881 xmlSchemaParticlePtr r,
16882 xmlSchemaParticlePtr b)
16883{
16884 int ret = 0;
16885
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016886 /*part = WXS_TYPE_PARTICLE(type);
16887 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016888 */
16889
16890 TODO
16891
16892 /*
16893 * SPEC (1) "They are the same particle."
16894 */
16895 if (r == b)
16896 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016897
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016898
16899 return (0);
16900}
16901
16902/**
16903 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16904 * @ctxt: the schema parser context
16905 * @r: the model group particle
16906 * @b: the base wildcard particle
16907 *
16908 * (3.9.6) Constraints on Particle Schema Components
16909 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016910 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016911 * NSRecurseCheckCardinality)
16912 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016913 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016914 * STATUS: TODO: subst-groups
16915 *
16916 * Returns 0 if the constraints are satisfied, a positive
16917 * error code if not and -1 if an internal error occured.
16918 */
16919static int
16920xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16921 xmlSchemaParticlePtr r,
16922 xmlSchemaParticlePtr b)
16923{
16924 xmlSchemaParticlePtr part;
16925 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16926 if ((r->children == NULL) || (r->children->children == NULL))
16927 return (-1);
16928 /*
16929 * SPEC "For a group particle to be a ·valid restriction· of a
16930 * wildcard particle..."
16931 *
16932 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016933 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016934 * Particle Valid (Restriction) (§3.9.6)."
16935 */
16936 part = (xmlSchemaParticlePtr) r->children->children;
16937 do {
16938 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16939 return (1);
16940 part = (xmlSchemaParticlePtr) part->next;
16941 } while (part != NULL);
16942 /*
16943 * SPEC (2) "The effective total range of the group [...] is a
16944 * valid restriction of B's occurrence range as defined by
16945 * Occurrence Range OK (§3.9.6)."
16946 */
16947 if (xmlSchemaCheckParticleRangeOK(
16948 xmlSchemaGetParticleTotalRangeMin(r),
16949 xmlSchemaGetParticleTotalRangeMax(r),
16950 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016951 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016952 return (0);
16953}
16954
16955/**
16956 * xmlSchemaCheckRCaseRecurse:
16957 * @ctxt: the schema parser context
16958 * @r: the <all> or <sequence> model group particle
16959 * @b: the base <all> or <sequence> model group particle
16960 *
16961 * (3.9.6) Constraints on Particle Schema Components
16962 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016963 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016964 Recurse)
16965 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016966 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016967 * STATUS: ?
16968 * TODO: subst-groups
16969 *
16970 * Returns 0 if the constraints are satisfied, a positive
16971 * error code if not and -1 if an internal error occured.
16972 */
16973static int
16974xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16975 xmlSchemaParticlePtr r,
16976 xmlSchemaParticlePtr b)
16977{
16978 /* xmlSchemaParticlePtr part; */
16979 /* TODO: Error codes (rcase-Recurse). */
16980 if ((r->children == NULL) || (b->children == NULL) ||
16981 (r->children->type != b->children->type))
16982 return (-1);
16983 /*
16984 * SPEC "For an all or sequence group particle to be a ·valid
16985 * restriction· of another group particle with the same {compositor}..."
16986 *
16987 * SPEC (1) "R's occurrence range is a valid restriction of B's
16988 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16989 */
16990 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16991 b->minOccurs, b->maxOccurs))
16992 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016993
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016994
16995 return (0);
16996}
16997
16998#endif
16999
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017000#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17001 xmlSchemaPCustomErrExt(pctxt, \
17002 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017003 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017004 "It is an error for both '%s' and '%s' to be specified on the "\
17005 "same type definition", \
17006 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17007 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17008
17009#define FACET_RESTR_ERR(fac1, msg) \
17010 xmlSchemaPCustomErr(pctxt, \
17011 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017012 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017013 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017014
17015#define FACET_RESTR_FIXED_ERR(fac) \
17016 xmlSchemaPCustomErr(pctxt, \
17017 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017018 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017019 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017020 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017021
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017022static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017023xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17024 xmlSchemaFacetPtr facet1,
17025 xmlSchemaFacetPtr facet2,
17026 int lessGreater,
17027 int orEqual,
17028 int ofBase)
17029{
17030 xmlChar *msg = NULL;
17031
17032 msg = xmlStrdup(BAD_CAST "'");
17033 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17034 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17035 if (lessGreater == 0)
17036 msg = xmlStrcat(msg, BAD_CAST " equal to");
17037 if (lessGreater == 1)
17038 msg = xmlStrcat(msg, BAD_CAST " greater than");
17039 else
17040 msg = xmlStrcat(msg, BAD_CAST " less than");
17041
17042 if (orEqual)
17043 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17044 msg = xmlStrcat(msg, BAD_CAST " '");
17045 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17046 if (ofBase)
17047 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17048 else
17049 msg = xmlStrcat(msg, BAD_CAST "'");
17050
17051 xmlSchemaPCustomErr(pctxt,
17052 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017053 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017054 (const char *) msg, NULL);
17055
17056 if (msg != NULL)
17057 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017058}
17059
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017060/*
17061* xmlSchemaDeriveAndValidateFacets:
17062*
17063* Schema Component Constraint: Simple Type Restriction (Facets)
17064* (st-restrict-facets)
17065*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017066static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017067xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17068 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017069{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017070 xmlSchemaTypePtr base = type->baseType;
17071 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017072 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017073 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17074 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17075 fmininc = NULL, fmaxinc = NULL,
17076 fminexc = NULL, fmaxexc = NULL,
17077 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17078 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17079 bfmininc = NULL, bfmaxinc = NULL,
17080 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017081 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017082
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017083 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017084 * SPEC st-restrict-facets 1:
17085 * "The {variety} of R is the same as that of B."
17086 */
17087 /*
17088 * SPEC st-restrict-facets 2:
17089 * "If {variety} is atomic, the {primitive type definition}
17090 * of R is the same as that of B."
17091 *
17092 * NOTE: we leave 1 & 2 out for now, since this will be
17093 * satisfied by the derivation process.
17094 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17095 */
17096 /*
17097 * SPEC st-restrict-facets 3:
17098 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017099 * of B, eliminating duplicates. To eliminate duplicates,
17100 * when a facet of the same kind occurs in both S and the
17101 * {facets} of B, the one in the {facets} of B is not
17102 * included, with the exception of enumeration and pattern
17103 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017104 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017106
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017107 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17108 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017110 last = type->facetSet;
17111 if (last != NULL)
17112 while (last->next != NULL)
17113 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017114
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017115 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17116 facet = cur->facet;
17117 switch (facet->type) {
17118 case XML_SCHEMA_FACET_LENGTH:
17119 flength = facet; break;
17120 case XML_SCHEMA_FACET_MINLENGTH:
17121 fminlen = facet; break;
17122 case XML_SCHEMA_FACET_MININCLUSIVE:
17123 fmininc = facet; break;
17124 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17125 fminexc = facet; break;
17126 case XML_SCHEMA_FACET_MAXLENGTH:
17127 fmaxlen = facet; break;
17128 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17129 fmaxinc = facet; break;
17130 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17131 fmaxexc = facet; break;
17132 case XML_SCHEMA_FACET_TOTALDIGITS:
17133 ftotdig = facet; break;
17134 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17135 ffracdig = facet; break;
17136 default:
17137 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017138 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017139 }
17140 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17141 facet = cur->facet;
17142 switch (facet->type) {
17143 case XML_SCHEMA_FACET_LENGTH:
17144 bflength = facet; break;
17145 case XML_SCHEMA_FACET_MINLENGTH:
17146 bfminlen = facet; break;
17147 case XML_SCHEMA_FACET_MININCLUSIVE:
17148 bfmininc = facet; break;
17149 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17150 bfminexc = facet; break;
17151 case XML_SCHEMA_FACET_MAXLENGTH:
17152 bfmaxlen = facet; break;
17153 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17154 bfmaxinc = facet; break;
17155 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17156 bfmaxexc = facet; break;
17157 case XML_SCHEMA_FACET_TOTALDIGITS:
17158 bftotdig = facet; break;
17159 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17160 bffracdig = facet; break;
17161 default:
17162 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017164 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017165 /*
17166 * length and minLength or maxLength (2.2) + (3.2)
17167 */
17168 if (flength && (fminlen || fmaxlen)) {
17169 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17170 "either of 'minLength' or 'maxLength' to be specified on "
17171 "the same type definition")
17172 }
17173 /*
17174 * Mutual exclusions in the same derivation step.
17175 */
17176 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017177 /*
17178 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017179 */
17180 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17181 }
17182 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017183 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017184 * SCC "minInclusive and minExclusive"
17185 */
17186 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017188
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017189 if (flength && bflength) {
17190 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017191 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017192 * The values have to be equal.
17193 */
17194 res = xmlSchemaCompareValues(flength->val, bflength->val);
17195 if (res == -2)
17196 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017197 if (res != 0)
17198 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17199 if ((res != 0) && (bflength->fixed)) {
17200 FACET_RESTR_FIXED_ERR(flength)
17201 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017202
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017203 }
17204 if (fminlen && bfminlen) {
17205 /*
17206 * SCC "minLength valid restriction"
17207 * minLength >= BASE minLength
17208 */
17209 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17210 if (res == -2)
17211 goto internal_error;
17212 if (res == -1)
17213 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17214 if ((res != 0) && (bfminlen->fixed)) {
17215 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017216 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017217 }
17218 if (fmaxlen && bfmaxlen) {
17219 /*
17220 * SCC "maxLength valid restriction"
17221 * maxLength <= BASE minLength
17222 */
17223 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17224 if (res == -2)
17225 goto internal_error;
17226 if (res == 1)
17227 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17228 if ((res != 0) && (bfmaxlen->fixed)) {
17229 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017230 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017231 }
17232 /*
17233 * SCC "length and minLength or maxLength"
17234 */
17235 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017236 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017237 if (flength) {
17238 if (! fminlen)
17239 flength = bflength;
17240 if (fminlen) {
17241 /* (1.1) length >= minLength */
17242 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17243 if (res == -2)
17244 goto internal_error;
17245 if (res == -1)
17246 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17247 }
17248 if (! fmaxlen)
17249 fmaxlen = bfmaxlen;
17250 if (fmaxlen) {
17251 /* (2.1) length <= maxLength */
17252 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17253 if (res == -2)
17254 goto internal_error;
17255 if (res == 1)
17256 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17257 }
17258 }
17259 if (fmaxinc) {
17260 /*
17261 * "maxInclusive"
17262 */
17263 if (fmininc) {
17264 /* SCC "maxInclusive >= minInclusive" */
17265 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17266 if (res == -2)
17267 goto internal_error;
17268 if (res == -1) {
17269 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17270 }
17271 }
17272 /*
17273 * SCC "maxInclusive valid restriction"
17274 */
17275 if (bfmaxinc) {
17276 /* maxInclusive <= BASE maxInclusive */
17277 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17278 if (res == -2)
17279 goto internal_error;
17280 if (res == 1)
17281 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17282 if ((res != 0) && (bfmaxinc->fixed)) {
17283 FACET_RESTR_FIXED_ERR(fmaxinc)
17284 }
17285 }
17286 if (bfmaxexc) {
17287 /* maxInclusive < BASE maxExclusive */
17288 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17289 if (res == -2)
17290 goto internal_error;
17291 if (res != -1) {
17292 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17293 }
17294 }
17295 if (bfmininc) {
17296 /* maxInclusive >= BASE minInclusive */
17297 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17298 if (res == -2)
17299 goto internal_error;
17300 if (res == -1) {
17301 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17302 }
17303 }
17304 if (bfminexc) {
17305 /* maxInclusive > BASE minExclusive */
17306 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17307 if (res == -2)
17308 goto internal_error;
17309 if (res != 1) {
17310 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17311 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017312 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017313 }
17314 if (fmaxexc) {
17315 /*
17316 * "maxExclusive >= minExclusive"
17317 */
17318 if (fminexc) {
17319 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17320 if (res == -2)
17321 goto internal_error;
17322 if (res == -1) {
17323 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17324 }
17325 }
17326 /*
17327 * "maxExclusive valid restriction"
17328 */
17329 if (bfmaxexc) {
17330 /* maxExclusive <= BASE maxExclusive */
17331 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17332 if (res == -2)
17333 goto internal_error;
17334 if (res == 1) {
17335 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17336 }
17337 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017338 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017339 }
17340 }
17341 if (bfmaxinc) {
17342 /* maxExclusive <= BASE maxInclusive */
17343 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17344 if (res == -2)
17345 goto internal_error;
17346 if (res == 1) {
17347 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17348 }
17349 }
17350 if (bfmininc) {
17351 /* maxExclusive > BASE minInclusive */
17352 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17353 if (res == -2)
17354 goto internal_error;
17355 if (res != 1) {
17356 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17357 }
17358 }
17359 if (bfminexc) {
17360 /* maxExclusive > BASE minExclusive */
17361 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17362 if (res == -2)
17363 goto internal_error;
17364 if (res != 1) {
17365 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17366 }
17367 }
17368 }
17369 if (fminexc) {
17370 /*
17371 * "minExclusive < maxInclusive"
17372 */
17373 if (fmaxinc) {
17374 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17375 if (res == -2)
17376 goto internal_error;
17377 if (res != -1) {
17378 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17379 }
17380 }
17381 /*
17382 * "minExclusive valid restriction"
17383 */
17384 if (bfminexc) {
17385 /* minExclusive >= BASE minExclusive */
17386 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17387 if (res == -2)
17388 goto internal_error;
17389 if (res == -1) {
17390 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17391 }
17392 if ((res != 0) && (bfminexc->fixed)) {
17393 FACET_RESTR_FIXED_ERR(fminexc)
17394 }
17395 }
17396 if (bfmaxinc) {
17397 /* minExclusive <= BASE maxInclusive */
17398 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17399 if (res == -2)
17400 goto internal_error;
17401 if (res == 1) {
17402 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17403 }
17404 }
17405 if (bfmininc) {
17406 /* minExclusive >= BASE minInclusive */
17407 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17408 if (res == -2)
17409 goto internal_error;
17410 if (res == -1) {
17411 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17412 }
17413 }
17414 if (bfmaxexc) {
17415 /* minExclusive < BASE maxExclusive */
17416 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17417 if (res == -2)
17418 goto internal_error;
17419 if (res != -1) {
17420 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17421 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017422 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017423 }
17424 if (fmininc) {
17425 /*
17426 * "minInclusive < maxExclusive"
17427 */
17428 if (fmaxexc) {
17429 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17430 if (res == -2)
17431 goto internal_error;
17432 if (res != -1) {
17433 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17434 }
17435 }
17436 /*
17437 * "minExclusive valid restriction"
17438 */
17439 if (bfmininc) {
17440 /* minInclusive >= BASE minInclusive */
17441 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17442 if (res == -2)
17443 goto internal_error;
17444 if (res == -1) {
17445 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17446 }
17447 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017448 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017449 }
17450 }
17451 if (bfmaxinc) {
17452 /* minInclusive <= BASE maxInclusive */
17453 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17454 if (res == -2)
17455 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017456 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017457 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17458 }
17459 }
17460 if (bfminexc) {
17461 /* minInclusive > BASE minExclusive */
17462 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17463 if (res == -2)
17464 goto internal_error;
17465 if (res != 1)
17466 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17467 }
17468 if (bfmaxexc) {
17469 /* minInclusive < BASE maxExclusive */
17470 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17471 if (res == -2)
17472 goto internal_error;
17473 if (res != -1)
17474 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17475 }
17476 }
17477 if (ftotdig && bftotdig) {
17478 /*
17479 * SCC " totalDigits valid restriction"
17480 * totalDigits <= BASE totalDigits
17481 */
17482 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17483 if (res == -2)
17484 goto internal_error;
17485 if (res == 1)
17486 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17487 -1, 1, 1);
17488 if ((res != 0) && (bftotdig->fixed)) {
17489 FACET_RESTR_FIXED_ERR(ftotdig)
17490 }
17491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017492 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017493 /*
17494 * SCC "fractionDigits valid restriction"
17495 * fractionDigits <= BASE fractionDigits
17496 */
17497 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17498 if (res == -2)
17499 goto internal_error;
17500 if (res == 1)
17501 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17502 -1, 1, 1);
17503 if ((res != 0) && (bffracdig->fixed)) {
17504 FACET_RESTR_FIXED_ERR(ffracdig)
17505 }
17506 }
17507 /*
17508 * SCC "fractionDigits less than or equal to totalDigits"
17509 */
17510 if (! ftotdig)
17511 ftotdig = bftotdig;
17512 if (! ffracdig)
17513 ffracdig = bffracdig;
17514 if (ftotdig && ffracdig) {
17515 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17516 if (res == -2)
17517 goto internal_error;
17518 if (res == 1)
17519 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17520 -1, 1, 0);
17521 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017522 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017523 * *Enumerations* won' be added here, since only the first set
17524 * of enumerations in the ancestor-or-self axis is used
17525 * for validation, plus we need to use the base type of those
17526 * enumerations for whitespace.
17527 *
17528 * *Patterns*: won't be add here, since they are ORed at
17529 * type level and ANDed at ancestor level. This will
17530 * happed during validation by walking the base axis
17531 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017532 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017533 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17534 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017535 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017536 * Special handling of enumerations and patterns.
17537 * TODO: hmm, they should not appear in the set, so remove this.
17538 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017539 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017540 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017541 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017542 /*
17543 * Search for a duplicate facet in the current type.
17544 */
17545 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017546 /* err = 0; */
17547 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017548 while (link != NULL) {
17549 facet = link->facet;
17550 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017551 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017552 case XML_SCHEMA_FACET_WHITESPACE:
17553 /*
17554 * The whitespace must be stronger.
17555 */
17556 if (facet->whitespace < bfacet->whitespace) {
17557 FACET_RESTR_ERR(flength,
17558 "The 'whitespace' value has to be equal to "
17559 "or stronger than the 'whitespace' value of "
17560 "the base type")
17561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017563 (facet->whitespace != bfacet->whitespace)) {
17564 FACET_RESTR_FIXED_ERR(facet)
17565 }
17566 break;
17567 default:
17568 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017569 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017570 /* Duplicate found. */
17571 break;
17572 }
17573 link = link->next;
17574 }
17575 /*
17576 * If no duplicate was found: add the base types's facet
17577 * to the set.
17578 */
17579 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017580 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017581 xmlMalloc(sizeof(xmlSchemaFacetLink));
17582 if (link == NULL) {
17583 xmlSchemaPErrMemory(pctxt,
17584 "deriving facets, creating a facet link", NULL);
17585 return (-1);
17586 }
17587 link->facet = cur->facet;
17588 link->next = NULL;
17589 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 type->facetSet = link;
17591 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017592 last->next = link;
17593 last = link;
17594 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017595
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017596 }
17597
17598 return (0);
17599internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017600 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17601 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017602 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017603}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017604
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017605static int
17606xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17607 xmlSchemaTypePtr type)
17608{
17609 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17610 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017611 * The actual value is then formed by replacing any union type
17612 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017613 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017614 *
17615 * TODO: There's a bug entry at
17616 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17617 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017618 */
17619 link = type->memberTypes;
17620 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017621
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017622 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017623 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017624
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017625 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017626 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017627 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017628 link->type = subLink->type;
17629 if (subLink->next != NULL) {
17630 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017632 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017633 while (subLink != NULL) {
17634 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017635 xmlMalloc(sizeof(xmlSchemaTypeLink));
17636 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017638 NULL);
17639 return (-1);
17640 }
17641 newLink->type = subLink->type;
17642 prevLink->next = newLink;
17643 prevLink = newLink;
17644 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017646 subLink = subLink->next;
17647 }
17648 }
17649 }
17650 }
17651 link = link->next;
17652 }
17653 return (0);
17654}
17655
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017656static void
17657xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17658{
17659 int has = 0, needVal = 0, normVal = 0;
17660
17661 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17662 if (has) {
17663 needVal = (type->baseType->flags &
17664 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17665 normVal = (type->baseType->flags &
17666 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17667 }
17668 if (type->facets != NULL) {
17669 xmlSchemaFacetPtr fac;
17670
17671 for (fac = type->facets; fac != NULL; fac = fac->next) {
17672 switch (fac->type) {
17673 case XML_SCHEMA_FACET_WHITESPACE:
17674 break;
17675 case XML_SCHEMA_FACET_PATTERN:
17676 normVal = 1;
17677 has = 1;
17678 break;
17679 case XML_SCHEMA_FACET_ENUMERATION:
17680 needVal = 1;
17681 normVal = 1;
17682 has = 1;
17683 break;
17684 default:
17685 has = 1;
17686 break;
17687 }
17688 }
17689 }
17690 if (normVal)
17691 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17692 if (needVal)
17693 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17694 if (has)
17695 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17696
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017697 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017698 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17699 /*
17700 * OPTIMIZE VAL TODO: Some facets need a computed value.
17701 */
17702 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17703 (prim->builtInType != XML_SCHEMAS_STRING)) {
17704 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17705 }
17706 }
17707}
17708
17709static int
17710xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17711{
17712
17713
17714 /*
17715 * Evaluate the whitespace-facet value.
17716 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017717 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017718 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17719 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017720 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017721 return (0);
17722
17723 if (type->facetSet != NULL) {
17724 xmlSchemaFacetLinkPtr lin;
17725
17726 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17727 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17728 switch (lin->facet->whitespace) {
17729 case XML_SCHEMAS_FACET_PRESERVE:
17730 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17731 break;
17732 case XML_SCHEMAS_FACET_REPLACE:
17733 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17734 break;
17735 case XML_SCHEMAS_FACET_COLLAPSE:
17736 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17737 break;
17738 default:
17739 return (-1);
17740 }
17741 return (0);
17742 }
17743 }
17744 }
17745 /*
17746 * For all ·atomic· datatypes other than string (and types ·derived·
17747 * by ·restriction· from it) the value of whiteSpace is fixed to
17748 * collapse
17749 */
17750 {
17751 xmlSchemaTypePtr anc;
17752
17753 for (anc = type->baseType; anc != NULL &&
17754 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17755 anc = anc->baseType) {
17756
17757 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17758 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17759 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17760
17761 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17762 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17763 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17764
17765 } else
17766 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17767 break;
17768 }
17769 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017770 }
17771 return (0);
17772}
17773
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017774static int
17775xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17776 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017777{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017778 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17779 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017780 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017781 return(0);
17782 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017783
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017784 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017785 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017786 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017787 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017788 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017789 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017790 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017791 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017792 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017793 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017794 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017795 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017796 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017797 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017798 * Corresponds to <simpleType><union>...
17799 */
17800 if (type->memberTypes == NULL) {
17801 /*
17802 * This one is really needed, so get out.
17803 */
17804 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17805 "union type has no member-types assigned");
17806 return(-1);
17807 }
17808 } else {
17809 /*
17810 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017811 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017812 if (type->baseType == NULL) {
17813 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17814 "type has no base-type assigned");
17815 return(-1);
17816 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017817 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017818 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17819 return(-1);
17820 /*
17821 * Variety
17822 * If the <restriction> alternative is chosen, then the
17823 * {variety} of the {base type definition}.
17824 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017825 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017826 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017827 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017828 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017829 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017830 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017831 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017832 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017833 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017834 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017835 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017836 * NOTE that we won't assign the memberTypes of the base,
17837 * since this will make trouble when freeing them; we will
17838 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017839 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017840 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017841 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017842 return(0);
17843}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844
Daniel Veillard8651f532002-04-17 09:06:27 +000017845#ifdef DEBUG_TYPE
Daniel Veillardd0271472006-01-02 10:22:02 +000017846void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017847xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17848 xmlSchemaTypePtr type)
17849{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017850 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017851 xmlGenericError(xmlGenericErrorContext,
17852 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017853 type->node->doc->URL,
17854 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017855 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017856 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017857 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017858 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017859 switch (type->contentType) {
17860 case XML_SCHEMA_CONTENT_SIMPLE:
17861 xmlGenericError(xmlGenericErrorContext, "simple\n");
17862 break;
17863 case XML_SCHEMA_CONTENT_ELEMENTS:
17864 xmlGenericError(xmlGenericErrorContext, "elements\n");
17865 break;
17866 case XML_SCHEMA_CONTENT_UNKNOWN:
17867 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17868 break;
17869 case XML_SCHEMA_CONTENT_EMPTY:
17870 xmlGenericError(xmlGenericErrorContext, "empty\n");
17871 break;
17872 case XML_SCHEMA_CONTENT_MIXED:
17873 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017874 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017875 xmlGenericError(xmlGenericErrorContext,
17876 "mixed as emptiable particle\n");
17877 else
17878 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17879 break;
17880 /* Removed, since not used. */
17881 /*
17882 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17883 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17884 break;
17885 */
17886 case XML_SCHEMA_CONTENT_BASIC:
17887 xmlGenericError(xmlGenericErrorContext, "basic\n");
17888 break;
17889 default:
17890 xmlGenericError(xmlGenericErrorContext,
17891 "not registered !!!\n");
17892 break;
17893 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017894 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017895}
Daniel Veillard8651f532002-04-17 09:06:27 +000017896#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017897
17898/*
17899* 3.14.6 Constraints on Simple Type Definition Schema Components
17900*/
17901static int
17902xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17903 xmlSchemaTypePtr type)
17904{
17905 int res, olderrs = pctxt->nberrors;
17906
17907 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17908 return(-1);
17909
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017910 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017911 return(0);
17912
17913 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17914 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17915
17916 if (type->baseType == NULL) {
17917 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17918 "missing baseType");
17919 goto exit_failure;
17920 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017921 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017922 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017923 /*
17924 * If a member type of a union is a union itself, we need to substitute
17925 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017926 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17927 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017928 */
17929 if ((type->memberTypes != NULL) &&
17930 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17931 return(-1);
17932 /*
17933 * SPEC src-simple-type 1
17934 * "The corresponding simple type definition, if any, must satisfy
17935 * the conditions set out in Constraints on Simple Type Definition
17936 * Schema Components (§3.14.6)."
17937 */
17938 /*
17939 * Schema Component Constraint: Simple Type Definition Properties Correct
17940 * (st-props-correct)
17941 */
17942 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17943 HFAILURE HERROR
17944 /*
17945 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17946 * (cos-st-restricts)
17947 */
17948 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17949 HFAILURE HERROR
17950 /*
17951 * TODO: Removed the error report, since it got annoying to get an
17952 * extra error report, if anything failed until now.
17953 * Enable this if needed.
17954 *
17955 * xmlSchemaPErr(ctxt, type->node,
17956 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17957 * "Simple type '%s' does not satisfy the constraints "
17958 * "on simple type definitions.\n",
17959 * type->name, NULL);
17960 */
17961 /*
17962 * Schema Component Constraint: Simple Type Restriction (Facets)
17963 * (st-restrict-facets)
17964 */
17965 res = xmlSchemaCheckFacetValues(type, pctxt);
17966 HFAILURE HERROR
17967 if ((type->facetSet != NULL) ||
17968 (type->baseType->facetSet != NULL)) {
17969 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17970 HFAILURE HERROR
17971 }
17972 /*
17973 * Whitespace value.
17974 */
17975 res = xmlSchemaTypeFixupWhitespace(type);
17976 HFAILURE HERROR
17977 xmlSchemaTypeFixupOptimFacets(type);
17978
17979exit_error:
17980#ifdef DEBUG_TYPE
17981 xmlSchemaDebugFixedType(pctxt, type);
17982#endif
17983 if (olderrs != pctxt->nberrors)
17984 return(pctxt->err);
17985 return(0);
17986
17987exit_failure:
17988#ifdef DEBUG_TYPE
17989 xmlSchemaDebugFixedType(pctxt, type);
17990#endif
17991 return(-1);
17992}
17993
17994static int
17995xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17996 xmlSchemaTypePtr type)
17997{
17998 int res = 0, olderrs = pctxt->nberrors;
17999 xmlSchemaTypePtr baseType = type->baseType;
18000
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018001 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018002 return(0);
18003 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18004 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018005 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018006 "missing baseType");
18007 goto exit_failure;
18008 }
18009 /*
18010 * Fixup the base type.
18011 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018012 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018013 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018014 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18015 /*
18016 * Skip fixup if the base type is invalid.
18017 * TODO: Generate a warning!
18018 */
18019 return(0);
18020 }
18021 /*
18022 * This basically checks if the base type can be derived.
18023 */
18024 res = xmlSchemaCheckSRCCT(pctxt, type);
18025 HFAILURE HERROR
18026 /*
18027 * Fixup the content type.
18028 */
18029 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18030 /*
18031 * Corresponds to <complexType><simpleContent>...
18032 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018033 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018034 (baseType->contentTypeDef != NULL) &&
18035 (WXS_IS_RESTRICTION(type))) {
18036 xmlSchemaTypePtr contentBase, content;
18037#ifdef ENABLE_NAMED_LOCALS
18038 char buf[30];
18039 const xmlChar *tmpname;
18040#endif
18041 /*
18042 * SPEC (1) If <restriction> + base type is <complexType>,
18043 * "whose own {content type} is a simple type..."
18044 */
18045 if (type->contentTypeDef != NULL) {
18046 /*
18047 * SPEC (1.1) "the simple type definition corresponding to the
18048 * <simpleType> among the [children] of <restriction> if there
18049 * is one;"
18050 * Note that this "<simpleType> among the [children]" was put
18051 * into ->contentTypeDef during parsing.
18052 */
18053 contentBase = type->contentTypeDef;
18054 type->contentTypeDef = NULL;
18055 } else {
18056 /*
18057 * (1.2) "...otherwise (<restriction> has no <simpleType>
18058 * among its [children]), the simple type definition which
18059 * is the {content type} of the ... base type."
18060 */
18061 contentBase = baseType->contentTypeDef;
18062 }
18063 /*
18064 * SPEC
18065 * "... a simple type definition which restricts the simple
18066 * type definition identified in clause 1.1 or clause 1.2
18067 * with a set of facet components"
18068 *
18069 * Create the anonymous simple type, which will be the content
18070 * type of the complex type.
18071 */
18072#ifdef ENABLE_NAMED_LOCALS
18073 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18074 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018075 content = xmlSchemaAddType(pctxt, pctxt->schema,
18076 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018077 type->node, 0);
18078#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018079 content = xmlSchemaAddType(pctxt, pctxt->schema,
18080 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018081 type->node, 0);
18082#endif
18083 if (content == NULL)
18084 goto exit_failure;
18085 /*
18086 * We will use the same node as for the <complexType>
18087 * to have it somehow anchored in the schema doc.
18088 */
18089 content->type = XML_SCHEMA_TYPE_SIMPLE;
18090 content->baseType = contentBase;
18091 /*
18092 * Move the facets, previously anchored on the
18093 * complexType during parsing.
18094 */
18095 content->facets = type->facets;
18096 type->facets = NULL;
18097 content->facetSet = type->facetSet;
18098 type->facetSet = NULL;
18099
18100 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018101 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018102 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018103 /*
18104 * Fixup the newly created type. We don't need to check
18105 * for circularity here.
18106 */
18107 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18108 HFAILURE HERROR
18109 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18110 HFAILURE HERROR
18111
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018112 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018113 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18114 (WXS_IS_RESTRICTION(type))) {
18115 /*
18116 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18117 * an emptiable particle, then a simple type definition which
18118 * restricts the <restriction>'s <simpleType> child.
18119 */
18120 if ((type->contentTypeDef == NULL) ||
18121 (type->contentTypeDef->baseType == NULL)) {
18122 /*
18123 * TODO: Check if this ever happens.
18124 */
18125 xmlSchemaPCustomErr(pctxt,
18126 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018127 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018128 "Internal error: xmlSchemaTypeFixup, "
18129 "complex type '%s': the <simpleContent><restriction> "
18130 "is missing a <simpleType> child, but was not catched "
18131 "by xmlSchemaCheckSRCCT()", type->name);
18132 goto exit_failure;
18133 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018134 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018135 /*
18136 * SPEC (3) If <extension> + base is <complexType> with
18137 * <simpleType> content, "...then the {content type} of that
18138 * complex type definition"
18139 */
18140 if (baseType->contentTypeDef == NULL) {
18141 /*
18142 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18143 * should have catched this already.
18144 */
18145 xmlSchemaPCustomErr(pctxt,
18146 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018147 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018148 "Internal error: xmlSchemaTypeFixup, "
18149 "complex type '%s': the <extension>ed base type is "
18150 "a complex type with no simple content type",
18151 type->name);
18152 goto exit_failure;
18153 }
18154 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018155 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018156 /*
18157 * SPEC (4) <extension> + base is <simpleType>
18158 * "... then that simple type definition"
18159 */
18160 type->contentTypeDef = baseType;
18161 } else {
18162 /*
18163 * TODO: Check if this ever happens.
18164 */
18165 xmlSchemaPCustomErr(pctxt,
18166 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018167 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018168 "Internal error: xmlSchemaTypeFixup, "
18169 "complex type '%s' with <simpleContent>: unhandled "
18170 "derivation case", type->name);
18171 goto exit_failure;
18172 }
18173 } else {
18174 int dummySequence = 0;
18175 xmlSchemaParticlePtr particle =
18176 (xmlSchemaParticlePtr) type->subtypes;
18177 /*
18178 * Corresponds to <complexType><complexContent>...
18179 *
18180 * NOTE that the effective mixed was already set during parsing of
18181 * <complexType> and <complexContent>; its flag value is
18182 * XML_SCHEMAS_TYPE_MIXED.
18183 *
18184 * Compute the "effective content":
18185 * (2.1.1) + (2.1.2) + (2.1.3)
18186 */
18187 if ((particle == NULL) ||
18188 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18189 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18190 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18191 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18192 (particle->minOccurs == 0))) &&
18193 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18194 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18195 /*
18196 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18197 * a particle whose properties are as follows:..."
18198 *
18199 * Empty sequence model group with
18200 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18201 * NOTE that we sill assign it the <complexType> node to
18202 * somehow anchor it in the doc.
18203 */
18204 if ((particle == NULL) ||
18205 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18206 /*
18207 * Create the particle.
18208 */
18209 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18210 type->node, 1, 1);
18211 if (particle == NULL)
18212 goto exit_failure;
18213 /*
18214 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018215 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018216 particle->children = (xmlSchemaTreeItemPtr)
18217 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18218 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18219 if (particle->children == NULL)
18220 goto exit_failure;
18221
18222 type->subtypes = (xmlSchemaTypePtr) particle;
18223 }
18224 dummySequence = 1;
18225 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18226 } else {
18227 /*
18228 * SPEC (2.1.5) "otherwise empty"
18229 */
18230 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18231 }
18232 } else {
18233 /*
18234 * SPEC (2.2) "otherwise the particle corresponding to the
18235 * <all>, <choice>, <group> or <sequence> among the
18236 * [children]."
18237 */
18238 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18239 }
18240 /*
18241 * Compute the "content type".
18242 */
18243 if (WXS_IS_RESTRICTION(type)) {
18244 /*
18245 * SPEC (3.1) "If <restriction>..."
18246 * (3.1.1) + (3.1.2) */
18247 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18248 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18249 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18250 }
18251 } else {
18252 /*
18253 * SPEC (3.2) "If <extension>..."
18254 */
18255 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18256 /*
18257 * SPEC (3.2.1)
18258 */
18259 type->contentType = baseType->contentType;
18260 type->subtypes = baseType->subtypes;
18261 /*
18262 * NOTE that the effective mixed is ignored here.
18263 */
18264 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18265 /*
18266 * SPEC (3.2.2)
18267 */
18268 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18269 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18270 } else {
18271 /*
18272 * SPEC (3.2.3)
18273 */
18274 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18275 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18276 /*
18277 * "A model group whose {compositor} is sequence and whose
18278 * {particles} are..."
18279 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018280 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18281 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18282 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18283 XML_SCHEMA_TYPE_ALL))
18284 {
18285 /*
18286 * SPEC cos-all-limited (1)
18287 */
18288 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18289 /* TODO: error code */
18290 XML_SCHEMAP_COS_ALL_LIMITED,
18291 WXS_ITEM_NODE(type), NULL,
18292 "The type has an 'all' model group in its "
18293 "{content type} and thus cannot be derived from "
18294 "a non-empty type, since this would produce a "
18295 "'sequence' model group containing the 'all' "
18296 "model group; 'all' model groups are not "
18297 "allowed to appear inside other model groups",
18298 NULL, NULL);
18299
18300 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18301 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18302 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18303 XML_SCHEMA_TYPE_ALL))
18304 {
18305 /*
18306 * SPEC cos-all-limited (1)
18307 */
18308 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18309 /* TODO: error code */
18310 XML_SCHEMAP_COS_ALL_LIMITED,
18311 WXS_ITEM_NODE(type), NULL,
18312 "A type cannot be derived by extension from a type "
18313 "which has an 'all' model group in its "
18314 "{content type}, since this would produce a "
18315 "'sequence' model group containing the 'all' "
18316 "model group; 'all' model groups are not "
18317 "allowed to appear inside other model groups",
18318 NULL, NULL);
18319
18320 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018321 xmlSchemaTreeItemPtr effectiveContent =
18322 (xmlSchemaTreeItemPtr) type->subtypes;
18323 /*
18324 * Create the particle.
18325 */
18326 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18327 type->node, 1, 1);
18328 if (particle == NULL)
18329 goto exit_failure;
18330 /*
18331 * Create the "sequence" model group.
18332 */
18333 particle->children = (xmlSchemaTreeItemPtr)
18334 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18335 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18336 if (particle->children == NULL)
18337 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018338 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018339 /*
18340 * SPEC "the particle of the {content type} of
18341 * the ... base ..."
18342 * Create a duplicate of the base type's particle
18343 * and assign its "term" to it.
18344 */
18345 particle->children->children =
18346 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18347 pctxt->schema, type->node,
18348 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18349 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18350 if (particle->children->children == NULL)
18351 goto exit_failure;
18352 particle = (xmlSchemaParticlePtr)
18353 particle->children->children;
18354 particle->children =
18355 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18356 /*
18357 * SPEC "followed by the ·effective content·."
18358 */
18359 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018360 /*
18361 * This all will result in:
18362 * new-particle
18363 * --> new-sequence(
18364 * new-particle
18365 * --> base-model,
18366 * this-particle
18367 * --> this-model
18368 * )
18369 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018370 } else {
18371 /*
18372 * This is the case when there is already an empty
18373 * <sequence> with minOccurs==maxOccurs==1.
18374 * Just add the base types's content type.
18375 * NOTE that, although we miss to add an intermediate
18376 * <sequence>, this should produce no difference to
18377 * neither the regex compilation of the content model,
18378 * nor to the complex type contraints.
18379 */
18380 particle->children->children =
18381 (xmlSchemaTreeItemPtr) baseType->subtypes;
18382 }
18383 }
18384 }
18385 }
18386 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018387 * Now fixup attribute uses:
18388 * - expand attr. group references
18389 * - intersect attribute wildcards
18390 * - inherit attribute uses of the base type
18391 * - inherit or union attr. wildcards if extending
18392 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018393 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018394 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018395 HFAILURE HERROR
18396 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018397 * Apply the complex type component constraints; this will not
18398 * check attributes, since this is done in
18399 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018400 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018401 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018402 HFAILURE HERROR
18403
18404#ifdef DEBUG_TYPE
18405 xmlSchemaDebugFixedType(pctxt, type);
18406#endif
18407 if (olderrs != pctxt->nberrors)
18408 return(pctxt->err);
18409 else
18410 return(0);
18411
18412exit_error:
18413 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18414#ifdef DEBUG_TYPE
18415 xmlSchemaDebugFixedType(pctxt, type);
18416#endif
18417 return(pctxt->err);
18418
18419exit_failure:
18420 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18421#ifdef DEBUG_TYPE
18422 xmlSchemaDebugFixedType(pctxt, type);
18423#endif
18424 return(-1);
18425}
18426
18427
18428/**
18429 * xmlSchemaTypeFixup:
18430 * @typeDecl: the schema type definition
18431 * @ctxt: the schema parser context
18432 *
18433 * Fixes the content model of the type.
18434 * URGENT TODO: We need an int result!
18435 */
18436static int
18437xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018438 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018439{
18440 if (type == NULL)
18441 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018442 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18443 AERROR_INT("xmlSchemaTypeFixup",
18444 "this function needs a parser context");
18445 return(-1);
18446 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018447 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018448 return(0);
18449 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018450 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018451 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018452 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018453 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018454}
18455
18456/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018457 * xmlSchemaCheckFacet:
18458 * @facet: the facet
18459 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018460 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018461 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018462 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018463 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018464 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018465 * Returns 0 if valid, a positive error code if not valid and
18466 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018467 */
18468int
18469xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018470 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018471 xmlSchemaParserCtxtPtr pctxt,
18472 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018473{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018475
Daniel Veillardce682bc2004-11-05 17:22:25 +000018476 if ((facet == NULL) || (typeDecl == NULL))
18477 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018478 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018479 * TODO: will the parser context be given if used from
18480 * the relaxNG module?
18481 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018482 if (pctxt == NULL)
18483 ctxtGiven = 0;
18484 else
18485 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018486
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018487 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018488 case XML_SCHEMA_FACET_MININCLUSIVE:
18489 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18490 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018491 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18492 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018493 /*
18494 * Okay we need to validate the value
18495 * at that point.
18496 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018497 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018498
18499 /* 4.3.5.5 Constraints on enumeration Schema Components
18500 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018501 * It is an ·error· if any member of {value} is not in the
18502 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018503 *
18504 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018505 * The value ·must· be in the
18506 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018507 */
18508 /*
18509 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018510 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018511 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018512 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018513 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018514 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018516 */
18517 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18518 base = typeDecl->baseType;
18519 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520 PERROR_INT("xmlSchemaCheckFacet",
18521 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018522 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018523 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018524 } else
18525 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526
18527 if (! ctxtGiven) {
18528 /*
18529 * A context is needed if called from RelaxNG.
18530 */
18531 pctxt = xmlSchemaNewParserCtxt("*");
18532 if (pctxt == NULL)
18533 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018534 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018535 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018537 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018538 * facet->node is just the node holding the facet
18539 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018540 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018541 */
18542 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018543 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018544 facet->value, &(facet->val), 1, 1, 0);
18545 if (ret != 0) {
18546 if (ret < 0) {
18547 /* No error message for RelaxNG. */
18548 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018549 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018550 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18551 "Internal error: xmlSchemaCheckFacet, "
18552 "failed to validate the value '%s' of the "
18553 "facet '%s' against the base type",
18554 facet->value, xmlSchemaFacetTypeToString(facet->type));
18555 }
18556 goto internal_error;
18557 }
18558 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18559 /* No error message for RelaxNG. */
18560 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018561 xmlChar *str = NULL;
18562
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018563 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018564 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018565 "The value '%s' of the facet does not validate "
18566 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018567 facet->value,
18568 xmlSchemaFormatQName(&str,
18569 base->targetNamespace, base->name));
18570 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018572 goto exit;
18573 } else if (facet->val == NULL) {
18574 if (ctxtGiven) {
18575 PERROR_INT("xmlSchemaCheckFacet",
18576 "value was not computed");
18577 }
18578 TODO
18579 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018580 break;
18581 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018582 case XML_SCHEMA_FACET_PATTERN:
18583 facet->regexp = xmlRegexpCompile(facet->value);
18584 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018585 ret = XML_SCHEMAP_REGEXP_INVALID;
18586 /* No error message for RelaxNG. */
18587 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018588 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018589 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018590 "The value '%s' of the facet 'pattern' is not a "
18591 "valid regular expression",
18592 facet->value, NULL);
18593 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018594 }
18595 break;
18596 case XML_SCHEMA_FACET_TOTALDIGITS:
18597 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18598 case XML_SCHEMA_FACET_LENGTH:
18599 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018600 case XML_SCHEMA_FACET_MINLENGTH:
18601
18602 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18603 ret = xmlSchemaValidatePredefinedType(
18604 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18605 facet->value, &(facet->val));
18606 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018607 ret = xmlSchemaValidatePredefinedType(
18608 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18609 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018610 }
18611 if (ret != 0) {
18612 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018613 /* No error message for RelaxNG. */
18614 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018615 PERROR_INT("xmlSchemaCheckFacet",
18616 "validating facet value");
18617 }
18618 goto internal_error;
18619 }
18620 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18621 /* No error message for RelaxNG. */
18622 if (ctxtGiven) {
18623 /* error code */
18624 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18625 ret, facet->node, WXS_BASIC_CAST typeDecl,
18626 "The value '%s' of the facet '%s' is not a valid '%s'",
18627 facet->value,
18628 xmlSchemaFacetTypeToString(facet->type),
18629 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18630 BAD_CAST "nonNegativeInteger" :
18631 BAD_CAST "positiveInteger",
18632 NULL);
18633 }
18634 }
18635 break;
18636
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018637 case XML_SCHEMA_FACET_WHITESPACE:{
18638 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18639 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18640 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18641 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18642 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18643 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18644 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18646 /* No error message for RelaxNG. */
18647 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018648 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018649 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018650 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018651 "The value '%s' of the facet 'whitespace' is not "
18652 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018653 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018654 }
18655 }
18656 default:
18657 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018658 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018659exit:
18660 if ((! ctxtGiven) && (pctxt != NULL))
18661 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018662 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018663internal_error:
18664 if ((! ctxtGiven) && (pctxt != NULL))
18665 xmlSchemaFreeParserCtxt(pctxt);
18666 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018667}
18668
18669/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018670 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018671 * @typeDecl: the schema type definition
18672 * @ctxt: the schema parser context
18673 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018674 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018675 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018676static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018677xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018678 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018679{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018680 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018681 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018682 /*
18683 * NOTE: It is intended to use the facets list, instead
18684 * of facetSet.
18685 */
18686 if (typeDecl->facets != NULL) {
18687 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018688
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018689 /*
18690 * Temporarily assign the "schema" to the validation context
18691 * of the parser context. This is needed for NOTATION validation.
18692 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018693 if (pctxt->vctxt == NULL) {
18694 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18695 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018696 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018697 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018698 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018699 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18700 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018701 facet = facet->next;
18702 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018703 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018704 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018705 if (olderrs != pctxt->nberrors)
18706 return(pctxt->err);
18707 return(0);
18708exit_failure:
18709 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018710}
18711
18712/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018713 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018714 * @ctxtMGroup: the searched model group
18715 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018716 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018717 *
18718 * This one is intended to be used by
18719 * xmlSchemaCheckGroupDefCircular only.
18720 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018721 * Returns the particle with the circular model group definition reference,
18722 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018724static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018725xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018726 xmlSchemaTreeItemPtr particle)
18727{
18728 xmlSchemaTreeItemPtr circ = NULL;
18729 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018730 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018731
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018732 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018733 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018734 if (term == NULL)
18735 continue;
18736 switch (term->type) {
18737 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018738 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018739 if (gdef == groupDef)
18740 return (particle);
18741 /*
18742 * Mark this model group definition to avoid infinite
18743 * recursion on circular references not yet examined.
18744 */
18745 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18746 continue;
18747 if (gdef->children != NULL) {
18748 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18749 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18750 gdef->children->children);
18751 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18752 if (circ != NULL)
18753 return (circ);
18754 }
18755 break;
18756 case XML_SCHEMA_TYPE_SEQUENCE:
18757 case XML_SCHEMA_TYPE_CHOICE:
18758 case XML_SCHEMA_TYPE_ALL:
18759 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18760 if (circ != NULL)
18761 return (circ);
18762 break;
18763 default:
18764 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018765 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018766 }
18767 return (NULL);
18768}
18769
18770/**
18771 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018772 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018773 * @ctxt: the parser context
18774 * @name: the name
18775 *
18776 * Checks for circular references to model group definitions.
18777 */
18778static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018779xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018780 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018781{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018782 /*
18783 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018784 * 2 Circular groups are disallowed. That is, within the {particles}
18785 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018786 * is the group itself.
18787 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018788 if ((item == NULL) ||
18789 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18790 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018791 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018792 {
18793 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018794
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018795 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018796 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018797 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018798 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018799 * TODO: The error report is not adequate: this constraint
18800 * is defined for model groups but not definitions, but since
18801 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018802 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018803 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018804 */
18805 xmlSchemaPCustomErr(ctxt,
18806 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018807 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018808 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018809 "defined", xmlSchemaFormatQName(&str,
18810 item->targetNamespace, item->name));
18811 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018812 /*
18813 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018814 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018815 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018816 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018817 }
18818 }
18819}
18820
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018821/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018822 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018823 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018824 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018825 *
18826 * Assigns the model group of model group definitions to the "term"
18827 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018828 * In xmlSchemaResolveModelGroupParticleReferences the model group
18829 * definitions were assigned to the "term", since needed for the
18830 * circularity check.
18831 *
18832 * Schema Component Constraint:
18833 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018834 */
18835static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018836xmlSchemaModelGroupToModelGroupDefFixup(
18837 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18838 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018839{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018840 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18841
18842 while (particle != NULL) {
18843 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18844 ((WXS_PARTICLE_TERM(particle))->type !=
18845 XML_SCHEMA_TYPE_GROUP))
18846 {
18847 particle = WXS_PTC_CAST particle->next;
18848 continue;
18849 }
18850 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18851 /*
18852 * TODO: Remove the particle.
18853 */
18854 WXS_PARTICLE_TERM(particle) = NULL;
18855 particle = WXS_PTC_CAST particle->next;
18856 continue;
18857 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018858 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018859 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018860 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018861 WXS_PARTICLE_TERM(particle) =
18862 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18863
18864 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018865 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018866}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018867
18868/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018869 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018870 * @ctxtGr: the searched attribute group
18871 * @attr: the current attribute list to be processed
18872 *
18873 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018874 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018875 *
18876 * Returns the circular attribute grou reference, otherwise NULL.
18877 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018878static xmlSchemaQNameRefPtr
18879xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18880 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018881{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018882 xmlSchemaAttributeGroupPtr gr;
18883 xmlSchemaQNameRefPtr ref, circ;
18884 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018885 /*
18886 * We will search for an attribute group reference which
18887 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018888 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018889 for (i = 0; i < list->nbItems; i++) {
18890 ref = list->items[i];
18891 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18892 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18893 (ref->item != NULL))
18894 {
18895 gr = WXS_ATTR_GROUP_CAST ref->item;
18896 if (gr == ctxtGr)
18897 return(ref);
18898 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18899 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018900 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018901 * Mark as visited to avoid infinite recursion on
18902 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018903 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018904 if ((gr->attrUses) &&
18905 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18906 {
18907 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18908 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18909 (xmlSchemaItemListPtr) gr->attrUses);
18910 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18911 if (circ != NULL)
18912 return (circ);
18913 }
18914
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018915 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018916 }
18917 return (NULL);
18918}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018919
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018920/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018921 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018922 * attrGr: the attribute group definition
18923 * @ctxt: the parser context
18924 * @name: the name
18925 *
18926 * Checks for circular references of attribute groups.
18927 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018928static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018929xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018930 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018931{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018932 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018933 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018934 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018935 * 3 Circular group reference is disallowed outside <redefine>.
18936 * That is, unless this element information item's parent is
18937 * <redefine>, then among the [children], if any, there must
18938 * not be an <attributeGroup> with ref [attribute] which resolves
18939 * to the component corresponding to this <attributeGroup>. Indirect
18940 * circularity is also ruled out. That is, when QName resolution
18941 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18942 * any <attributeGroup>s with a ref [attribute] among the [children],
18943 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018944 * which resolves to the component corresponding to this <attributeGroup>.
18945 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018946 if (attrGr->attrUses == NULL)
18947 return(0);
18948 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18949 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018950 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018951 xmlSchemaQNameRefPtr circ;
18952
18953 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18954 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018956 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018957 /*
18958 * TODO: Report the referenced attr group as QName.
18959 */
18960 xmlSchemaPCustomErr(ctxt,
18961 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018962 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018963 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018964 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18965 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018966 /*
18967 * NOTE: We will cut the reference to avoid further
18968 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018969 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018970 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018971 circ->item = NULL;
18972 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018973 }
18974 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018975 return(0);
18976}
18977
18978static int
18979xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18980 xmlSchemaAttributeGroupPtr attrGr);
18981
18982/**
18983 * xmlSchemaExpandAttributeGroupRefs:
18984 * @pctxt: the parser context
18985 * @node: the node of the component holding the attribute uses
18986 * @completeWild: the intersected wildcard to be returned
18987 * @list: the attribute uses
18988 *
18989 * Substitutes contained attribute group references
18990 * for their attribute uses. Wilcards are intersected.
18991 * Attribute use prohibitions are removed from the list
18992 * and returned via the @prohibs list.
18993 * Pointlessness of attr. prohibs, if a matching attr. decl
18994 * is existent a well, are checked.
18995 */
18996static int
18997xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
18998 xmlSchemaBasicItemPtr item,
18999 xmlSchemaWildcardPtr *completeWild,
19000 xmlSchemaItemListPtr list,
19001 xmlSchemaItemListPtr prohibs)
19002{
19003 xmlSchemaAttributeGroupPtr gr;
19004 xmlSchemaAttributeUsePtr use;
19005 xmlSchemaItemListPtr sublist;
19006 int i, j;
19007 int created = (*completeWild == NULL) ? 0 : 1;
19008
19009 if (prohibs)
19010 prohibs->nbItems = 0;
19011
19012 for (i = 0; i < list->nbItems; i++) {
19013 use = list->items[i];
19014
19015 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19016 if (prohibs == NULL) {
19017 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19018 "unexpected attr prohibition found");
19019 return(-1);
19020 }
19021 /*
19022 * Remove from attribute uses.
19023 */
19024 if (xmlSchemaItemListRemove(list, i) == -1)
19025 return(-1);
19026 i--;
19027 /*
19028 * Note that duplicate prohibitions were already
19029 * handled at parsing time.
19030 */
19031 /*
19032 * Add to list of prohibitions.
19033 */
19034 xmlSchemaItemListAddSize(prohibs, 2, use);
19035 continue;
19036 }
19037 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19038 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19039 {
19040 if ((WXS_QNAME_CAST use)->item == NULL)
19041 return(-1);
19042 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19043 /*
19044 * Expand the referenced attr. group.
19045 * TODO: remove this, this is done in a previous step, so
19046 * already done here.
19047 */
19048 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19049 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19050 return(-1);
19051 }
19052 /*
19053 * Build the 'complete' wildcard; i.e. intersect multiple
19054 * wildcards.
19055 */
19056 if (gr->attributeWildcard != NULL) {
19057 if (*completeWild == NULL) {
19058 *completeWild = gr->attributeWildcard;
19059 } else {
19060 if (! created) {
19061 xmlSchemaWildcardPtr tmpWild;
19062
19063 /*
19064 * Copy the first encountered wildcard as context,
19065 * except for the annotation.
19066 *
19067 * Although the complete wildcard might not correspond
19068 * to any node in the schema, we will anchor it on
19069 * the node of the owner component.
19070 */
19071 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19072 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19073 WXS_ITEM_NODE(item));
19074 if (tmpWild == NULL)
19075 return(-1);
19076 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19077 tmpWild, *completeWild) == -1)
19078 return (-1);
19079 tmpWild->processContents = (*completeWild)->processContents;
19080 *completeWild = tmpWild;
19081 created = 1;
19082 }
19083
19084 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19085 gr->attributeWildcard) == -1)
19086 return(-1);
19087 }
19088 }
19089 /*
19090 * Just remove the reference if the referenced group does not
19091 * contain any attribute uses.
19092 */
19093 if (gr->attrUses == NULL) {
19094 if (xmlSchemaItemListRemove(list, i) == -1)
19095 return(-1);
19096 i--;
19097 continue;
19098 }
19099 /*
19100 * Add the attribute uses.
19101 */
19102 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19103 if (sublist->nbItems != 0) {
19104 list->items[i] = sublist->items[0];
19105 if (sublist->nbItems != 1) {
19106 for (j = 1; j < sublist->nbItems; j++) {
19107 i++;
19108 if (xmlSchemaItemListInsert(list,
19109 sublist->items[j], i) == -1)
19110 return(-1);
19111 }
19112 }
19113 }
19114 }
19115
19116 }
19117 /*
19118 * Handle pointless prohibitions of declared attributes.
19119 */
19120 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19121 xmlSchemaAttributeUseProhibPtr prohib;
19122
19123 for (i = prohibs->nbItems -1; i >= 0; i--) {
19124 prohib = prohibs->items[i];
19125 for (j = 0; j < list->nbItems; j++) {
19126 use = list->items[j];
19127
19128 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19129 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19130 {
19131 xmlChar *str = NULL;
19132
19133 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19134 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19135 prohib->node, NULL,
19136 "Skipping pointless attribute use prohibition "
19137 "'%s', since a corresponding attribute use "
19138 "exists already in the type definition",
19139 xmlSchemaFormatQName(&str,
19140 prohib->targetNamespace, prohib->name),
19141 NULL, NULL);
19142 FREE_AND_NULL(str);
19143 /*
19144 * Remove the prohibition.
19145 */
19146 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19147 return(-1);
19148 break;
19149 }
19150 }
19151 }
19152 }
19153 return(0);
19154}
19155
19156/**
19157 * xmlSchemaAttributeGroupExpandRefs:
19158 * @pctxt: the parser context
19159 * @attrGr: the attribute group definition
19160 *
19161 * Computation of:
19162 * {attribute uses} property
19163 * {attribute wildcard} property
19164 *
19165 * Substitutes contained attribute group references
19166 * for their attribute uses. Wilcards are intersected.
19167 */
19168static int
19169xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19170 xmlSchemaAttributeGroupPtr attrGr)
19171{
19172 if ((attrGr->attrUses == NULL) ||
19173 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19174 return(0);
19175
19176 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19177 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19178 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19179 return(-1);
19180 return(0);
19181}
19182
19183/**
19184 * xmlSchemaAttributeGroupExpandRefs:
19185 * @pctxt: the parser context
19186 * @attrGr: the attribute group definition
19187 *
19188 * Substitutes contained attribute group references
19189 * for their attribute uses. Wilcards are intersected.
19190 *
19191 * Schema Component Constraint:
19192 * Attribute Group Definition Properties Correct (ag-props-correct)
19193 */
19194static int
19195xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19196 xmlSchemaAttributeGroupPtr attrGr)
19197{
19198 /*
19199 * SPEC ag-props-correct
19200 * (1) "The values of the properties of an attribute group definition
19201 * must be as described in the property tableau in The Attribute
19202 * Group Definition Schema Component (§3.6.1), modulo the impact of
19203 * Missing Sub-components (§5.3);"
19204 */
19205
19206 if ((attrGr->attrUses != NULL) &&
19207 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19208 {
19209 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19210 xmlSchemaAttributeUsePtr use, tmp;
19211 int i, j, hasId = 0;
19212
19213 for (i = uses->nbItems -1; i >= 0; i--) {
19214 use = uses->items[i];
19215 /*
19216 * SPEC ag-props-correct
19217 * (2) "Two distinct members of the {attribute uses} must not have
19218 * {attribute declaration}s both of whose {name}s match and whose
19219 * {target namespace}s are identical."
19220 */
19221 if (i > 0) {
19222 for (j = i -1; j >= 0; j--) {
19223 tmp = uses->items[j];
19224 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19225 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19226 (WXS_ATTRUSE_DECL_TNS(use) ==
19227 WXS_ATTRUSE_DECL_TNS(tmp)))
19228 {
19229 xmlChar *str = NULL;
19230
19231 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19232 XML_SCHEMAP_AG_PROPS_CORRECT,
19233 attrGr->node, WXS_BASIC_CAST attrGr,
19234 "Duplicate %s",
19235 xmlSchemaGetComponentDesignation(&str, use),
19236 NULL);
19237 FREE_AND_NULL(str);
19238 /*
19239 * Remove the duplicate.
19240 */
19241 if (xmlSchemaItemListRemove(uses, i) == -1)
19242 return(-1);
19243 goto next_use;
19244 }
19245 }
19246 }
19247 /*
19248 * SPEC ag-props-correct
19249 * (3) "Two distinct members of the {attribute uses} must not have
19250 * {attribute declaration}s both of whose {type definition}s are or
19251 * are derived from ID."
19252 * TODO: Does 'derived' include member-types of unions?
19253 */
19254 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19255 if (xmlSchemaIsDerivedFromBuiltInType(
19256 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19257 {
19258 if (hasId) {
19259 xmlChar *str = NULL;
19260
19261 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19262 XML_SCHEMAP_AG_PROPS_CORRECT,
19263 attrGr->node, WXS_BASIC_CAST attrGr,
19264 "There must not exist more than one attribute "
19265 "declaration of type 'xs:ID' "
19266 "(or derived from 'xs:ID'). The %s violates this "
19267 "constraint",
19268 xmlSchemaGetComponentDesignation(&str, use),
19269 NULL);
19270 FREE_AND_NULL(str);
19271 if (xmlSchemaItemListRemove(uses, i) == -1)
19272 return(-1);
19273 }
19274 hasId = 1;
19275 }
19276 }
19277next_use: {}
19278 }
19279 }
19280 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019281}
19282
19283/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019284 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019285 * @attrgrpDecl: the schema attribute definition
19286 * @ctxt: the schema parser context
19287 * @name: the attribute name
19288 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019289 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019290 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019291static int
19292xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19293 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019294{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019295 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019296
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019297 if (ref->item != NULL)
19298 return(0);
19299 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19300 ref->name,
19301 ref->targetNamespace);
19302 if (group == NULL) {
19303 xmlSchemaPResCompAttrErr(ctxt,
19304 XML_SCHEMAP_SRC_RESOLVE,
19305 NULL, ref->node,
19306 "ref", ref->name, ref->targetNamespace,
19307 ref->itemType, NULL);
19308 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019309 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019310 ref->item = WXS_BASIC_CAST group;
19311 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019312}
19313
19314/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019315 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019316 * @item: an schema attribute declaration/use
19317 * @ctxt: a schema parser context
19318 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019319 *
19320 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019321 * Schema Component Constraint:
19322 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019323 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019324 * Validates the value constraints of an attribute declaration/use.
19325 * NOTE that this needs the simle type definitions to be already
19326 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019327 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019328static int
19329xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19330 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019331{
19332
19333 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019334 * SPEC a-props-correct (1)
19335 * "The values of the properties of an attribute declaration must
19336 * be as described in the property tableau in The Attribute
19337 * Declaration Schema Component (§3.2.1), modulo the impact of
19338 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019339 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019340
19341 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19342 return(0);
19343
19344 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019345 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019346
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019347 /*
19348 * SPEC a-props-correct (3)
19349 * "If the {type definition} is or is derived from ID then there
19350 * must not be a {value constraint}."
19351 */
19352 if (xmlSchemaIsDerivedFromBuiltInType(
19353 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19354 {
19355 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19356 XML_SCHEMAP_A_PROPS_CORRECT_3,
19357 NULL, WXS_BASIC_CAST attr,
19358 "Value constraints are not allowed if the type definition "
19359 "is or is derived from xs:ID",
19360 NULL, NULL);
19361 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019362 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019363 /*
19364 * SPEC a-props-correct (2)
19365 * "if there is a {value constraint}, the canonical lexical
19366 * representation of its value must be ·valid· with respect
19367 * to the {type definition} as defined in String Valid (§3.14.4)."
19368 * TODO: Don't care about the *cononical* stuff here, this requirement
19369 * will be removed in WXS 1.1 anyway.
19370 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019371 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019372 attr->node, WXS_ATTR_TYPEDEF(attr),
19373 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019374 1, 1, 0);
19375 if (ret != 0) {
19376 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019377 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019378 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019379 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019380 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019381 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019382 XML_SCHEMAP_A_PROPS_CORRECT_2,
19383 NULL, WXS_BASIC_CAST attr,
19384 "The value of the value constraint is not valid",
19385 NULL, NULL);
19386 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019387 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019388 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019389
19390 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019391}
19392
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019393static xmlSchemaElementPtr
19394xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19395 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019396{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019397 xmlSchemaElementPtr ret;
19398
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019399 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019400 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019401 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019402 return (ancestor);
19403
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019404 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019405 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019406 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019407 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019408 WXS_SUBST_HEAD(ancestor));
19409 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019410
19411 return (ret);
19412}
19413
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019414/**
19415 * xmlSchemaCheckElemPropsCorrect:
19416 * @ctxt: a schema parser context
19417 * @decl: the element declaration
19418 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019419 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019420 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019421 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019422 *
19423 * STATUS:
19424 * missing: (6)
19425 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019426static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019427xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19428 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019429{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019430 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019431 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019432 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019433 * SPEC (1) "The values of the properties of an element declaration
19434 * must be as described in the property tableau in The Element
19435 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19436 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019437 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019438 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19439 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019440
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019441 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019442 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019443 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019444 * affiliation}, then {scope} must be global."
19445 */
19446 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19447 xmlSchemaPCustomErr(pctxt,
19448 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019449 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019450 "Only global element declarations can have a "
19451 "substitution group affiliation", NULL);
19452 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019453 }
19454 /*
19455 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19456 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019457 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019458 * property."
19459 */
19460 if (head == elemDecl)
19461 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019462 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019463 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19464 else
19465 circ = NULL;
19466 if (circ != NULL) {
19467 xmlChar *strA = NULL, *strB = NULL;
19468
19469 xmlSchemaPCustomErrExt(pctxt,
19470 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019471 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019472 "The element declaration '%s' defines a circular "
19473 "substitution group to element declaration '%s'",
19474 xmlSchemaGetComponentQName(&strA, circ),
19475 xmlSchemaGetComponentQName(&strB, head),
19476 NULL);
19477 FREE_AND_NULL(strA)
19478 FREE_AND_NULL(strB)
19479 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19480 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019481 /*
19482 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019483 * the {type definition}
19484 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019485 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019486 * of the {substitution group exclusions} of the {substitution group
19487 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19488 * (if the {type definition} is complex) or as defined in
19489 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019490 * simple)."
19491 *
19492 * NOTE: {substitution group exclusions} means the values of the
19493 * attribute "final".
19494 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019495
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019496 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019497 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019498
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019499 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19500 set |= SUBSET_EXTENSION;
19501 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19502 set |= SUBSET_RESTRICTION;
19503
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019504 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019505 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019506 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19507
19508 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019509 xmlSchemaPCustomErrExt(pctxt,
19510 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019511 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019512 "The type definition '%s' was "
19513 "either rejected by the substitution group "
19514 "affiliation '%s', or not validly derived from its type "
19515 "definition '%s'",
19516 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019517 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019518 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019519 FREE_AND_NULL(strA)
19520 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019521 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019522 }
19523 }
19524 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019525 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019526 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019527 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019528 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019529 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019530 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019531 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019532 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019533 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019534 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019535 (WXS_IS_COMPLEX(typeDef) &&
19536 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019537 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19538 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019539
19540 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19541 xmlSchemaPCustomErr(pctxt,
19542 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019543 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019544 "The type definition (or type definition's content type) is or "
19545 "is derived from ID; value constraints are not allowed in "
19546 "conjunction with such a type definition", NULL);
19547 } else if (elemDecl->value != NULL) {
19548 int vcret;
19549 xmlNodePtr node = NULL;
19550
19551 /*
19552 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19553 * representation of its value must be ·valid· with respect to the
19554 * {type definition} as defined in Element Default Valid (Immediate)
19555 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019556 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019557 if (typeDef == NULL) {
19558 xmlSchemaPErr(pctxt, elemDecl->node,
19559 XML_SCHEMAP_INTERNAL,
19560 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19561 "type is missing... skipping validation of "
19562 "the value constraint", NULL, NULL);
19563 return (-1);
19564 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019565 if (elemDecl->node != NULL) {
19566 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19567 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19568 BAD_CAST "fixed");
19569 else
19570 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19571 BAD_CAST "default");
19572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019573 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19574 typeDef, elemDecl->value, &(elemDecl->defVal));
19575 if (vcret != 0) {
19576 if (vcret < 0) {
19577 PERROR_INT("xmlSchemaElemCheckValConstr",
19578 "failed to validate the value constraint of an "
19579 "element declaration");
19580 return (-1);
19581 }
19582 return (vcret);
19583 }
19584 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019585
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019586 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019587}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019588
19589/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019590 * xmlSchemaCheckElemSubstGroup:
19591 * @ctxt: a schema parser context
19592 * @decl: the element declaration
19593 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019594 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019595 * Schema Component Constraint:
19596 * Substitution Group (cos-equiv-class)
19597 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019598 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019599 * a list will be built for each subst. group head, holding all direct
19600 * referents to this head.
19601 * NOTE that this function needs:
19602 * 1. circular subst. groups to be checked beforehand
19603 * 2. the declaration's type to be derived from the head's type
19604 *
19605 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019606 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019607 */
19608static void
19609xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19610 xmlSchemaElementPtr elemDecl)
19611{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019612 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019613 /* SPEC (1) "Its {abstract} is false." */
19614 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19615 return;
19616 {
19617 xmlSchemaElementPtr head;
19618 xmlSchemaTypePtr headType, type;
19619 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019620 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019621 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19622 * {disallowed substitutions} as the blocking constraint, as defined in
19623 * Substitution Group OK (Transitive) (§3.3.6)."
19624 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019625 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19626 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019627 set = 0;
19628 methSet = 0;
19629 /*
19630 * The blocking constraints.
19631 */
19632 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19633 continue;
19634 headType = head->subtypes;
19635 type = elemDecl->subtypes;
19636 if (headType == type)
19637 goto add_member;
19638 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19639 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19640 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19641 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19642 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019643 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019644 * "The set of all {derivation method}s involved in the
19645 * derivation of D's {type definition} from C's {type definition}
19646 * does not intersect with the union of the blocking constraint,
19647 * C's {prohibited substitutions} (if C is complex, otherwise the
19648 * empty set) and the {prohibited substitutions} (respectively the
19649 * empty set) of any intermediate {type definition}s in the
19650 * derivation of D's {type definition} from C's {type definition}."
19651 */
19652 /*
19653 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19654 * subst.head axis, the methSet does not need to be computed for
19655 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019656 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019657 /*
19658 * The set of all {derivation method}s involved in the derivation
19659 */
19660 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019661 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019662 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19663 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019664
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019665 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019666 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19667 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19668
19669 type = type->baseType;
19670 }
19671 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019672 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019673 * the head's type.
19674 */
19675 type = elemDecl->subtypes->baseType;
19676 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019677 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019678 if ((type->flags &
19679 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19680 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19681 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19682 if ((type->flags &
19683 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19684 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19685 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19686 } else
19687 break;
19688 if (type == headType)
19689 break;
19690 type = type->baseType;
19691 }
19692 if ((set != 0) &&
19693 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19694 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19695 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19696 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19697 continue;
19698 }
19699add_member:
19700 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19701 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19702 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19703 }
19704 }
19705}
19706
19707/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019708 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019709 * @item: an schema element declaration/particle
19710 * @ctxt: a schema parser context
19711 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019712 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019713 * Validates the value constraints of an element declaration.
19714 *
19715 * Fixes finish doing the computations on the element declarations.
19716 */
19717static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019718xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019719 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019720{
19721 if (elemDecl == NULL)
19722 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019723 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19724 return;
19725 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019726 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19727 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019728}
19729
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019730/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019731 * xmlSchemaResolveModelGroupParticleReferences:
19732 * @particle: a particle component
19733 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019734 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019735 * Resolves references of a model group's {particles} to
19736 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019737 */
19738static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019739xmlSchemaResolveModelGroupParticleReferences(
19740 xmlSchemaParserCtxtPtr ctxt,
19741 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019742{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019743 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19744 xmlSchemaQNameRefPtr ref;
19745 xmlSchemaBasicItemPtr refItem;
19746
19747 /*
19748 * URGENT TODO: Test this.
19749 */
19750 while (particle != NULL) {
19751 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19752 ((WXS_PARTICLE_TERM(particle))->type !=
19753 XML_SCHEMA_EXTRA_QNAMEREF))
19754 {
19755 goto next_particle;
19756 }
19757 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019758 /*
19759 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019760 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019761 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019762 particle->children = NULL;
19763
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019764 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19765 ref->itemType, ref->name, ref->targetNamespace);
19766 if (refItem == NULL) {
19767 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019768 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019769 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019770 /* TODO: remove the particle. */
19771 goto next_particle;
19772 }
19773 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19774 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19775 /* TODO: remove the particle. */
19776 goto next_particle;
19777 /*
19778 * NOTE that we will assign the model group definition
19779 * itself to the "term" of the particle. This will ease
19780 * the check for circular model group definitions. After
19781 * that the "term" will be assigned the model group of the
19782 * model group definition.
19783 */
19784 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19785 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019786 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019787 * SPEC cos-all-limited (1)
19788 * SPEC cos-all-limited (1.2)
19789 * "It appears only as the value of one or both of the
19790 * following properties:"
19791 * (1.1) "the {model group} property of a model group
19792 * definition."
19793 * (1.2) "the {term} property of a particle [... of] the "
19794 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019795 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019796 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19797 /* TODO: error code */
19798 XML_SCHEMAP_COS_ALL_LIMITED,
19799 WXS_ITEM_NODE(particle), NULL,
19800 "A model group definition is referenced, but "
19801 "it contains an 'all' model group, which "
19802 "cannot be contained by model groups",
19803 NULL, NULL);
19804 /* TODO: remove the particle. */
19805 goto next_particle;
19806 }
19807 particle->children = (xmlSchemaTreeItemPtr) refItem;
19808 } else {
19809 /*
19810 * TODO: Are referenced element declarations the only
19811 * other components we expect here?
19812 */
19813 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019814 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019815next_particle:
19816 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019817 }
19818}
19819
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019820static int
19821xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19822 xmlSchemaValPtr y)
19823{
19824 xmlSchemaTypePtr tx, ty, ptx, pty;
19825 int ret;
19826
19827 while (x != NULL) {
19828 /* Same types. */
19829 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19830 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19831 ptx = xmlSchemaGetPrimitiveType(tx);
19832 pty = xmlSchemaGetPrimitiveType(ty);
19833 /*
19834 * (1) if a datatype T' is ·derived· by ·restriction· from an
19835 * atomic datatype T then the ·value space· of T' is a subset of
19836 * the ·value space· of T. */
19837 /*
19838 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19839 * from a common atomic ancestor T then the ·value space·s of T'
19840 * and T'' may overlap.
19841 */
19842 if (ptx != pty)
19843 return(0);
19844 /*
19845 * We assume computed values to be normalized, so do a fast
19846 * string comparison for string based types.
19847 */
19848 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019849 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019850 if (! xmlStrEqual(
19851 xmlSchemaValueGetAsString(x),
19852 xmlSchemaValueGetAsString(y)))
19853 return (0);
19854 } else {
19855 ret = xmlSchemaCompareValuesWhtsp(
19856 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19857 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19858 if (ret == -2)
19859 return(-1);
19860 if (ret != 0)
19861 return(0);
19862 }
19863 /*
19864 * Lists.
19865 */
19866 x = xmlSchemaValueGetNext(x);
19867 if (x != NULL) {
19868 y = xmlSchemaValueGetNext(y);
19869 if (y == NULL)
19870 return (0);
19871 } else if (xmlSchemaValueGetNext(y) != NULL)
19872 return (0);
19873 else
19874 return (1);
19875 }
19876 return (0);
19877}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019878
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019879/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019880 * xmlSchemaResolveAttrUseReferences:
19881 * @item: an attribute use
19882 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019883 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019884 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019885 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019886static int
19887xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19888 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019889{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019890 if ((ctxt == NULL) || (ause == NULL))
19891 return(-1);
19892 if ((ause->attrDecl == NULL) ||
19893 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19894 return(0);
19895
19896 {
19897 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19898
19899 /*
19900 * TODO: Evaluate, what errors could occur if the declaration is not
19901 * found.
19902 */
19903 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19904 ref->name, ref->targetNamespace);
19905 if (ause->attrDecl == NULL) {
19906 xmlSchemaPResCompAttrErr(ctxt,
19907 XML_SCHEMAP_SRC_RESOLVE,
19908 WXS_BASIC_CAST ause, ause->node,
19909 "ref", ref->name, ref->targetNamespace,
19910 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19911 return(ctxt->err);;
19912 }
19913 }
19914 return(0);
19915}
19916
19917/**
19918 * xmlSchemaCheckAttrUsePropsCorrect:
19919 * @ctxt: a parser context
19920 * @use: an attribute use
19921 *
19922 * Schema Component Constraint:
19923 * Attribute Use Correct (au-props-correct)
19924 *
19925 */
19926static int
19927xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19928 xmlSchemaAttributeUsePtr use)
19929{
19930 if ((ctxt == NULL) || (use == NULL))
19931 return(-1);
19932 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19933 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19934 return(0);
19935
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019936 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019937 * SPEC au-props-correct (1)
19938 * "The values of the properties of an attribute use must be as
19939 * described in the property tableau in The Attribute Use Schema
19940 * Component (§3.5.1), modulo the impact of Missing
19941 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019942 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019943
19944 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19945 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19946 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19947 {
19948 xmlSchemaPCustomErr(ctxt,
19949 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19950 WXS_BASIC_CAST use, NULL,
19951 "The attribute declaration has a 'fixed' value constraint "
19952 ", thus the attribute use must also have a 'fixed' value "
19953 "constraint",
19954 NULL);
19955 return(ctxt->err);
19956 }
19957 /*
19958 * Compute and check the value constraint's value.
19959 */
19960 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19961 int ret;
19962 /*
19963 * TODO: The spec seems to be missing a check of the
19964 * value constraint of the attribute use. We will do it here.
19965 */
19966 /*
19967 * SPEC a-props-correct (3)
19968 */
19969 if (xmlSchemaIsDerivedFromBuiltInType(
19970 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19971 {
19972 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19973 XML_SCHEMAP_AU_PROPS_CORRECT,
19974 NULL, WXS_BASIC_CAST use,
19975 "Value constraints are not allowed if the type definition "
19976 "is or is derived from xs:ID",
19977 NULL, NULL);
19978 return(ctxt->err);
19979 }
19980
19981 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19982 use->node, WXS_ATTRUSE_TYPEDEF(use),
19983 use->defValue, &(use->defVal),
19984 1, 1, 0);
19985 if (ret != 0) {
19986 if (ret < 0) {
19987 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19988 "calling xmlSchemaVCheckCVCSimpleType()");
19989 return(-1);
19990 }
19991 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19992 XML_SCHEMAP_AU_PROPS_CORRECT,
19993 NULL, WXS_BASIC_CAST use,
19994 "The value of the value constraint is not valid",
19995 NULL, NULL);
19996 return(ctxt->err);
19997 }
19998 }
19999 /*
20000 * SPEC au-props-correct (2)
20001 * "If the {attribute declaration} has a fixed
20002 * {value constraint}, then if the attribute use itself has a
20003 * {value constraint}, it must also be fixed and its value must match
20004 * that of the {attribute declaration}'s {value constraint}."
20005 */
20006 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20007 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20008 {
20009 if (! xmlSchemaAreValuesEqual(use->defVal,
20010 (WXS_ATTRUSE_DECL(use))->defVal))
20011 {
20012 xmlSchemaPCustomErr(ctxt,
20013 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20014 WXS_BASIC_CAST use, NULL,
20015 "The 'fixed' value constraint of the attribute use "
20016 "must match the attribute declaration's value "
20017 "constraint '%s'",
20018 (WXS_ATTRUSE_DECL(use))->defValue);
20019 }
20020 return(ctxt->err);
20021 }
20022 return(0);
20023}
20024
20025
20026
20027
20028/**
20029 * xmlSchemaResolveAttrTypeReferences:
20030 * @item: an attribute declaration
20031 * @ctxt: a parser context
20032 *
20033 * Resolves the referenced type definition component.
20034 */
20035static int
20036xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20037 xmlSchemaParserCtxtPtr ctxt)
20038{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020039 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020040 * The simple type definition corresponding to the <simpleType> element
20041 * information item in the [children], if present, otherwise the simple
20042 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020043 * [attribute], if present, otherwise the ·simple ur-type definition·.
20044 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020045 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020046 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020047 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20048 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020049 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020050 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020051 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020052
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020053 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20054 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020055 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020056 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020057 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020058 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020059 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020060 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020061 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020062 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020063 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020064
Daniel Veillard3646d642004-06-02 19:19:14 +000020065 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020066 /*
20067 * The type defaults to the xs:anySimpleType.
20068 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020069 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20070 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020071 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020072}
20073
20074/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020075 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020076 * @idc: the identity-constraint definition
20077 * @ctxt: the schema parser context
20078 * @name: the attribute name
20079 *
20080 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020081 * Schema Component Constraint:
20082 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020083 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020084static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020085xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020086 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020087{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020088 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020089 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020090 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020091 idc->ref->item = (xmlSchemaBasicItemPtr)
20092 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20093 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020094 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020095 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020096 * TODO: It is actually not an error to fail to resolve
20097 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020098 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020099 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020100 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020101 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020102 "refer", idc->ref->name,
20103 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020104 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020105 return(pctxt->err);
20106 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20107 /*
20108 * SPEC c-props-correct (1)
20109 */
20110 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20111 XML_SCHEMAP_C_PROPS_CORRECT,
20112 NULL, WXS_BASIC_CAST idc,
20113 "The keyref references a keyref",
20114 NULL, NULL);
20115 idc->ref->item = NULL;
20116 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020117 } else {
20118 if (idc->nbFields !=
20119 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20120 xmlChar *str = NULL;
20121 xmlSchemaIDCPtr refer;
20122
20123 refer = (xmlSchemaIDCPtr) idc->ref->item;
20124 /*
20125 * SPEC c-props-correct(2)
20126 * "If the {identity-constraint category} is keyref,
20127 * the cardinality of the {fields} must equal that of
20128 * the {fields} of the {referenced key}.
20129 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020130 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020131 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020132 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020133 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020134 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020135 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020136 refer->name),
20137 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020138 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020139 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020140 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020141 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020142 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020143 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020144}
20145
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020146static int
20147xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20148 xmlSchemaParserCtxtPtr pctxt)
20149{
20150 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20151 prohib->targetNamespace) == NULL) {
20152
20153 xmlSchemaPResCompAttrErr(pctxt,
20154 XML_SCHEMAP_SRC_RESOLVE,
20155 NULL, prohib->node,
20156 "ref", prohib->name, prohib->targetNamespace,
20157 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20158 return(XML_SCHEMAP_SRC_RESOLVE);
20159 }
20160 return(0);
20161}
20162
20163#define WXS_REDEFINED_TYPE(c) \
20164(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20165
20166#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20167(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20168
20169#define WXS_REDEFINED_ATTR_GROUP(c) \
20170(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20171
20172static int
20173xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20174{
20175 int err = 0;
20176 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20177 xmlSchemaBasicItemPtr prev, item;
20178 int wasRedefined;
20179
20180 if (redef == NULL)
20181 return(0);
20182
20183 do {
20184 item = redef->item;
20185 /*
20186 * First try to locate the redefined component in the
20187 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020188 * NOTE: According to this schema bug entry:
20189 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20190 * it's not clear if the referenced component needs to originate
20191 * from the <redefine>d schema _document_ or the schema; the latter
20192 * would include all imported and included sub-schemas of the
20193 * <redefine>d schema. Currenlty we latter approach is used.
20194 * SUPPLEMENT: It seems that the WG moves towards the latter
20195 * approach, so we are doing it right.
20196 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020197 */
20198 prev = xmlSchemaFindRedefCompInGraph(
20199 redef->targetBucket, item->type,
20200 redef->refName, redef->refTargetNs);
20201 if (prev == NULL) {
20202 xmlChar *str = NULL;
20203 xmlNodePtr node;
20204
20205 /*
20206 * SPEC src-redefine:
20207 * (6.2.1) "The ·actual value· of its own name attribute plus
20208 * target namespace must successfully ·resolve· to a model
20209 * group definition in I."
20210 * (7.2.1) "The ·actual value· of its own name attribute plus
20211 * target namespace must successfully ·resolve· to an attribute
20212 * group definition in I."
20213
20214 *
20215 * Note that, if we are redefining with the use of references
20216 * to components, the spec assumes the src-resolve to be used;
20217 * but this won't assure that we search only *inside* the
20218 * redefined schema.
20219 */
20220 if (redef->reference)
20221 node = WXS_ITEM_NODE(redef->reference);
20222 else
20223 node = WXS_ITEM_NODE(item);
20224 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20225 /*
20226 * TODO: error code.
20227 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20228 * reference kind.
20229 */
20230 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020231 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020232 "the redefined schema",
20233 WXS_ITEM_TYPE_NAME(item),
20234 xmlSchemaFormatQName(&str, redef->refTargetNs,
20235 redef->refName));
20236 FREE_AND_NULL(str);
20237 err = pctxt->err;
20238 redef = redef->next;
20239 continue;
20240 }
20241 /*
20242 * TODO: Obtaining and setting the redefinition state is really
20243 * clumsy.
20244 */
20245 wasRedefined = 0;
20246 switch (item->type) {
20247 case XML_SCHEMA_TYPE_COMPLEX:
20248 case XML_SCHEMA_TYPE_SIMPLE:
20249 if ((WXS_TYPE_CAST prev)->flags &
20250 XML_SCHEMAS_TYPE_REDEFINED)
20251 {
20252 wasRedefined = 1;
20253 break;
20254 }
20255 /* Mark it as redefined. */
20256 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20257 /*
20258 * Assign the redefined type to the
20259 * base type of the redefining type.
20260 * TODO: How
20261 */
20262 ((xmlSchemaTypePtr) item)->baseType =
20263 (xmlSchemaTypePtr) prev;
20264 break;
20265 case XML_SCHEMA_TYPE_GROUP:
20266 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20267 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20268 {
20269 wasRedefined = 1;
20270 break;
20271 }
20272 /* Mark it as redefined. */
20273 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20274 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20275 if (redef->reference != NULL) {
20276 /*
20277 * Overwrite the QName-reference with the
20278 * referenced model group def.
20279 */
20280 (WXS_PTC_CAST redef->reference)->children =
20281 WXS_TREE_CAST prev;
20282 }
20283 redef->target = prev;
20284 break;
20285 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20286 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20287 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20288 {
20289 wasRedefined = 1;
20290 break;
20291 }
20292 (WXS_ATTR_GROUP_CAST prev)->flags |=
20293 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20294 if (redef->reference != NULL) {
20295 /*
20296 * Assign the redefined attribute group to the
20297 * QName-reference component.
20298 * This is the easy case, since we will just
20299 * expand the redefined group.
20300 */
20301 (WXS_QNAME_CAST redef->reference)->item = prev;
20302 redef->target = NULL;
20303 } else {
20304 /*
20305 * This is the complicated case: we need
20306 * to apply src-redefine (7.2.2) at a later
20307 * stage, i.e. when attribute group references
20308 * have beed expanded and simple types have
20309 * beed fixed.
20310 */
20311 redef->target = prev;
20312 }
20313 break;
20314 default:
20315 PERROR_INT("xmlSchemaResolveRedefReferences",
20316 "Unexpected redefined component type");
20317 return(-1);
20318 }
20319 if (wasRedefined) {
20320 xmlChar *str = NULL;
20321 xmlNodePtr node;
20322
20323 if (redef->reference)
20324 node = WXS_ITEM_NODE(redef->reference);
20325 else
20326 node = WXS_ITEM_NODE(redef->item);
20327
20328 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20329 /* TODO: error code. */
20330 XML_SCHEMAP_SRC_REDEFINE,
20331 node, NULL,
20332 "The referenced %s was already redefined. Multiple "
20333 "redefinition of the same component is not supported",
20334 xmlSchemaGetComponentDesignation(&str, prev),
20335 NULL);
20336 FREE_AND_NULL(str)
20337 err = pctxt->err;
20338 redef = redef->next;
20339 continue;
20340 }
20341 redef = redef->next;
20342 } while (redef != NULL);
20343
20344 return(err);
20345}
20346
20347static int
20348xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20349{
20350 int err = 0;
20351 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20352 xmlSchemaBasicItemPtr item;
20353
20354 if (redef == NULL)
20355 return(0);
20356
20357 do {
20358 if (redef->target == NULL) {
20359 redef = redef->next;
20360 continue;
20361 }
20362 item = redef->item;
20363
20364 switch (item->type) {
20365 case XML_SCHEMA_TYPE_SIMPLE:
20366 case XML_SCHEMA_TYPE_COMPLEX:
20367 /*
20368 * Since the spec wants the {name} of the redefined
20369 * type to be 'absent', we'll NULL it.
20370 */
20371 (WXS_TYPE_CAST redef->target)->name = NULL;
20372
20373 /*
20374 * TODO: Seems like there's nothing more to do. The normal
20375 * inheritance mechanism is used. But not 100% sure.
20376 */
20377 break;
20378 case XML_SCHEMA_TYPE_GROUP:
20379 /*
20380 * URGENT TODO:
20381 * SPEC src-redefine:
20382 * (6.2.2) "The {model group} of the model group definition
20383 * which corresponds to it per XML Representation of Model
20384 * Group Definition Schema Components (§3.7.2) must be a
20385 * ·valid restriction· of the {model group} of that model
20386 * group definition in I, as defined in Particle Valid
20387 * (Restriction) (§3.9.6)."
20388 */
20389 break;
20390 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20391 /*
20392 * SPEC src-redefine:
20393 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20394 * the attribute group definition which corresponds to it
20395 * per XML Representation of Attribute Group Definition Schema
20396 * Components (§3.6.2) must be ·valid restrictions· of the
20397 * {attribute uses} and {attribute wildcard} of that attribute
20398 * group definition in I, as defined in clause 2, clause 3 and
20399 * clause 4 of Derivation Valid (Restriction, Complex)
20400 * (§3.4.6) (where references to the base type definition are
20401 * understood as references to the attribute group definition
20402 * in I)."
20403 */
20404 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20405 XML_SCHEMA_ACTION_REDEFINE,
20406 item, redef->target,
20407 (WXS_ATTR_GROUP_CAST item)->attrUses,
20408 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20409 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20410 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20411 if (err == -1)
20412 return(-1);
20413 break;
20414 default:
20415 break;
20416 }
20417 redef = redef->next;
20418 } while (redef != NULL);
20419 return(0);
20420}
20421
20422
20423static int
20424xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20425 xmlSchemaBucketPtr bucket)
20426{
20427 xmlSchemaBasicItemPtr item;
20428 int err;
20429 xmlHashTablePtr *table;
20430 const xmlChar *name;
20431 int i;
20432
20433#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20434 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20435 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20436 else \
20437 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20438
20439 /*
20440 * Add global components to the schema's hash tables.
20441 * This is the place where duplicate components will be
20442 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020443 * TODO: I think normally we should support imports of the
20444 * same namespace from multiple locations. We don't do currently,
20445 * but if we do then according to:
20446 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20447 * we would need, if imported directly, to import redefined
20448 * components as well to be able to catch clashing components.
20449 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020450 */
20451 if (bucket == NULL)
20452 return(-1);
20453 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20454 return(0);
20455 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20456
20457 for (i = 0; i < bucket->globals->nbItems; i++) {
20458 item = bucket->globals->items[i];
20459 table = NULL;
20460 switch (item->type) {
20461 case XML_SCHEMA_TYPE_COMPLEX:
20462 case XML_SCHEMA_TYPE_SIMPLE:
20463 if (WXS_REDEFINED_TYPE(item))
20464 continue;
20465 name = (WXS_TYPE_CAST item)->name;
20466 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20467 break;
20468 case XML_SCHEMA_TYPE_ELEMENT:
20469 name = (WXS_ELEM_CAST item)->name;
20470 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20471 break;
20472 case XML_SCHEMA_TYPE_ATTRIBUTE:
20473 name = (WXS_ATTR_CAST item)->name;
20474 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20475 break;
20476 case XML_SCHEMA_TYPE_GROUP:
20477 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20478 continue;
20479 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20480 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20481 break;
20482 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20483 if (WXS_REDEFINED_ATTR_GROUP(item))
20484 continue;
20485 name = (WXS_ATTR_GROUP_CAST item)->name;
20486 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20487 break;
20488 case XML_SCHEMA_TYPE_IDC_KEY:
20489 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20490 case XML_SCHEMA_TYPE_IDC_KEYREF:
20491 name = (WXS_IDC_CAST item)->name;
20492 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20493 break;
20494 case XML_SCHEMA_TYPE_NOTATION:
20495 name = ((xmlSchemaNotationPtr) item)->name;
20496 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20497 break;
20498 default:
20499 PERROR_INT("xmlSchemaAddComponents",
20500 "Unexpected global component type");
20501 continue;
20502 }
20503 if (*table == NULL) {
20504 *table = xmlHashCreateDict(10, pctxt->dict);
20505 if (*table == NULL) {
20506 PERROR_INT("xmlSchemaAddComponents",
20507 "failed to create a component hash table");
20508 return(-1);
20509 }
20510 }
20511 err = xmlHashAddEntry(*table, name, item);
20512 if (err != 0) {
20513 xmlChar *str = NULL;
20514
20515 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20516 XML_SCHEMAP_REDEFINED_TYPE,
20517 WXS_ITEM_NODE(item),
20518 WXS_BASIC_CAST item,
20519 "A global %s '%s' does already exist",
20520 WXS_ITEM_TYPE_NAME(item),
20521 xmlSchemaGetComponentQName(&str, item));
20522 FREE_AND_NULL(str);
20523 }
20524 }
20525 /*
20526 * Process imported/included schemas.
20527 */
20528 if (bucket->relations != NULL) {
20529 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20530 do {
20531 if ((rel->bucket != NULL) &&
20532 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20533 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20534 return(-1);
20535 }
20536 rel = rel->next;
20537 } while (rel != NULL);
20538 }
20539 return(0);
20540}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020541
20542static int
20543xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20544{
20545 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20546 xmlSchemaTreeItemPtr item, *items;
20547 int nbItems, i;
20548
20549#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20550
20551 if ((con->pending == NULL) ||
20552 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020553 return(0);
20554
20555 /* TODO:
20556 * SPEC (src-redefine):
20557 * (6.2) "If it has no such self-reference, then all of the
20558 * following must be true:"
20559
20560 * (6.2.2) The {model group} of the model group definition which
20561 * corresponds to it per XML Representation of Model Group
20562 * Definition Schema Components (§3.7.2) must be a ·valid
20563 * restriction· of the {model group} of that model group definition
20564 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20565 */
20566 xmlSchemaCheckSRCRedefineFirst(pctxt);
20567
20568 /*
20569 * Add global components to the schemata's hash tables.
20570 */
20571 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020572
20573 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020574 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20575 nbItems = con->pending->nbItems;
20576 /*
20577 * Now that we have parsed *all* the schema document(s) and converted
20578 * them to schema components, we can resolve references, apply component
20579 * constraints, create the FSA from the content model, etc.
20580 */
20581 /*
20582 * Resolve references of..
20583 *
20584 * 1. element declarations:
20585 * - the type definition
20586 * - the substitution group affiliation
20587 * 2. simple/complex types:
20588 * - the base type definition
20589 * - the memberTypes of union types
20590 * - the itemType of list types
20591 * 3. attributes declarations and attribute uses:
20592 * - the type definition
20593 * - if an attribute use, then the attribute declaration
20594 * 4. attribute group references:
20595 * - the attribute group definition
20596 * 5. particles:
20597 * - the term of the particle (e.g. a model group)
20598 * 6. IDC key-references:
20599 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020600 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020601 */
20602 for (i = 0; i < nbItems; i++) {
20603 item = items[i];
20604 switch (item->type) {
20605 case XML_SCHEMA_TYPE_ELEMENT:
20606 xmlSchemaResolveElementReferences(
20607 (xmlSchemaElementPtr) item, pctxt);
20608 FIXHFAILURE;
20609 break;
20610 case XML_SCHEMA_TYPE_COMPLEX:
20611 case XML_SCHEMA_TYPE_SIMPLE:
20612 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020613 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020614 FIXHFAILURE;
20615 break;
20616 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020617 xmlSchemaResolveAttrTypeReferences(
20618 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020619 FIXHFAILURE;
20620 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020621 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20622 xmlSchemaResolveAttrUseReferences(
20623 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020624 FIXHFAILURE;
20625 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020626 case XML_SCHEMA_EXTRA_QNAMEREF:
20627 if ((WXS_QNAME_CAST item)->itemType ==
20628 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20629 {
20630 xmlSchemaResolveAttrGroupReferences(
20631 WXS_QNAME_CAST item, pctxt);
20632 }
20633 FIXHFAILURE;
20634 break;
20635 case XML_SCHEMA_TYPE_SEQUENCE:
20636 case XML_SCHEMA_TYPE_CHOICE:
20637 case XML_SCHEMA_TYPE_ALL:
20638 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20639 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020640 FIXHFAILURE;
20641 break;
20642 case XML_SCHEMA_TYPE_IDC_KEY:
20643 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20644 case XML_SCHEMA_TYPE_IDC_KEYREF:
20645 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020646 (xmlSchemaIDCPtr) item, pctxt);
20647 FIXHFAILURE;
20648 break;
20649 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20650 /*
20651 * Handle attribue prohibition which had a
20652 * "ref" attribute.
20653 */
20654 xmlSchemaResolveAttrUseProhibReferences(
20655 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020656 FIXHFAILURE;
20657 break;
20658 default:
20659 break;
20660 }
20661 }
20662 if (pctxt->nberrors != 0)
20663 goto exit_error;
20664
20665 /*
20666 * Now that all references are resolved we
20667 * can check for circularity of...
20668 * 1. the base axis of type definitions
20669 * 2. nested model group definitions
20670 * 3. nested attribute group definitions
20671 * TODO: check for circual substitution groups.
20672 */
20673 for (i = 0; i < nbItems; i++) {
20674 item = items[i];
20675 /*
20676 * Let's better stop on the first error here.
20677 */
20678 switch (item->type) {
20679 case XML_SCHEMA_TYPE_COMPLEX:
20680 case XML_SCHEMA_TYPE_SIMPLE:
20681 xmlSchemaCheckTypeDefCircular(
20682 (xmlSchemaTypePtr) item, pctxt);
20683 FIXHFAILURE;
20684 if (pctxt->nberrors != 0)
20685 goto exit_error;
20686 break;
20687 case XML_SCHEMA_TYPE_GROUP:
20688 xmlSchemaCheckGroupDefCircular(
20689 (xmlSchemaModelGroupDefPtr) item, pctxt);
20690 FIXHFAILURE;
20691 if (pctxt->nberrors != 0)
20692 goto exit_error;
20693 break;
20694 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20695 xmlSchemaCheckAttrGroupCircular(
20696 (xmlSchemaAttributeGroupPtr) item, pctxt);
20697 FIXHFAILURE;
20698 if (pctxt->nberrors != 0)
20699 goto exit_error;
20700 break;
20701 default:
20702 break;
20703 }
20704 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020705 if (pctxt->nberrors != 0)
20706 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020707 /*
20708 * Model group definition references:
20709 * Such a reference is reflected by a particle at the component
20710 * level. Until now the 'term' of such particles pointed
20711 * to the model group definition; this was done, in order to
20712 * ease circularity checks. Now we need to set the 'term' of
20713 * such particles to the model group of the model group definition.
20714 */
20715 for (i = 0; i < nbItems; i++) {
20716 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020717 switch (item->type) {
20718 case XML_SCHEMA_TYPE_SEQUENCE:
20719 case XML_SCHEMA_TYPE_CHOICE:
20720 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20721 WXS_MODEL_GROUP_CAST item);
20722 break;
20723 default:
20724 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020725 }
20726 }
20727 if (pctxt->nberrors != 0)
20728 goto exit_error;
20729 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020730 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020731 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020732 for (i = 0; i < nbItems; i++) {
20733 item = items[i];
20734 switch (item->type) {
20735 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20736 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20737 WXS_ATTR_GROUP_HAS_REFS(item))
20738 {
20739 xmlSchemaAttributeGroupExpandRefs(pctxt,
20740 WXS_ATTR_GROUP_CAST item);
20741 FIXHFAILURE;
20742 }
20743 break;
20744 default:
20745 break;
20746 }
20747 }
20748 if (pctxt->nberrors != 0)
20749 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020750 /*
20751 * First compute the variety of simple types. This is needed as
20752 * a seperate step, since otherwise we won't be able to detect
20753 * circular union types in all cases.
20754 */
20755 for (i = 0; i < nbItems; i++) {
20756 item = items[i];
20757 switch (item->type) {
20758 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020759 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020760 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20761 (xmlSchemaTypePtr) item);
20762 FIXHFAILURE;
20763 }
20764 break;
20765 default:
20766 break;
20767 }
20768 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020769 if (pctxt->nberrors != 0)
20770 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020771 /*
20772 * Detect circular union types. Note that this needs the variety to
20773 * be already computed.
20774 */
20775 for (i = 0; i < nbItems; i++) {
20776 item = items[i];
20777 switch (item->type) {
20778 case XML_SCHEMA_TYPE_SIMPLE:
20779 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20780 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20781 (xmlSchemaTypePtr) item);
20782 FIXHFAILURE;
20783 }
20784 break;
20785 default:
20786 break;
20787 }
20788 }
20789 if (pctxt->nberrors != 0)
20790 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020791
20792 /*
20793 * Do the complete type fixup for simple types.
20794 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020795 for (i = 0; i < nbItems; i++) {
20796 item = items[i];
20797 switch (item->type) {
20798 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020799 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20800 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20801 FIXHFAILURE;
20802 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020803 break;
20804 default:
20805 break;
20806 }
20807 }
20808 if (pctxt->nberrors != 0)
20809 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020810 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020811 * At this point we need all simple types to be builded and checked.
20812 */
20813 /*
20814 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020815 */
20816 for (i = 0; i < nbItems; i++) {
20817 item = items[i];
20818 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020819 case XML_SCHEMA_TYPE_ATTRIBUTE:
20820 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20821 FIXHFAILURE;
20822 break;
20823 default:
20824 break;
20825 }
20826 }
20827 if (pctxt->nberrors != 0)
20828 goto exit_error;
20829 /*
20830 * Apply constraints for attribute uses.
20831 */
20832 for (i = 0; i < nbItems; i++) {
20833 item = items[i];
20834 switch (item->type) {
20835 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20836 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20837 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20838 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020839 FIXHFAILURE;
20840 }
20841 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020842 default:
20843 break;
20844 }
20845 }
20846 if (pctxt->nberrors != 0)
20847 goto exit_error;
20848
20849 /*
20850 * Apply constraints for attribute group definitions.
20851 */
20852 for (i = 0; i < nbItems; i++) {
20853 item = items[i];
20854 switch (item->type) {
20855 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20856 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20857 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20858 {
20859 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20860 FIXHFAILURE;
20861 }
20862 break;
20863 default:
20864 break;
20865 }
20866 }
20867 if (pctxt->nberrors != 0)
20868 goto exit_error;
20869
20870 /*
20871 * Apply constraints for redefinitions.
20872 */
20873 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20874 xmlSchemaCheckSRCRedefineSecond(pctxt);
20875 if (pctxt->nberrors != 0)
20876 goto exit_error;
20877
20878 /*
20879 * Fixup complex types.
20880 */
20881 for (i = 0; i < nbItems; i++) {
20882 item = con->pending->items[i];
20883 switch (item->type) {
20884 case XML_SCHEMA_TYPE_COMPLEX:
20885 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20886 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20887 FIXHFAILURE;
20888 }
20889 break;
20890 default:
20891 break;
20892 }
20893 }
20894 if (pctxt->nberrors != 0)
20895 goto exit_error;
20896
20897 /*
20898 * The list could have changed, since xmlSchemaFixupComplexType()
20899 * will create particles and model groups in some cases.
20900 */
20901 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20902 nbItems = con->pending->nbItems;
20903
20904 /*
20905 * At this point all complex types need to be builded and checked.
20906 */
20907 /*
20908 * Apply some constraints for element declarations.
20909 */
20910 for (i = 0; i < nbItems; i++) {
20911 item = items[i];
20912 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020913 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020914
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020915 if ((((xmlSchemaElementPtr) item)->flags &
20916 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20917 xmlSchemaCheckElementDeclComponent(
20918 (xmlSchemaElementPtr) item, pctxt);
20919 FIXHFAILURE;
20920 }
20921 break;
20922 default:
20923 break;
20924 }
20925 }
20926 if (pctxt->nberrors != 0)
20927 goto exit_error;
20928 /*
20929 * Finally we can build the automaton from the content model of
20930 * complex types.
20931 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020932
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020933 for (i = 0; i < nbItems; i++) {
20934 item = items[i];
20935 switch (item->type) {
20936 case XML_SCHEMA_TYPE_COMPLEX:
20937 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020938 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020939 break;
20940 default:
20941 break;
20942 }
20943 }
20944 if (pctxt->nberrors != 0)
20945 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020946 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020947 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020948 */
20949 con->pending->nbItems = 0;
20950 return(0);
20951exit_error:
20952 con->pending->nbItems = 0;
20953 return(pctxt->err);
20954exit_failure:
20955 con->pending->nbItems = 0;
20956 return(-1);
20957}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020958/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020959 * xmlSchemaParse:
20960 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020961 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020962 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020963 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020964 *
20965 * Returns the internal XML Schema structure built from the resource or
20966 * NULL in case of error
20967 */
20968xmlSchemaPtr
20969xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20970{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020971 xmlSchemaPtr schema = NULL;
20972 xmlSchemaBucketPtr bucket = NULL;
20973 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020974
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020975 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020976 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020977 * the API; i.e. not automatically by the validated instance document.
20978 */
20979
Daniel Veillard4255d502002-04-16 15:50:10 +000020980 xmlSchemaInitTypes();
20981
Daniel Veillard6045c902002-10-09 21:13:59 +000020982 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020983 return (NULL);
20984
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020985 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020986 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020987 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020988 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020989
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020990 /* Create the *main* schema. */
20991 schema = xmlSchemaNewSchema(ctxt);
20992 if (schema == NULL)
20993 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020994 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020995 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020996 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020997 if (ctxt->constructor == NULL) {
20998 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
20999 if (ctxt->constructor == NULL)
21000 return(NULL);
21001 /* Take ownership of the constructor to be able to free it. */
21002 ctxt->ownsConstructor = 1;
21003 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021004 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021005 /*
21006 * Locate and add the schema document.
21007 */
21008 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21009 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21010 NULL, NULL, &bucket);
21011 if (res == -1)
21012 goto exit_failure;
21013 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021014 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021015
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021016 if (bucket == NULL) {
21017 /* TODO: Error code, actually we failed to *locate* the schema. */
21018 if (ctxt->URL)
21019 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21020 NULL, NULL,
21021 "Failed to locate the main schema resource at '%s'",
21022 ctxt->URL, NULL);
21023 else
21024 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21025 NULL, NULL,
21026 "Failed to locate the main schema resource",
21027 NULL, NULL);
21028 goto exit;
21029 }
21030 /* Set the main schema bucket. */
21031 ctxt->constructor->bucket = bucket;
21032 ctxt->targetNamespace = bucket->targetNamespace;
21033 schema->targetNamespace = bucket->targetNamespace;
21034
21035 /* Then do the parsing for good. */
21036 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21037 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021038 if (ctxt->nberrors != 0)
21039 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021040
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021041 schema->doc = bucket->doc;
21042 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021043
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021044 ctxt->schema = schema;
21045
21046 if (xmlSchemaFixupComponents(ctxt) == -1)
21047 goto exit_failure;
21048
21049 /*
21050 * TODO: This is not nice, since we cannot distinguish from the
21051 * result if there was an internal error or not.
21052 */
21053exit:
21054 if (ctxt->nberrors != 0) {
21055 if (schema) {
21056 xmlSchemaFree(schema);
21057 schema = NULL;
21058 }
21059 if (ctxt->constructor) {
21060 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21061 ctxt->constructor = NULL;
21062 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021063 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021064 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021065 ctxt->schema = NULL;
21066 return(schema);
21067exit_failure:
21068 /*
21069 * Quite verbose, but should catch internal errors, which were
21070 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021071 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021072 if (schema) {
21073 xmlSchemaFree(schema);
21074 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021075 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021076 if (ctxt->constructor) {
21077 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21078 ctxt->constructor = NULL;
21079 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021080 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021081 PERROR_INT2("xmlSchemaParse",
21082 "An internal error occured");
21083 ctxt->schema = NULL;
21084 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021085}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021086
Daniel Veillard4255d502002-04-16 15:50:10 +000021087/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021088 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021089 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021090 * @err: the error callback
21091 * @warn: the warning callback
21092 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021093 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021094 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021095 */
21096void
21097xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021098 xmlSchemaValidityErrorFunc err,
21099 xmlSchemaValidityWarningFunc warn, void *ctx)
21100{
Daniel Veillard4255d502002-04-16 15:50:10 +000021101 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021102 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021103 ctxt->error = err;
21104 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021105 ctxt->errCtxt = ctx;
21106 if (ctxt->vctxt != NULL)
21107 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21108}
21109
21110/**
21111 * xmlSchemaSetParserStructuredErrors:
21112 * @ctxt: a schema parser context
21113 * @serror: the structured error function
21114 * @ctx: the functions context
21115 *
21116 * Set the structured error callback
21117 */
21118void
21119xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21120 xmlStructuredErrorFunc serror,
21121 void *ctx)
21122{
21123 if (ctxt == NULL)
21124 return;
21125 ctxt->serror = serror;
21126 ctxt->errCtxt = ctx;
21127 if (ctxt->vctxt != NULL)
21128 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021129}
21130
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021131/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021132 * xmlSchemaGetParserErrors:
21133 * @ctxt: a XMl-Schema parser context
21134 * @err: the error callback result
21135 * @warn: the warning callback result
21136 * @ctx: contextual data for the callbacks result
21137 *
21138 * Get the callback information used to handle errors for a parser context
21139 *
21140 * Returns -1 in case of failure, 0 otherwise
21141 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021142int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021143xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021144 xmlSchemaValidityErrorFunc * err,
21145 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021146{
21147 if (ctxt == NULL)
21148 return(-1);
21149 if (err != NULL)
21150 *err = ctxt->error;
21151 if (warn != NULL)
21152 *warn = ctxt->warning;
21153 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021154 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021155 return(0);
21156}
21157
21158/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021159 * xmlSchemaFacetTypeToString:
21160 * @type: the facet type
21161 *
21162 * Convert the xmlSchemaTypeType to a char string.
21163 *
21164 * Returns the char string representation of the facet type if the
21165 * type is a facet and an "Internal Error" string otherwise.
21166 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021167static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021168xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21169{
21170 switch (type) {
21171 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021172 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021173 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021174 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021175 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021176 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021177 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021178 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021179 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021180 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021181 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021182 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021183 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021184 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021185 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021186 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021187 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021188 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021189 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021190 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021191 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021192 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021193 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021194 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021195 default:
21196 break;
21197 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021198 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021199}
21200
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021201static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021202xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21203{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021204 /*
21205 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021206 * from xsd:string.
21207 */
21208 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021209 /*
21210 * Note that we assume a whitespace of preserve for anySimpleType.
21211 */
21212 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21213 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21214 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021215 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021216 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021217 else {
21218 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021219 * For all ·atomic· datatypes other than string (and types ·derived·
21220 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021221 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021222 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021223 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021224 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021225 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021226 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021227 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021228 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021230 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021231 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021232 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021233 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021234 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21235 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21236 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21237 return (XML_SCHEMA_WHITESPACE_REPLACE);
21238 else
21239 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021240 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021241 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021242}
21243
Daniel Veillard4255d502002-04-16 15:50:10 +000021244/************************************************************************
21245 * *
21246 * Simple type validation *
21247 * *
21248 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021249
Daniel Veillard4255d502002-04-16 15:50:10 +000021250
21251/************************************************************************
21252 * *
21253 * DOM Validation code *
21254 * *
21255 ************************************************************************/
21256
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021257/**
21258 * xmlSchemaAssembleByLocation:
21259 * @pctxt: a schema parser context
21260 * @vctxt: a schema validation context
21261 * @schema: the existing schema
21262 * @node: the node that fired the assembling
21263 * @nsName: the namespace name of the new schema
21264 * @location: the location of the schema
21265 *
21266 * Expands an existing schema by an additional schema.
21267 *
21268 * Returns 0 if the new schema is correct, a positive error code
21269 * number otherwise and -1 in case of an internal or API error.
21270 */
21271static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021272xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021273 xmlSchemaPtr schema,
21274 xmlNodePtr node,
21275 const xmlChar *nsName,
21276 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021277{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021278 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021279 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021280 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021281
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021282 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021283 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021284
21285 if (vctxt->pctxt == NULL) {
21286 VERROR_INT("xmlSchemaAssembleByLocation",
21287 "no parser context available");
21288 return(-1);
21289 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021290 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021291 if (pctxt->constructor == NULL) {
21292 PERROR_INT("xmlSchemaAssembleByLocation",
21293 "no constructor");
21294 return(-1);
21295 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021296 /*
21297 * Acquire the schema document.
21298 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021299 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21300 location, node);
21301 /*
21302 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21303 * the process will automatically change this to
21304 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21305 */
21306 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21307 location, NULL, NULL, 0, node, NULL, nsName,
21308 &bucket);
21309 if (ret != 0)
21310 return(ret);
21311 if (bucket == NULL) {
21312 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021313 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021314 return(-1);
21315 }
21316 /*
21317 * The first located schema will be handled as if all other
21318 * schemas imported by XSI were imported by this first schema.
21319 */
21320 if ((bucket != NULL) &&
21321 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21322 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21323 /*
21324 * TODO: Is this handled like an import? I.e. is it not an error
21325 * if the schema cannot be located?
21326 */
21327 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21328 return(0);
21329 /*
21330 * We will reuse the parser context for every schema imported
21331 * directly via XSI. So reset the context.
21332 */
21333 pctxt->nberrors = 0;
21334 pctxt->err = 0;
21335 pctxt->doc = bucket->doc;
21336
21337 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21338 if (ret == -1) {
21339 pctxt->doc = NULL;
21340 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021341 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021342 /* Paranoid error channelling. */
21343 if ((ret == 0) && (pctxt->nberrors != 0))
21344 ret = pctxt->err;
21345 if (pctxt->nberrors == 0) {
21346 /*
21347 * Only bother to fixup pending components, if there was
21348 * no error yet.
21349 */
21350 xmlSchemaFixupComponents(pctxt);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021351 ret = pctxt->err;
21352 /*
21353 * Not nice, but we need somehow to channel the schema parser
21354 * error to the validation context.
21355 */
21356 if ((ret != 0) && (vctxt->err == 0))
21357 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021358 vctxt->nberrors += pctxt->nberrors;
21359 } else {
21360 /* Add to validation error sum. */
21361 vctxt->nberrors += pctxt->nberrors;
21362 }
21363 pctxt->doc = NULL;
21364 return(ret);
21365exit_failure:
21366 pctxt->doc = NULL;
21367 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021368}
21369
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021370static xmlSchemaAttrInfoPtr
21371xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21372 int metaType)
21373{
21374 if (vctxt->nbAttrInfos == 0)
21375 return (NULL);
21376 {
21377 int i;
21378 xmlSchemaAttrInfoPtr iattr;
21379
21380 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21381 iattr = vctxt->attrInfos[i];
21382 if (iattr->metaType == metaType)
21383 return (iattr);
21384 }
21385
21386 }
21387 return (NULL);
21388}
21389
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021390/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021391 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021392 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021393 *
21394 * Expands an existing schema by an additional schema using
21395 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21396 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21397 * must be set to 1.
21398 *
21399 * Returns 0 if the new schema is correct, a positive error code
21400 * number otherwise and -1 in case of an internal or API error.
21401 */
21402static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021403xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021404{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021405 const xmlChar *cur, *end;
21406 const xmlChar *nsname = NULL, *location;
21407 int count = 0;
21408 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021409 xmlSchemaAttrInfoPtr iattr;
21410
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021411 /*
21412 * Parse the value; we will assume an even number of values
21413 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021414 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021415 * URGENT TODO: !! This needs to work for both
21416 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21417 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021418 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021419 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21420 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21421 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021422 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021423 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21424 if (iattr == NULL)
21425 return (0);
21426 cur = iattr->value;
21427 do {
21428 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021429 /*
21430 * Get the namespace name.
21431 */
21432 while (IS_BLANK_CH(*cur))
21433 cur++;
21434 end = cur;
21435 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21436 end++;
21437 if (end == cur)
21438 break;
21439 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021440 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021441 cur = end;
21442 }
21443 /*
21444 * Get the URI.
21445 */
21446 while (IS_BLANK_CH(*cur))
21447 cur++;
21448 end = cur;
21449 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21450 end++;
21451 if (end == cur)
21452 break;
21453 count++;
21454 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021455 cur = end;
21456 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21457 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021458 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021459 VERROR_INT("xmlSchemaAssembleByXSI",
21460 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021461 return (-1);
21462 }
21463 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021464 return (ret);
21465}
21466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021467static const xmlChar *
21468xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21469 const xmlChar *prefix)
21470{
21471 if (vctxt->sax != NULL) {
21472 int i, j;
21473 xmlSchemaNodeInfoPtr inode;
21474
21475 for (i = vctxt->depth; i >= 0; i--) {
21476 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21477 inode = vctxt->elemInfos[i];
21478 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21479 if (((prefix == NULL) &&
21480 (inode->nsBindings[j] == NULL)) ||
21481 ((prefix != NULL) && xmlStrEqual(prefix,
21482 inode->nsBindings[j]))) {
21483
21484 /*
21485 * Note that the namespace bindings are already
21486 * in a string dict.
21487 */
21488 return (inode->nsBindings[j+1]);
21489 }
21490 }
21491 }
21492 }
21493 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021494#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021495 } else if (vctxt->reader != NULL) {
21496 xmlChar *nsName;
21497
21498 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21499 if (nsName != NULL) {
21500 const xmlChar *ret;
21501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021502 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21503 xmlFree(nsName);
21504 return (ret);
21505 } else
21506 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021507#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021508 } else {
21509 xmlNsPtr ns;
21510
21511 if ((vctxt->inode->node == NULL) ||
21512 (vctxt->inode->node->doc == NULL)) {
21513 VERROR_INT("xmlSchemaLookupNamespace",
21514 "no node or node's doc avaliable");
21515 return (NULL);
21516 }
21517 ns = xmlSearchNs(vctxt->inode->node->doc,
21518 vctxt->inode->node, prefix);
21519 if (ns != NULL)
21520 return (ns->href);
21521 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021522 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021523}
21524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021525/*
21526* This one works on the schema of the validation context.
21527*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021528static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021529xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21530 xmlSchemaPtr schema,
21531 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021532 const xmlChar *value,
21533 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021534 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021535{
21536 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021537
21538 if (vctxt && (vctxt->schema == NULL)) {
21539 VERROR_INT("xmlSchemaValidateNotation",
21540 "a schema is needed on the validation context");
21541 return (-1);
21542 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021543 ret = xmlValidateQName(value, 1);
21544 if (ret != 0)
21545 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021546 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021547 xmlChar *localName = NULL;
21548 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021549
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021550 localName = xmlSplitQName2(value, &prefix);
21551 if (prefix != NULL) {
21552 const xmlChar *nsName = NULL;
21553
21554 if (vctxt != NULL)
21555 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21556 else if (node != NULL) {
21557 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21558 if (ns != NULL)
21559 nsName = ns->href;
21560 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021561 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021562 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021563 return (1);
21564 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021565 if (nsName == NULL) {
21566 xmlFree(prefix);
21567 xmlFree(localName);
21568 return (1);
21569 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021570 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021571 if (valNeeded && (val != NULL)) {
21572 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21573 BAD_CAST xmlStrdup(nsName));
21574 if (*val == NULL)
21575 ret = -1;
21576 }
21577 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021578 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021579 xmlFree(prefix);
21580 xmlFree(localName);
21581 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021582 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021583 if (valNeeded && (val != NULL)) {
21584 (*val) = xmlSchemaNewNOTATIONValue(
21585 BAD_CAST xmlStrdup(value), NULL);
21586 if (*val == NULL)
21587 ret = -1;
21588 }
21589 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021590 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021591 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021593 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021594}
21595
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021596static int
21597xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21598 const xmlChar* lname,
21599 const xmlChar* nsname)
21600{
21601 int i;
21602
21603 lname = xmlDictLookup(vctxt->dict, lname, -1);
21604 if (lname == NULL)
21605 return(-1);
21606 if (nsname != NULL) {
21607 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21608 if (nsname == NULL)
21609 return(-1);
21610 }
21611 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21612 if ((vctxt->nodeQNames->items [i] == lname) &&
21613 (vctxt->nodeQNames->items[i +1] == nsname))
21614 /* Already there */
21615 return(i);
21616 }
21617 /* Add new entry. */
21618 i = vctxt->nodeQNames->nbItems;
21619 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21620 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21621 return(i);
21622}
21623
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021624/************************************************************************
21625 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021626 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021627 * *
21628 ************************************************************************/
21629
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021630/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021631 * xmlSchemaAugmentIDC:
21632 * @idcDef: the IDC definition
21633 *
21634 * Creates an augmented IDC definition item.
21635 *
21636 * Returns the item, or NULL on internal errors.
21637 */
21638static void
21639xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21640 xmlSchemaValidCtxtPtr vctxt)
21641{
21642 xmlSchemaIDCAugPtr aidc;
21643
21644 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21645 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021646 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021647 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21648 NULL);
21649 return;
21650 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021651 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021652 aidc->def = idcDef;
21653 aidc->next = NULL;
21654 if (vctxt->aidcs == NULL)
21655 vctxt->aidcs = aidc;
21656 else {
21657 aidc->next = vctxt->aidcs;
21658 vctxt->aidcs = aidc;
21659 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021660 /*
21661 * Save if we have keyrefs at all.
21662 */
21663 if ((vctxt->hasKeyrefs == 0) &&
21664 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21665 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021666}
21667
21668/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021669 * xmlSchemaIDCNewBinding:
21670 * @idcDef: the IDC definition of this binding
21671 *
21672 * Creates a new IDC binding.
21673 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021674 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021675 */
21676static xmlSchemaPSVIIDCBindingPtr
21677xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21678{
21679 xmlSchemaPSVIIDCBindingPtr ret;
21680
21681 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21682 sizeof(xmlSchemaPSVIIDCBinding));
21683 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021684 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021685 "allocating a PSVI IDC binding item", NULL);
21686 return (NULL);
21687 }
21688 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21689 ret->definition = idcDef;
21690 return (ret);
21691}
21692
21693/**
21694 * xmlSchemaIDCStoreNodeTableItem:
21695 * @vctxt: the WXS validation context
21696 * @item: the IDC node table item
21697 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021698 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021699 * They are stored to avoid copying them if IDC node-tables are merged
21700 * with corresponding parent IDC node-tables (bubbling).
21701 *
21702 * Returns 0 if succeeded, -1 on internal errors.
21703 */
21704static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021705xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021706 xmlSchemaPSVIIDCNodePtr item)
21707{
21708 /*
21709 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021710 */
21711 if (vctxt->idcNodes == NULL) {
21712 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021713 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21714 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021715 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021716 "allocating the IDC node table item list", NULL);
21717 return (-1);
21718 }
21719 vctxt->sizeIdcNodes = 20;
21720 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21721 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021722 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21723 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021724 sizeof(xmlSchemaPSVIIDCNodePtr));
21725 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021726 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021727 "re-allocating the IDC node table item list", NULL);
21728 return (-1);
21729 }
21730 }
21731 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021732
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021733 return (0);
21734}
21735
21736/**
21737 * xmlSchemaIDCStoreKey:
21738 * @vctxt: the WXS validation context
21739 * @item: the IDC key
21740 *
21741 * The validation context is used to store an IDC key.
21742 *
21743 * Returns 0 if succeeded, -1 on internal errors.
21744 */
21745static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021746xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021747 xmlSchemaPSVIIDCKeyPtr key)
21748{
21749 /*
21750 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021751 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021752 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021753 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021754 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21755 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021756 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021757 "allocating the IDC key storage list", NULL);
21758 return (-1);
21759 }
21760 vctxt->sizeIdcKeys = 40;
21761 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21762 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021763 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21764 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021765 sizeof(xmlSchemaPSVIIDCKeyPtr));
21766 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021767 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021768 "re-allocating the IDC key storage list", NULL);
21769 return (-1);
21770 }
21771 }
21772 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021773
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021774 return (0);
21775}
21776
21777/**
21778 * xmlSchemaIDCAppendNodeTableItem:
21779 * @bind: the IDC binding
21780 * @ntItem: the node-table item
21781 *
21782 * Appends the IDC node-table item to the binding.
21783 *
21784 * Returns 0 on success and -1 on internal errors.
21785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021786static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021787xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21788 xmlSchemaPSVIIDCNodePtr ntItem)
21789{
21790 if (bind->nodeTable == NULL) {
21791 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021792 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021793 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21794 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021795 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021796 "allocating an array of IDC node-table items", NULL);
21797 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021798 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021799 } else if (bind->sizeNodes <= bind->nbNodes) {
21800 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021801 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21802 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021803 sizeof(xmlSchemaPSVIIDCNodePtr));
21804 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021805 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021806 "re-allocating an array of IDC node-table items", NULL);
21807 return(-1);
21808 }
21809 }
21810 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021811 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021812}
21813
21814/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021815 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021816 * @vctxt: the WXS validation context
21817 * @matcher: the IDC matcher
21818 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021819 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021820 * of the given matcher. If none found, a new one is created
21821 * and added to the IDC table.
21822 *
21823 * Returns an IDC binding or NULL on internal errors.
21824 */
21825static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021826xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021827 xmlSchemaIDCMatcherPtr matcher)
21828{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021829 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021830
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021831 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021832
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021833 if (ielem->idcTable == NULL) {
21834 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21835 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021836 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021837 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021838 } else {
21839 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021840
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021841 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021842 do {
21843 if (bind->definition == matcher->aidc->def)
21844 return(bind);
21845 if (bind->next == NULL) {
21846 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21847 if (bind->next == NULL)
21848 return (NULL);
21849 return(bind->next);
21850 }
21851 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021852 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021853 }
21854 return (NULL);
21855}
21856
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021857static xmlSchemaItemListPtr
21858xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21859 xmlSchemaIDCMatcherPtr matcher)
21860{
21861 if (matcher->targets == NULL)
21862 matcher->targets = xmlSchemaItemListCreate();
21863 return(matcher->targets);
21864}
21865
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021866/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021867 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021868 * @key: the IDC key
21869 *
21870 * Frees an IDC key together with its compiled value.
21871 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021872static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021873xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21874{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021875 if (key->val != NULL)
21876 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021877 xmlFree(key);
21878}
21879
21880/**
21881 * xmlSchemaIDCFreeBinding:
21882 *
21883 * Frees an IDC binding. Note that the node table-items
21884 * are not freed.
21885 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021886static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021887xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21888{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021889 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021890 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021891 if (bind->dupls != NULL)
21892 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021893 xmlFree(bind);
21894}
21895
21896/**
21897 * xmlSchemaIDCFreeIDCTable:
21898 * @bind: the first IDC binding in the list
21899 *
21900 * Frees an IDC table, i.e. all the IDC bindings in the list.
21901 */
21902static void
21903xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21904{
21905 xmlSchemaPSVIIDCBindingPtr prev;
21906
21907 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021908 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021909 bind = bind->next;
21910 xmlSchemaIDCFreeBinding(prev);
21911 }
21912}
21913
21914/**
21915 * xmlSchemaIDCFreeMatcherList:
21916 * @matcher: the first IDC matcher in the list
21917 *
21918 * Frees a list of IDC matchers.
21919 */
21920static void
21921xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21922{
21923 xmlSchemaIDCMatcherPtr next;
21924
21925 while (matcher != NULL) {
21926 next = matcher->next;
21927 if (matcher->keySeqs != NULL) {
21928 int i;
21929 for (i = 0; i < matcher->sizeKeySeqs; i++)
21930 if (matcher->keySeqs[i] != NULL)
21931 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021932 xmlFree(matcher->keySeqs);
21933 }
21934 if (matcher->targets != NULL) {
21935 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21936 int i;
21937 xmlSchemaPSVIIDCNodePtr idcNode;
21938 /*
21939 * Node-table items for keyrefs are not stored globally
21940 * to the validation context, since they are not bubbled.
21941 * We need to free them here.
21942 */
21943 for (i = 0; i < matcher->targets->nbItems; i++) {
21944 idcNode =
21945 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21946 xmlFree(idcNode->keys);
21947 xmlFree(idcNode);
21948 }
21949 }
21950 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021951 }
21952 xmlFree(matcher);
21953 matcher = next;
21954 }
21955}
21956
21957/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021958 * xmlSchemaIDCAddStateObject:
21959 * @vctxt: the WXS validation context
21960 * @matcher: the IDC matcher
21961 * @sel: the XPath information
21962 * @parent: the parent "selector" state object if any
21963 * @type: "selector" or "field"
21964 *
21965 * Creates/reuses and activates state objects for the given
21966 * XPath information; if the XPath expression consists of unions,
21967 * multiple state objects are created for every unioned expression.
21968 *
21969 * Returns 0 on success and -1 on internal errors.
21970 */
21971static int
21972xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21973 xmlSchemaIDCMatcherPtr matcher,
21974 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021975 int type)
21976{
21977 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021978
21979 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021980 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021981 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021982 if (vctxt->xpathStatePool != NULL) {
21983 sto = vctxt->xpathStatePool;
21984 vctxt->xpathStatePool = sto->next;
21985 sto->next = NULL;
21986 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021987 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021988 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021989 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021990 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21991 if (sto == NULL) {
21992 xmlSchemaVErrMemory(NULL,
21993 "allocating an IDC state object", NULL);
21994 return (-1);
21995 }
21996 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21997 }
21998 /*
21999 * Add to global list.
22000 */
22001 if (vctxt->xpathStates != NULL)
22002 sto->next = vctxt->xpathStates;
22003 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022004
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022005 /*
22006 * Free the old xpath validation context.
22007 */
22008 if (sto->xpathCtxt != NULL)
22009 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22010
22011 /*
22012 * Create a new XPath (pattern) validation context.
22013 */
22014 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22015 (xmlPatternPtr) sel->xpathComp);
22016 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022017 VERROR_INT("xmlSchemaIDCAddStateObject",
22018 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022019 return (-1);
22020 }
22021 sto->type = type;
22022 sto->depth = vctxt->depth;
22023 sto->matcher = matcher;
22024 sto->sel = sel;
22025 sto->nbHistory = 0;
22026
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022027#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022028 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22029 sto->sel->xpath);
22030#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022031 return (0);
22032}
22033
22034/**
22035 * xmlSchemaXPathEvaluate:
22036 * @vctxt: the WXS validation context
22037 * @nodeType: the nodeType of the current node
22038 *
22039 * Evaluates all active XPath state objects.
22040 *
22041 * Returns the number of IC "field" state objects which resolved to
22042 * this node, 0 if none resolved and -1 on internal errors.
22043 */
22044static int
22045xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022046 xmlElementType nodeType)
22047{
22048 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022049 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022050
22051 if (vctxt->xpathStates == NULL)
22052 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022053
22054 if (nodeType == XML_ATTRIBUTE_NODE)
22055 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022056#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022057 {
22058 xmlChar *str = NULL;
22059 xmlGenericError(xmlGenericErrorContext,
22060 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022061 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22062 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022063 FREE_AND_NULL(str)
22064 }
22065#endif
22066 /*
22067 * Process all active XPath state objects.
22068 */
22069 first = vctxt->xpathStates;
22070 sto = first;
22071 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022072#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022073 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022074 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22075 sto->matcher->aidc->def->name, sto->sel->xpath);
22076 else
22077 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22078 sto->matcher->aidc->def->name, sto->sel->xpath);
22079#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022080 if (nodeType == XML_ELEMENT_NODE)
22081 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022082 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022083 else
22084 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022085 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022086
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022087 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022088 VERROR_INT("xmlSchemaXPathEvaluate",
22089 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022090 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022091 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022092 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022093 goto next_sto;
22094 /*
22095 * Full match.
22096 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022097#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022098 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022099 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022100#endif
22101 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022102 * Register a match in the state object history.
22103 */
22104 if (sto->history == NULL) {
22105 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22106 if (sto->history == NULL) {
22107 xmlSchemaVErrMemory(NULL,
22108 "allocating the state object history", NULL);
22109 return(-1);
22110 }
22111 sto->sizeHistory = 10;
22112 } else if (sto->sizeHistory <= sto->nbHistory) {
22113 sto->sizeHistory *= 2;
22114 sto->history = (int *) xmlRealloc(sto->history,
22115 sto->sizeHistory * sizeof(int));
22116 if (sto->history == NULL) {
22117 xmlSchemaVErrMemory(NULL,
22118 "re-allocating the state object history", NULL);
22119 return(-1);
22120 }
22121 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022122 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022123
22124#ifdef DEBUG_IDC
22125 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22126 vctxt->depth);
22127#endif
22128
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022129 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22130 xmlSchemaIDCSelectPtr sel;
22131 /*
22132 * Activate state objects for the IDC fields of
22133 * the IDC selector.
22134 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022135#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022136 xmlGenericError(xmlGenericErrorContext, "IDC: "
22137 "activating field states\n");
22138#endif
22139 sel = sto->matcher->aidc->def->fields;
22140 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022141 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22142 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22143 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022144 sel = sel->next;
22145 }
22146 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22147 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022148 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022149 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022150#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022151 xmlGenericError(xmlGenericErrorContext,
22152 "IDC: key found\n");
22153#endif
22154 /*
22155 * Notify that the character value of this node is
22156 * needed.
22157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022158 if (resolved == 0) {
22159 if ((vctxt->inode->flags &
22160 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22161 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22162 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022163 resolved++;
22164 }
22165next_sto:
22166 if (sto->next == NULL) {
22167 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022168 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022169 */
22170 head = first;
22171 sto = vctxt->xpathStates;
22172 } else
22173 sto = sto->next;
22174 }
22175 return (resolved);
22176}
22177
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022178static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022179xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022180 xmlChar **buf,
22181 xmlSchemaPSVIIDCKeyPtr *seq,
22182 int count)
22183{
22184 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022185 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022186
22187 *buf = xmlStrdup(BAD_CAST "[");
22188 for (i = 0; i < count; i++) {
22189 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022190 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22191 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22192 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022193 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022194 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022195 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022196 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22197 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022198 *buf = xmlStrcat(*buf, BAD_CAST "???");
22199 }
22200 if (i < count -1)
22201 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22202 else
22203 *buf = xmlStrcat(*buf, BAD_CAST "'");
22204 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022205 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022206 value = NULL;
22207 }
22208 }
22209 *buf = xmlStrcat(*buf, BAD_CAST "]");
22210
22211 return (BAD_CAST *buf);
22212}
22213
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022214/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022215 * xmlSchemaXPathPop:
22216 * @vctxt: the WXS validation context
22217 *
22218 * Pops all XPath states.
22219 *
22220 * Returns 0 on success and -1 on internal errors.
22221 */
22222static int
22223xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22224{
22225 xmlSchemaIDCStateObjPtr sto;
22226 int res;
22227
22228 if (vctxt->xpathStates == NULL)
22229 return(0);
22230 sto = vctxt->xpathStates;
22231 do {
22232 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22233 if (res == -1)
22234 return (-1);
22235 sto = sto->next;
22236 } while (sto != NULL);
22237 return(0);
22238}
22239
22240/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022241 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022242 * @vctxt: the WXS validation context
22243 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022244 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022245 *
22246 * Processes and pops the history items of the IDC state objects.
22247 * IDC key-sequences are validated/created on IDC bindings.
22248 *
22249 * Returns 0 on success and -1 on internal errors.
22250 */
22251static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022252xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022253 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022254{
22255 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022256 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022257 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022258 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022259
22260 if (vctxt->xpathStates == NULL)
22261 return (0);
22262 sto = vctxt->xpathStates;
22263
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022264#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022265 {
22266 xmlChar *str = NULL;
22267 xmlGenericError(xmlGenericErrorContext,
22268 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022269 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22270 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022271 FREE_AND_NULL(str)
22272 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022273#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022274 /*
22275 * Evaluate the state objects.
22276 */
22277 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022278 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22279 if (res == -1) {
22280 VERROR_INT("xmlSchemaXPathProcessHistory",
22281 "calling xmlStreamPop()");
22282 return (-1);
22283 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022284#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022285 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22286 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022287#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022288 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022289 goto deregister_check;
22290
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022291 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022292
22293 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022294 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022295 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022296 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022297 sto = sto->next;
22298 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022299 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022300 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022301 /*
22302 * NOTE: According to
22303 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22304 * ... the simple-content of complex types is also allowed.
22305 */
22306
22307 if (WXS_IS_COMPLEX(type)) {
22308 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22309 /*
22310 * Sanity check for complex types with simple content.
22311 */
22312 simpleType = type->contentTypeDef;
22313 if (simpleType == NULL) {
22314 VERROR_INT("xmlSchemaXPathProcessHistory",
22315 "field resolves to a CT with simple content "
22316 "but the CT is missing the ST definition");
22317 return (-1);
22318 }
22319 } else
22320 simpleType = NULL;
22321 } else
22322 simpleType = type;
22323 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022324 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022325
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022326 /*
22327 * Not qualified if the field resolves to a node of non
22328 * simple type.
22329 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022330 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022331 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022332 WXS_BASIC_CAST sto->matcher->aidc->def,
22333 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022334 "non-simple type",
22335 sto->sel->xpath,
22336 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22337 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022338 sto->nbHistory--;
22339 goto deregister_check;
22340 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022341
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022342 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022343 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022344 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022345 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022347 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022348 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022349 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022350 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022351 sto->nbHistory--;
22352 goto deregister_check;
22353 } else {
22354 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22355 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022356 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022357
22358 /*
22359 * The key will be anchored on the matcher's list of
22360 * key-sequences. The position in this list is determined
22361 * by the target node's depth relative to the matcher's
22362 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022363 *
22364 * Element Depth Pos List-entries
22365 * <scope> 0 NULL
22366 * <bar> 1 NULL
22367 * <target/> 2 2 target
22368 * <bar>
22369 * </scope>
22370 *
22371 * The size of the list is only dependant on the depth of
22372 * the tree.
22373 * An entry will be NULLed in selector_leave, i.e. when
22374 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022375 */
22376 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022377 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022378
22379 /*
22380 * Create/grow the array of key-sequences.
22381 */
22382 if (matcher->keySeqs == NULL) {
22383 if (pos > 9)
22384 matcher->sizeKeySeqs = pos * 2;
22385 else
22386 matcher->sizeKeySeqs = 10;
22387 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22388 xmlMalloc(matcher->sizeKeySeqs *
22389 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22390 if (matcher->keySeqs == NULL) {
22391 xmlSchemaVErrMemory(NULL,
22392 "allocating an array of key-sequences",
22393 NULL);
22394 return(-1);
22395 }
22396 memset(matcher->keySeqs, 0,
22397 matcher->sizeKeySeqs *
22398 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22399 } else if (pos >= matcher->sizeKeySeqs) {
22400 int i = matcher->sizeKeySeqs;
22401
22402 matcher->sizeKeySeqs *= 2;
22403 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22404 xmlRealloc(matcher->keySeqs,
22405 matcher->sizeKeySeqs *
22406 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022407 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022408 xmlSchemaVErrMemory(NULL,
22409 "reallocating an array of key-sequences",
22410 NULL);
22411 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022412 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022413 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022414 * The array needs to be NULLed.
22415 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022416 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022417 for (; i < matcher->sizeKeySeqs; i++)
22418 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022419 }
22420
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022421 /*
22422 * Get/create the key-sequence.
22423 */
22424 keySeq = matcher->keySeqs[pos];
22425 if (keySeq == NULL) {
22426 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022427 } else if (keySeq[idx] != NULL) {
22428 xmlChar *str = NULL;
22429 /*
22430 * cvc-identity-constraint:
22431 * 3 For each node in the ·target node set· all
22432 * of the {fields}, with that node as the context
22433 * node, evaluate to either an empty node-set or
22434 * a node-set with exactly one member, which must
22435 * have a simple type.
22436 *
22437 * The key was already set; report an error.
22438 */
22439 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22440 XML_SCHEMAV_CVC_IDC, NULL,
22441 WXS_BASIC_CAST matcher->aidc->def,
22442 "The XPath '%s' of a field of %s evaluates to a "
22443 "node-set with more than one member",
22444 sto->sel->xpath,
22445 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22446 FREE_AND_NULL(str);
22447 sto->nbHistory--;
22448 goto deregister_check;
22449 } else
22450 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022451
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022452create_sequence:
22453 /*
22454 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022455 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022456 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22457 matcher->aidc->def->nbFields *
22458 sizeof(xmlSchemaPSVIIDCKeyPtr));
22459 if (keySeq == NULL) {
22460 xmlSchemaVErrMemory(NULL,
22461 "allocating an IDC key-sequence", NULL);
22462 return(-1);
22463 }
22464 memset(keySeq, 0, matcher->aidc->def->nbFields *
22465 sizeof(xmlSchemaPSVIIDCKeyPtr));
22466 matcher->keySeqs[pos] = keySeq;
22467create_key:
22468 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022469 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022470 */
22471 if (key == NULL) {
22472 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22473 sizeof(xmlSchemaPSVIIDCKey));
22474 if (key == NULL) {
22475 xmlSchemaVErrMemory(NULL,
22476 "allocating a IDC key", NULL);
22477 xmlFree(keySeq);
22478 matcher->keySeqs[pos] = NULL;
22479 return(-1);
22480 }
22481 /*
22482 * Consume the compiled value.
22483 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022484 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022485 key->val = vctxt->inode->val;
22486 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022487 /*
22488 * Store the key in a global list.
22489 */
22490 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22491 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022492 return (-1);
22493 }
22494 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022495 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022496 }
22497 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022498
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022499 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022500 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022501 xmlSchemaPSVIIDCNodePtr ntItem;
22502 xmlSchemaIDCMatcherPtr matcher;
22503 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022504 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022505 int pos, i, j, nbKeys;
22506 /*
22507 * Here we have the following scenario:
22508 * An IDC 'selector' state object resolved to a target node,
22509 * during the time this target node was in the
22510 * ancestor-or-self axis, the 'field' state object(s) looked
22511 * out for matching nodes to create a key-sequence for this
22512 * target node. Now we are back to this target node and need
22513 * to put the key-sequence, together with the target node
22514 * itself, into the node-table of the corresponding IDC
22515 * binding.
22516 */
22517 matcher = sto->matcher;
22518 idc = matcher->aidc->def;
22519 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022520 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022521 /*
22522 * Check if the matcher has any key-sequences at all, plus
22523 * if it has a key-sequence for the current target node.
22524 */
22525 if ((matcher->keySeqs == NULL) ||
22526 (matcher->sizeKeySeqs <= pos)) {
22527 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22528 goto selector_key_error;
22529 else
22530 goto selector_leave;
22531 }
22532
22533 keySeq = &(matcher->keySeqs[pos]);
22534 if (*keySeq == NULL) {
22535 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22536 goto selector_key_error;
22537 else
22538 goto selector_leave;
22539 }
22540
22541 for (i = 0; i < nbKeys; i++) {
22542 if ((*keySeq)[i] == NULL) {
22543 /*
22544 * Not qualified, if not all fields did resolve.
22545 */
22546 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22547 /*
22548 * All fields of a "key" IDC must resolve.
22549 */
22550 goto selector_key_error;
22551 }
22552 goto selector_leave;
22553 }
22554 }
22555 /*
22556 * All fields did resolve.
22557 */
22558
22559 /*
22560 * 4.1 If the {identity-constraint category} is unique(/key),
22561 * then no two members of the ·qualified node set· have
22562 * ·key-sequences· whose members are pairwise equal, as
22563 * defined by Equal in [XML Schemas: Datatypes].
22564 *
22565 * Get the IDC binding from the matcher and check for
22566 * duplicate key-sequences.
22567 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022568#if 0
22569 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22570#endif
22571 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022572 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022573 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022574 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022575
22576 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022577 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022578 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022579 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022580 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022581 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022582 bkeySeq =
22583 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022584 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022585 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022586 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022587 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022588 if (res == -1) {
22589 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022590 } else if (res == 0) {
22591 /*
22592 * One of the keys differs, so the key-sequence
22593 * won't be equal; get out.
22594 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022595 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022596 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022597 }
22598 if (res == 1) {
22599 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022600 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022601 */
22602 break;
22603 }
22604 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022605 } while (i < targets->nbItems);
22606 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022607 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022608 /*
22609 * TODO: Try to report the key-sequence.
22610 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022611 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022612 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022613 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022614 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022615 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022616 (*keySeq), nbKeys),
22617 xmlSchemaGetIDCDesignation(&strB, idc));
22618 FREE_AND_NULL(str);
22619 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022620 goto selector_leave;
22621 }
22622 }
22623 /*
22624 * Add a node-table item to the IDC binding.
22625 */
22626 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22627 sizeof(xmlSchemaPSVIIDCNode));
22628 if (ntItem == NULL) {
22629 xmlSchemaVErrMemory(NULL,
22630 "allocating an IDC node-table item", NULL);
22631 xmlFree(*keySeq);
22632 *keySeq = NULL;
22633 return(-1);
22634 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022635 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022636
22637 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022638 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022639 */
22640 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22641 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22642 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022643 xmlFree(*keySeq);
22644 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022645 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022646 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022647 ntItem->nodeQNameID = -1;
22648 } else {
22649 /*
22650 * Save a cached QName for this node on the IDC node, to be
22651 * able to report it, even if the node is not saved.
22652 */
22653 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22654 vctxt->inode->localName, vctxt->inode->nsName);
22655 if (ntItem->nodeQNameID == -1) {
22656 xmlFree(ntItem);
22657 xmlFree(*keySeq);
22658 *keySeq = NULL;
22659 return (-1);
22660 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022661 }
22662 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022663 * Init the node-table item: Save the node, position and
22664 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022665 */
22666 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022667 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022668 ntItem->keys = *keySeq;
22669 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022670#if 0
22671 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22672#endif
22673 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022674 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22675 /*
22676 * Free the item, since keyref items won't be
22677 * put on a global list.
22678 */
22679 xmlFree(ntItem->keys);
22680 xmlFree(ntItem);
22681 }
22682 return (-1);
22683 }
22684
22685 goto selector_leave;
22686selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022687 {
22688 xmlChar *str = NULL;
22689 /*
22690 * 4.2.1 (KEY) The ·target node set· and the
22691 * ·qualified node set· are equal, that is, every
22692 * member of the ·target node set· is also a member
22693 * of the ·qualified node set· and vice versa.
22694 */
22695 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22696 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022697 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022698 "Not all fields of %s evaluate to a node",
22699 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22700 FREE_AND_NULL(str);
22701 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022702selector_leave:
22703 /*
22704 * Free the key-sequence if not added to the IDC table.
22705 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022706 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022707 xmlFree(*keySeq);
22708 *keySeq = NULL;
22709 }
22710 } /* if selector */
22711
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022712 sto->nbHistory--;
22713
22714deregister_check:
22715 /*
22716 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022717 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022718 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022719#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022720 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22721 sto->sel->xpath);
22722#endif
22723 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022724 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022725 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022726 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022727 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022728 nextsto = sto->next;
22729 /*
22730 * Unlink from the list of active XPath state objects.
22731 */
22732 vctxt->xpathStates = sto->next;
22733 sto->next = vctxt->xpathStatePool;
22734 /*
22735 * Link it to the pool of reusable state objects.
22736 */
22737 vctxt->xpathStatePool = sto;
22738 sto = nextsto;
22739 } else
22740 sto = sto->next;
22741 } /* while (sto != NULL) */
22742 return (0);
22743}
22744
22745/**
22746 * xmlSchemaIDCRegisterMatchers:
22747 * @vctxt: the WXS validation context
22748 * @elemDecl: the element declaration
22749 *
22750 * Creates helper objects to evaluate IDC selectors/fields
22751 * successively.
22752 *
22753 * Returns 0 if OK and -1 on internal errors.
22754 */
22755static int
22756xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22757 xmlSchemaElementPtr elemDecl)
22758{
22759 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22760 xmlSchemaIDCPtr idc, refIdc;
22761 xmlSchemaIDCAugPtr aidc;
22762
22763 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22764 if (idc == NULL)
22765 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022766
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022767#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022768 {
22769 xmlChar *str = NULL;
22770 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022771 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022772 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22773 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022774 FREE_AND_NULL(str)
22775 }
22776#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022777 if (vctxt->inode->idcMatchers != NULL) {
22778 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22779 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022780 return (-1);
22781 }
22782 do {
22783 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22784 /*
22785 * Since IDCs bubbles are expensive we need to know the
22786 * depth at which the bubbles should stop; this will be
22787 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022788 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022789 * be -1, indicating that no bubbles are needed.
22790 */
22791 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22792 if (refIdc != NULL) {
22793 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022794 * Remember that we have keyrefs on this node.
22795 */
22796 vctxt->inode->hasKeyrefs = 1;
22797 /*
22798 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022799 */
22800 aidc = vctxt->aidcs;
22801 while (aidc != NULL) {
22802 if (aidc->def == refIdc)
22803 break;
22804 aidc = aidc->next;
22805 }
22806 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022807 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022808 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022809 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022810 return (-1);
22811 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022812 if ((aidc->keyrefDepth == -1) ||
22813 (vctxt->depth < aidc->keyrefDepth))
22814 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022815 }
22816 }
22817 /*
22818 * Lookup the augmented IDC item for the IDC definition.
22819 */
22820 aidc = vctxt->aidcs;
22821 while (aidc != NULL) {
22822 if (aidc->def == idc)
22823 break;
22824 aidc = aidc->next;
22825 }
22826 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022827 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22828 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022829 return (-1);
22830 }
22831 /*
22832 * Create an IDC matcher for every IDC definition.
22833 */
22834 matcher = (xmlSchemaIDCMatcherPtr)
22835 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22836 if (matcher == NULL) {
22837 xmlSchemaVErrMemory(vctxt,
22838 "allocating an IDC matcher", NULL);
22839 return (-1);
22840 }
22841 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22842 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022843 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022844 else
22845 last->next = matcher;
22846 last = matcher;
22847
22848 matcher->type = IDC_MATCHER;
22849 matcher->depth = vctxt->depth;
22850 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022851 matcher->idcType = aidc->def->type;
22852#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022853 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22854#endif
22855 /*
22856 * Init the automaton state object.
22857 */
22858 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022859 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022860 return (-1);
22861
22862 idc = idc->next;
22863 } while (idc != NULL);
22864 return (0);
22865}
22866
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022867static int
22868xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22869 xmlSchemaNodeInfoPtr ielem)
22870{
22871 xmlSchemaPSVIIDCBindingPtr bind;
22872 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22873 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22874 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22875
22876 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22877 /* vctxt->createIDCNodeTables */
22878 while (matcher != NULL) {
22879 /*
22880 * Skip keyref IDCs and empty IDC target-lists.
22881 */
22882 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22883 WXS_ILIST_IS_EMPTY(matcher->targets))
22884 {
22885 matcher = matcher->next;
22886 continue;
22887 }
22888 /*
22889 * If we _want_ the IDC node-table to be created in any case
22890 * then do so. Otherwise create them only if keyrefs need them.
22891 */
22892 if ((! vctxt->createIDCNodeTables) &&
22893 ((matcher->aidc->keyrefDepth == -1) ||
22894 (matcher->aidc->keyrefDepth > vctxt->depth)))
22895 {
22896 matcher = matcher->next;
22897 continue;
22898 }
22899 /*
22900 * Get/create the IDC binding on this element for the IDC definition.
22901 */
22902 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22903
22904 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22905 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22906 nbDupls = bind->dupls->nbItems;
22907 } else {
22908 dupls = NULL;
22909 nbDupls = 0;
22910 }
22911 if (bind->nodeTable != NULL) {
22912 nbNodeTable = bind->nbNodes;
22913 } else {
22914 nbNodeTable = 0;
22915 }
22916
22917 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22918 /*
22919 * Transfer all IDC target-nodes to the IDC node-table.
22920 */
22921 bind->nodeTable =
22922 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22923 bind->sizeNodes = matcher->targets->sizeItems;
22924 bind->nbNodes = matcher->targets->nbItems;
22925
22926 matcher->targets->items = NULL;
22927 matcher->targets->sizeItems = 0;
22928 matcher->targets->nbItems = 0;
22929 } else {
22930 /*
22931 * Compare the key-sequences and add to the IDC node-table.
22932 */
22933 nbTargets = matcher->targets->nbItems;
22934 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22935 nbFields = matcher->aidc->def->nbFields;
22936 i = 0;
22937 do {
22938 keys = targets[i]->keys;
22939 if (nbDupls) {
22940 /*
22941 * Search in already found duplicates first.
22942 */
22943 j = 0;
22944 do {
22945 if (nbFields == 1) {
22946 res = xmlSchemaAreValuesEqual(keys[0]->val,
22947 dupls[j]->keys[0]->val);
22948 if (res == -1)
22949 goto internal_error;
22950 if (res == 1) {
22951 /*
22952 * Equal key-sequence.
22953 */
22954 goto next_target;
22955 }
22956 } else {
22957 res = 0;
22958 ntkeys = dupls[j]->keys;
22959 for (k = 0; k < nbFields; k++) {
22960 res = xmlSchemaAreValuesEqual(keys[k]->val,
22961 ntkeys[k]->val);
22962 if (res == -1)
22963 goto internal_error;
22964 if (res == 0) {
22965 /*
22966 * One of the keys differs.
22967 */
22968 break;
22969 }
22970 }
22971 if (res == 1) {
22972 /*
22973 * Equal key-sequence found.
22974 */
22975 goto next_target;
22976 }
22977 }
22978 j++;
22979 } while (j < nbDupls);
22980 }
22981 if (nbNodeTable) {
22982 j = 0;
22983 do {
22984 if (nbFields == 1) {
22985 res = xmlSchemaAreValuesEqual(keys[0]->val,
22986 bind->nodeTable[j]->keys[0]->val);
22987 if (res == -1)
22988 goto internal_error;
22989 if (res == 0) {
22990 /*
22991 * The key-sequence differs.
22992 */
22993 goto next_node_table_entry;
22994 }
22995 } else {
22996 res = 0;
22997 ntkeys = bind->nodeTable[j]->keys;
22998 for (k = 0; k < nbFields; k++) {
22999 res = xmlSchemaAreValuesEqual(keys[k]->val,
23000 ntkeys[k]->val);
23001 if (res == -1)
23002 goto internal_error;
23003 if (res == 0) {
23004 /*
23005 * One of the keys differs.
23006 */
23007 goto next_node_table_entry;
23008 }
23009 }
23010 }
23011 /*
23012 * Add the duplicate to the list of duplicates.
23013 */
23014 if (bind->dupls == NULL) {
23015 bind->dupls = xmlSchemaItemListCreate();
23016 if (bind->dupls == NULL)
23017 goto internal_error;
23018 }
23019 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23020 goto internal_error;
23021 /*
23022 * Remove the duplicate entry from the IDC node-table.
23023 */
23024 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23025 bind->nbNodes--;
23026
23027 goto next_target;
23028
23029next_node_table_entry:
23030 j++;
23031 } while (j < nbNodeTable);
23032 }
23033 /*
23034 * If everything is fine, then add the IDC target-node to
23035 * the IDC node-table.
23036 */
23037 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23038 goto internal_error;
23039
23040next_target:
23041 i++;
23042 } while (i < nbTargets);
23043 }
23044 matcher = matcher->next;
23045 }
23046 return(0);
23047
23048internal_error:
23049 return(-1);
23050}
23051
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023052/**
23053 * xmlSchemaBubbleIDCNodeTables:
23054 * @depth: the current tree depth
23055 *
23056 * Merges IDC bindings of an element at @depth into the corresponding IDC
23057 * bindings of its parent element. If a duplicate note-table entry is found,
23058 * both, the parent node-table entry and child entry are discarded from the
23059 * node-table of the parent.
23060 *
23061 * Returns 0 if OK and -1 on internal errors.
23062 */
23063static int
23064xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23065{
23066 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023067 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23068 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023069 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023070 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023071
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023072 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023073 if (bind == NULL) {
23074 /* Fine, no table, no bubbles. */
23075 return (0);
23076 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023077
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023078 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23079 /*
23080 * Walk all bindings; create new or add to existing bindings.
23081 * Remove duplicate key-sequences.
23082 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023083 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023084
23085 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23086 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023087 /*
23088 * Check if the key/unique IDC table needs to be bubbled.
23089 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023090 if (! vctxt->createIDCNodeTables) {
23091 aidc = vctxt->aidcs;
23092 do {
23093 if (aidc->def == bind->definition) {
23094 if ((aidc->keyrefDepth == -1) ||
23095 (aidc->keyrefDepth >= vctxt->depth)) {
23096 goto next_binding;
23097 }
23098 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023099 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023100 aidc = aidc->next;
23101 } while (aidc != NULL);
23102 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023103
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023104 if (parTable != NULL)
23105 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023106 /*
23107 * Search a matching parent binding for the
23108 * IDC definition.
23109 */
23110 while (parBind != NULL) {
23111 if (parBind->definition == bind->definition)
23112 break;
23113 parBind = parBind->next;
23114 }
23115
23116 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023117 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023118 * Compare every node-table entry of the child node,
23119 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023120 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023121 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023122
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023123 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23124 oldDupls = parBind->dupls->nbItems;
23125 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23126 } else {
23127 dupls = NULL;
23128 oldDupls = 0;
23129 }
23130
23131 parNodes = parBind->nodeTable;
23132 nbFields = bind->definition->nbFields;
23133
23134 for (i = 0; i < bind->nbNodes; i++) {
23135 node = bind->nodeTable[i];
23136 if (node == NULL)
23137 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023138 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023139 * ...with every key-sequence of the parent node, already
23140 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023141 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023142 if (oldDupls) {
23143 j = 0;
23144 while (j < oldDupls) {
23145 if (nbFields == 1) {
23146 ret = xmlSchemaAreValuesEqual(
23147 node->keys[0]->val,
23148 dupls[j]->keys[0]->val);
23149 if (ret == -1)
23150 goto internal_error;
23151 if (ret == 0) {
23152 j++;
23153 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023154 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023155 } else {
23156 parNode = dupls[j];
23157 for (k = 0; k < nbFields; k++) {
23158 ret = xmlSchemaAreValuesEqual(
23159 node->keys[k]->val,
23160 parNode->keys[k]->val);
23161 if (ret == -1)
23162 goto internal_error;
23163 if (ret == 0)
23164 break;
23165 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023166 }
23167 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023168 /* Duplicate found. */
23169 break;
23170 j++;
23171 }
23172 if (j != oldDupls) {
23173 /* Duplicate found. Skip this entry. */
23174 continue;
23175 }
23176 }
23177 /*
23178 * ... and with every key-sequence of the parent node.
23179 */
23180 if (oldNum) {
23181 j = 0;
23182 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023183 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023184 if (nbFields == 1) {
23185 ret = xmlSchemaAreValuesEqual(
23186 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023187 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023188 if (ret == -1)
23189 goto internal_error;
23190 if (ret == 0) {
23191 j++;
23192 continue;
23193 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023194 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023195 for (k = 0; k < nbFields; k++) {
23196 ret = xmlSchemaAreValuesEqual(
23197 node->keys[k]->val,
23198 parNode->keys[k]->val);
23199 if (ret == -1)
23200 goto internal_error;
23201 if (ret == 0)
23202 break;
23203 }
23204 }
23205 if (ret == 1)
23206 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023207 break;
23208 j++;
23209 }
23210 if (j != oldNum) {
23211 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023212 * Handle duplicates. Move the duplicate in
23213 * the parent's node-table to the list of
23214 * duplicates.
23215 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023216 oldNum--;
23217 parBind->nbNodes--;
23218 /*
23219 * Move last old item to pos of duplicate.
23220 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023221 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023222
23223 if (parBind->nbNodes != oldNum) {
23224 /*
23225 * If new items exist, move last new item to
23226 * last of old items.
23227 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023228 parNodes[oldNum] =
23229 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023230 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023231 if (parBind->dupls == NULL) {
23232 parBind->dupls = xmlSchemaItemListCreate();
23233 if (parBind->dupls == NULL)
23234 goto internal_error;
23235 }
23236 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023237 } else {
23238 /*
23239 * Add the node-table entry (node and key-sequence) of
23240 * the child node to the node table of the parent node.
23241 */
23242 if (parBind->nodeTable == NULL) {
23243 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023244 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023245 if (parBind->nodeTable == NULL) {
23246 xmlSchemaVErrMemory(NULL,
23247 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023248 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023249 }
23250 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023251 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023252 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023253 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23254 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23255 sizeof(xmlSchemaPSVIIDCNodePtr));
23256 if (parBind->nodeTable == NULL) {
23257 xmlSchemaVErrMemory(NULL,
23258 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023259 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023260 }
23261 }
23262 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023263 /*
23264 * Append the new node-table entry to the 'new node-table
23265 * entries' section.
23266 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023267 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023268 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023269
23270 }
23271
23272 }
23273 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023274 /*
23275 * No binding for the IDC was found: create a new one and
23276 * copy all node-tables.
23277 */
23278 parBind = xmlSchemaIDCNewBinding(bind->definition);
23279 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023280 goto internal_error;
23281
23282 /*
23283 * TODO: Hmm, how to optimize the initial number of
23284 * allocated entries?
23285 */
23286 if (bind->nbNodes != 0) {
23287 /*
23288 * Add all IDC node-table entries.
23289 */
23290 if (! vctxt->psviExposeIDCNodeTables) {
23291 /*
23292 * Just move the entries.
23293 * NOTE: this is quite save here, since
23294 * all the keyref lookups have already been
23295 * performed.
23296 */
23297 parBind->nodeTable = bind->nodeTable;
23298 bind->nodeTable = NULL;
23299 parBind->sizeNodes = bind->sizeNodes;
23300 bind->sizeNodes = 0;
23301 parBind->nbNodes = bind->nbNodes;
23302 bind->nbNodes = 0;
23303 } else {
23304 /*
23305 * Copy the entries.
23306 */
23307 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23308 xmlMalloc(bind->nbNodes *
23309 sizeof(xmlSchemaPSVIIDCNodePtr));
23310 if (parBind->nodeTable == NULL) {
23311 xmlSchemaVErrMemory(NULL,
23312 "allocating an array of IDC node-table "
23313 "items", NULL);
23314 xmlSchemaIDCFreeBinding(parBind);
23315 goto internal_error;
23316 }
23317 parBind->sizeNodes = bind->nbNodes;
23318 parBind->nbNodes = bind->nbNodes;
23319 memcpy(parBind->nodeTable, bind->nodeTable,
23320 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23321 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023322 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023323 if (bind->dupls) {
23324 /*
23325 * Move the duplicates.
23326 */
23327 if (parBind->dupls != NULL)
23328 xmlSchemaItemListFree(parBind->dupls);
23329 parBind->dupls = bind->dupls;
23330 bind->dupls = NULL;
23331 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023332 if (*parTable == NULL)
23333 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023334 else {
23335 parBind->next = *parTable;
23336 *parTable = parBind;
23337 }
23338 }
23339
23340next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023341 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023342 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023343 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023344
23345internal_error:
23346 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023347}
23348
23349/**
23350 * xmlSchemaCheckCVCIDCKeyRef:
23351 * @vctxt: the WXS validation context
23352 * @elemDecl: the element declaration
23353 *
23354 * Check the cvc-idc-keyref constraints.
23355 */
23356static int
23357xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23358{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023359 xmlSchemaIDCMatcherPtr matcher;
23360 xmlSchemaPSVIIDCBindingPtr bind;
23361
23362 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023363 /*
23364 * Find a keyref.
23365 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023366 while (matcher != NULL) {
23367 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23368 matcher->targets &&
23369 matcher->targets->nbItems)
23370 {
23371 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023372 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023373 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023374
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023375 nbFields = matcher->aidc->def->nbFields;
23376
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023377 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023378 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023380 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023381 while (bind != NULL) {
23382 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023383 bind->definition)
23384 break;
23385 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023386 }
23387 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023388 /*
23389 * Search for a matching key-sequences.
23390 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023391 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023392 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023393 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023394 if (bind != NULL) {
23395 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023396 for (j = 0; j < bind->nbNodes; j++) {
23397 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023398 for (k = 0; k < nbFields; k++) {
23399 res = xmlSchemaAreValuesEqual(keys[k]->val,
23400 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023401 if (res == 0)
23402 break;
23403 else if (res == -1) {
23404 return (-1);
23405 }
23406 }
23407 if (res == 1) {
23408 /*
23409 * Match found.
23410 */
23411 break;
23412 }
23413 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023414 if ((res == 0) && hasDupls) {
23415 /*
23416 * Search in duplicates
23417 */
23418 for (j = 0; j < bind->dupls->nbItems; j++) {
23419 keys = ((xmlSchemaPSVIIDCNodePtr)
23420 bind->dupls->items[j])->keys;
23421 for (k = 0; k < nbFields; k++) {
23422 res = xmlSchemaAreValuesEqual(keys[k]->val,
23423 refKeys[k]->val);
23424 if (res == 0)
23425 break;
23426 else if (res == -1) {
23427 return (-1);
23428 }
23429 }
23430 if (res == 1) {
23431 /*
23432 * Match in duplicates found.
23433 */
23434 xmlChar *str = NULL, *strB = NULL;
23435 xmlSchemaKeyrefErr(vctxt,
23436 XML_SCHEMAV_CVC_IDC, refNode,
23437 (xmlSchemaTypePtr) matcher->aidc->def,
23438 "More than one match found for "
23439 "key-sequence %s of keyref '%s'",
23440 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23441 refNode->keys, nbFields),
23442 xmlSchemaGetComponentQName(&strB,
23443 matcher->aidc->def));
23444 FREE_AND_NULL(str);
23445 FREE_AND_NULL(strB);
23446 break;
23447 }
23448 }
23449 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023450 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023451
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023452 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023453 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023454 xmlSchemaKeyrefErr(vctxt,
23455 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023456 (xmlSchemaTypePtr) matcher->aidc->def,
23457 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023458 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023459 refNode->keys, nbFields),
23460 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023461 FREE_AND_NULL(str);
23462 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023463 }
23464 }
23465 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023466 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023467 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023468 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023469 return (0);
23470}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023471
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023472/************************************************************************
23473 * *
23474 * XML Reader validation code *
23475 * *
23476 ************************************************************************/
23477
23478static xmlSchemaAttrInfoPtr
23479xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023480{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023481 xmlSchemaAttrInfoPtr iattr;
23482 /*
23483 * Grow/create list of attribute infos.
23484 */
23485 if (vctxt->attrInfos == NULL) {
23486 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23487 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23488 vctxt->sizeAttrInfos = 1;
23489 if (vctxt->attrInfos == NULL) {
23490 xmlSchemaVErrMemory(vctxt,
23491 "allocating attribute info list", NULL);
23492 return (NULL);
23493 }
23494 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23495 vctxt->sizeAttrInfos++;
23496 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23497 xmlRealloc(vctxt->attrInfos,
23498 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23499 if (vctxt->attrInfos == NULL) {
23500 xmlSchemaVErrMemory(vctxt,
23501 "re-allocating attribute info list", NULL);
23502 return (NULL);
23503 }
23504 } else {
23505 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23506 if (iattr->localName != NULL) {
23507 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23508 "attr info not cleared");
23509 return (NULL);
23510 }
23511 iattr->nodeType = XML_ATTRIBUTE_NODE;
23512 return (iattr);
23513 }
23514 /*
23515 * Create an attribute info.
23516 */
23517 iattr = (xmlSchemaAttrInfoPtr)
23518 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23519 if (iattr == NULL) {
23520 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23521 return (NULL);
23522 }
23523 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23524 iattr->nodeType = XML_ATTRIBUTE_NODE;
23525 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23526
23527 return (iattr);
23528}
23529
23530static int
23531xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23532 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023533 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023534 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023535 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023536 int ownedNames,
23537 xmlChar *value,
23538 int ownedValue)
23539{
23540 xmlSchemaAttrInfoPtr attr;
23541
23542 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23543 if (attr == NULL) {
23544 VERROR_INT("xmlSchemaPushAttribute",
23545 "calling xmlSchemaGetFreshAttrInfo()");
23546 return (-1);
23547 }
23548 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023549 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023550 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23551 attr->localName = localName;
23552 attr->nsName = nsName;
23553 if (ownedNames)
23554 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23555 /*
23556 * Evaluate if it's an XSI attribute.
23557 */
23558 if (nsName != NULL) {
23559 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23560 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23561 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23562 }
23563 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23564 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23565 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23566 }
23567 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23568 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23569 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23570 }
23571 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23572 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23573 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23574 }
23575 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23576 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23577 }
23578 }
23579 attr->value = value;
23580 if (ownedValue)
23581 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23582 if (attr->metaType != 0)
23583 attr->state = XML_SCHEMAS_ATTR_META;
23584 return (0);
23585}
23586
23587static void
23588xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23589{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023590 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023591 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023592 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23593 FREE_AND_NULL(ielem->localName);
23594 FREE_AND_NULL(ielem->nsName);
23595 } else {
23596 ielem->localName = NULL;
23597 ielem->nsName = NULL;
23598 }
23599 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23600 FREE_AND_NULL(ielem->value);
23601 } else {
23602 ielem->value = NULL;
23603 }
23604 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023605 /*
23606 * PSVI TODO: Be careful not to free it when the value is
23607 * exposed via PSVI.
23608 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023609 xmlSchemaFreeValue(ielem->val);
23610 ielem->val = NULL;
23611 }
23612 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023613 /*
23614 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23615 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023616 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23617 ielem->idcMatchers = NULL;
23618 }
23619 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023620 /*
23621 * OPTIMIZE TODO: Use a pool of IDC tables??.
23622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023623 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23624 ielem->idcTable = NULL;
23625 }
23626 if (ielem->regexCtxt != NULL) {
23627 xmlRegFreeExecCtxt(ielem->regexCtxt);
23628 ielem->regexCtxt = NULL;
23629 }
23630 if (ielem->nsBindings != NULL) {
23631 xmlFree((xmlChar **)ielem->nsBindings);
23632 ielem->nsBindings = NULL;
23633 ielem->nbNsBindings = 0;
23634 ielem->sizeNsBindings = 0;
23635 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023636}
23637
23638/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023639 * xmlSchemaGetFreshElemInfo:
23640 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023641 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023642 * Creates/reuses and initializes the element info item for
23643 * the currect tree depth.
23644 *
23645 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023646 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023647static xmlSchemaNodeInfoPtr
23648xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023649{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023650 xmlSchemaNodeInfoPtr info = NULL;
23651
23652 if (vctxt->depth > vctxt->sizeElemInfos) {
23653 VERROR_INT("xmlSchemaGetFreshElemInfo",
23654 "inconsistent depth encountered");
23655 return (NULL);
23656 }
23657 if (vctxt->elemInfos == NULL) {
23658 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23659 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23660 if (vctxt->elemInfos == NULL) {
23661 xmlSchemaVErrMemory(vctxt,
23662 "allocating the element info array", NULL);
23663 return (NULL);
23664 }
23665 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23666 vctxt->sizeElemInfos = 10;
23667 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23668 int i = vctxt->sizeElemInfos;
23669
23670 vctxt->sizeElemInfos *= 2;
23671 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23672 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23673 sizeof(xmlSchemaNodeInfoPtr));
23674 if (vctxt->elemInfos == NULL) {
23675 xmlSchemaVErrMemory(vctxt,
23676 "re-allocating the element info array", NULL);
23677 return (NULL);
23678 }
23679 /*
23680 * We need the new memory to be NULLed.
23681 * TODO: Use memset instead?
23682 */
23683 for (; i < vctxt->sizeElemInfos; i++)
23684 vctxt->elemInfos[i] = NULL;
23685 } else
23686 info = vctxt->elemInfos[vctxt->depth];
23687
23688 if (info == NULL) {
23689 info = (xmlSchemaNodeInfoPtr)
23690 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23691 if (info == NULL) {
23692 xmlSchemaVErrMemory(vctxt,
23693 "allocating an element info", NULL);
23694 return (NULL);
23695 }
23696 vctxt->elemInfos[vctxt->depth] = info;
23697 } else {
23698 if (info->localName != NULL) {
23699 VERROR_INT("xmlSchemaGetFreshElemInfo",
23700 "elem info has not been cleared");
23701 return (NULL);
23702 }
23703 }
23704 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23705 info->nodeType = XML_ELEMENT_NODE;
23706 info->depth = vctxt->depth;
23707
23708 return (info);
23709}
23710
23711#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23712#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23713#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23714
23715static int
23716xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23717 xmlNodePtr node,
23718 xmlSchemaTypePtr type,
23719 xmlSchemaValType valType,
23720 const xmlChar * value,
23721 xmlSchemaValPtr val,
23722 unsigned long length,
23723 int fireErrors)
23724{
23725 int ret, error = 0;
23726
23727 xmlSchemaTypePtr tmpType;
23728 xmlSchemaFacetLinkPtr facetLink;
23729 xmlSchemaFacetPtr facet;
23730 unsigned long len = 0;
23731 xmlSchemaWhitespaceValueType ws;
23732
23733 /*
23734 * In Libxml2, derived built-in types have currently no explicit facets.
23735 */
23736 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023737 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023738
23739 /*
23740 * NOTE: Do not jump away, if the facetSet of the given type is
23741 * empty: until now, "pattern" and "enumeration" facets of the
23742 * *base types* need to be checked as well.
23743 */
23744 if (type->facetSet == NULL)
23745 goto pattern_and_enum;
23746
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023747 if (! WXS_IS_ATOMIC(type)) {
23748 if (WXS_IS_LIST(type))
23749 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023750 else
23751 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023752 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023753 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023754 * Whitespace handling is only of importance for string-based
23755 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023756 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023757 tmpType = xmlSchemaGetPrimitiveType(type);
23758 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023759 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023760 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23761 } else
23762 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23763 /*
23764 * If the value was not computed (for string or
23765 * anySimpleType based types), then use the provided
23766 * type.
23767 */
23768 if (val == NULL)
23769 valType = valType;
23770 else
23771 valType = xmlSchemaGetValType(val);
23772
23773 ret = 0;
23774 for (facetLink = type->facetSet; facetLink != NULL;
23775 facetLink = facetLink->next) {
23776 /*
23777 * Skip the pattern "whiteSpace": it is used to
23778 * format the character content beforehand.
23779 */
23780 switch (facetLink->facet->type) {
23781 case XML_SCHEMA_FACET_WHITESPACE:
23782 case XML_SCHEMA_FACET_PATTERN:
23783 case XML_SCHEMA_FACET_ENUMERATION:
23784 continue;
23785 case XML_SCHEMA_FACET_LENGTH:
23786 case XML_SCHEMA_FACET_MINLENGTH:
23787 case XML_SCHEMA_FACET_MAXLENGTH:
23788 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23789 valType, value, val, &len, ws);
23790 break;
23791 default:
23792 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23793 valType, value, val, ws);
23794 break;
23795 }
23796 if (ret < 0) {
23797 AERROR_INT("xmlSchemaValidateFacets",
23798 "validating against a atomic type facet");
23799 return (-1);
23800 } else if (ret > 0) {
23801 if (fireErrors)
23802 xmlSchemaFacetErr(actxt, ret, node,
23803 value, len, type, facetLink->facet, NULL, NULL, NULL);
23804 else
23805 return (ret);
23806 if (error == 0)
23807 error = ret;
23808 }
23809 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023810 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023811
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023812WXS_IS_LIST:
23813 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023814 goto pattern_and_enum;
23815 /*
23816 * "length", "minLength" and "maxLength" of list types.
23817 */
23818 ret = 0;
23819 for (facetLink = type->facetSet; facetLink != NULL;
23820 facetLink = facetLink->next) {
23821
23822 switch (facetLink->facet->type) {
23823 case XML_SCHEMA_FACET_LENGTH:
23824 case XML_SCHEMA_FACET_MINLENGTH:
23825 case XML_SCHEMA_FACET_MAXLENGTH:
23826 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23827 value, length, NULL);
23828 break;
23829 default:
23830 continue;
23831 }
23832 if (ret < 0) {
23833 AERROR_INT("xmlSchemaValidateFacets",
23834 "validating against a list type facet");
23835 return (-1);
23836 } else if (ret > 0) {
23837 if (fireErrors)
23838 xmlSchemaFacetErr(actxt, ret, node,
23839 value, length, type, facetLink->facet, NULL, NULL, NULL);
23840 else
23841 return (ret);
23842 if (error == 0)
23843 error = ret;
23844 }
23845 ret = 0;
23846 }
23847
23848pattern_and_enum:
23849 if (error >= 0) {
23850 int found = 0;
23851 /*
23852 * Process enumerations. Facet values are in the value space
23853 * of the defining type's base type. This seems to be a bug in the
23854 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23855 * Only the first set of enumerations in the ancestor-or-self axis
23856 * is used for validation.
23857 */
23858 ret = 0;
23859 tmpType = type;
23860 do {
23861 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23862 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23863 continue;
23864 found = 1;
23865 ret = xmlSchemaAreValuesEqual(facet->val, val);
23866 if (ret == 1)
23867 break;
23868 else if (ret < 0) {
23869 AERROR_INT("xmlSchemaValidateFacets",
23870 "validating against an enumeration facet");
23871 return (-1);
23872 }
23873 }
23874 if (ret != 0)
23875 break;
23876 tmpType = tmpType->baseType;
23877 } while ((tmpType != NULL) &&
23878 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23879 if (found && (ret == 0)) {
23880 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23881 if (fireErrors) {
23882 xmlSchemaFacetErr(actxt, ret, node,
23883 value, 0, type, NULL, NULL, NULL, NULL);
23884 } else
23885 return (ret);
23886 if (error == 0)
23887 error = ret;
23888 }
23889 }
23890
23891 if (error >= 0) {
23892 int found;
23893 /*
23894 * Process patters. Pattern facets are ORed at type level
23895 * and ANDed if derived. Walk the base type axis.
23896 */
23897 tmpType = type;
23898 facet = NULL;
23899 do {
23900 found = 0;
23901 for (facetLink = tmpType->facetSet; facetLink != NULL;
23902 facetLink = facetLink->next) {
23903 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23904 continue;
23905 found = 1;
23906 /*
23907 * NOTE that for patterns, @value needs to be the
23908 * normalized vaule.
23909 */
23910 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23911 if (ret == 1)
23912 break;
23913 else if (ret < 0) {
23914 AERROR_INT("xmlSchemaValidateFacets",
23915 "validating against a pattern facet");
23916 return (-1);
23917 } else {
23918 /*
23919 * Save the last non-validating facet.
23920 */
23921 facet = facetLink->facet;
23922 }
23923 }
23924 if (found && (ret != 1)) {
23925 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23926 if (fireErrors) {
23927 xmlSchemaFacetErr(actxt, ret, node,
23928 value, 0, type, facet, NULL, NULL, NULL);
23929 } else
23930 return (ret);
23931 if (error == 0)
23932 error = ret;
23933 break;
23934 }
23935 tmpType = tmpType->baseType;
23936 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23937 }
23938
23939 return (error);
23940}
23941
23942static xmlChar *
23943xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23944 const xmlChar *value)
23945{
23946 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23947 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23948 return (xmlSchemaCollapseString(value));
23949 case XML_SCHEMA_WHITESPACE_REPLACE:
23950 return (xmlSchemaWhiteSpaceReplace(value));
23951 default:
23952 return (NULL);
23953 }
23954}
23955
23956static int
23957xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23958 const xmlChar *value,
23959 xmlSchemaValPtr *val,
23960 int valNeeded)
23961{
23962 int ret;
23963 const xmlChar *nsName;
23964 xmlChar *local, *prefix = NULL;
23965
23966 ret = xmlValidateQName(value, 1);
23967 if (ret != 0) {
23968 if (ret == -1) {
23969 VERROR_INT("xmlSchemaValidateQName",
23970 "calling xmlValidateQName()");
23971 return (-1);
23972 }
23973 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23974 }
23975 /*
23976 * NOTE: xmlSplitQName2 will always return a duplicated
23977 * strings.
23978 */
23979 local = xmlSplitQName2(value, &prefix);
23980 if (local == NULL)
23981 local = xmlStrdup(value);
23982 /*
23983 * OPTIMIZE TODO: Use flags for:
23984 * - is there any namespace binding?
23985 * - is there a default namespace?
23986 */
23987 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23988
23989 if (prefix != NULL) {
23990 xmlFree(prefix);
23991 /*
23992 * A namespace must be found if the prefix is
23993 * NOT NULL.
23994 */
23995 if (nsName == NULL) {
23996 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023997 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023998 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023999 "The QName value '%s' has no "
24000 "corresponding namespace declaration in "
24001 "scope", value, NULL);
24002 if (local != NULL)
24003 xmlFree(local);
24004 return (ret);
24005 }
24006 }
24007 if (valNeeded && val) {
24008 if (nsName != NULL)
24009 *val = xmlSchemaNewQNameValue(
24010 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24011 else
24012 *val = xmlSchemaNewQNameValue(NULL,
24013 BAD_CAST local);
24014 } else
24015 xmlFree(local);
24016 return (0);
24017}
24018
24019/*
24020* cvc-simple-type
24021*/
24022static int
24023xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24024 xmlNodePtr node,
24025 xmlSchemaTypePtr type,
24026 const xmlChar *value,
24027 xmlSchemaValPtr *retVal,
24028 int fireErrors,
24029 int normalize,
24030 int isNormalized)
24031{
24032 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24033 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024034 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024035 xmlChar *normValue = NULL;
24036
24037#define NORMALIZE(atype) \
24038 if ((! isNormalized) && \
24039 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24040 normValue = xmlSchemaNormalizeValue(atype, value); \
24041 if (normValue != NULL) \
24042 value = normValue; \
24043 isNormalized = 1; \
24044 }
24045
24046 if ((retVal != NULL) && (*retVal != NULL)) {
24047 xmlSchemaFreeValue(*retVal);
24048 *retVal = NULL;
24049 }
24050 /*
24051 * 3.14.4 Simple Type Definition Validation Rules
24052 * Validation Rule: String Valid
24053 */
24054 /*
24055 * 1 It is schema-valid with respect to that definition as defined
24056 * by Datatype Valid in [XML Schemas: Datatypes].
24057 */
24058 /*
24059 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24060 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24061 * the string must be a ·declared entity name·.
24062 */
24063 /*
24064 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24065 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24066 * then every whitespace-delimited substring of the string must be a ·declared
24067 * entity name·.
24068 */
24069 /*
24070 * 2.3 otherwise no further condition applies.
24071 */
24072 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24073 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024074 if (value == NULL)
24075 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024076 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024077 xmlSchemaTypePtr biType; /* The built-in type. */
24078 /*
24079 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24080 * a literal in the ·lexical space· of {base type definition}"
24081 */
24082 /*
24083 * Whitespace-normalize.
24084 */
24085 NORMALIZE(type);
24086 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24087 /*
24088 * Get the built-in type.
24089 */
24090 biType = type->baseType;
24091 while ((biType != NULL) &&
24092 (biType->type != XML_SCHEMA_TYPE_BASIC))
24093 biType = biType->baseType;
24094
24095 if (biType == NULL) {
24096 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24097 "could not get the built-in type");
24098 goto internal_error;
24099 }
24100 } else
24101 biType = type;
24102 /*
24103 * NOTATIONs need to be processed here, since they need
24104 * to lookup in the hashtable of NOTATION declarations of the schema.
24105 */
24106 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24107 switch (biType->builtInType) {
24108 case XML_SCHEMAS_NOTATION:
24109 ret = xmlSchemaValidateNotation(
24110 (xmlSchemaValidCtxtPtr) actxt,
24111 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24112 NULL, value, &val, valNeeded);
24113 break;
24114 case XML_SCHEMAS_QNAME:
24115 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24116 value, &val, valNeeded);
24117 break;
24118 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024119 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024120 if (valNeeded)
24121 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24122 value, &val, NULL);
24123 else
24124 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24125 value, NULL, NULL);
24126 break;
24127 }
24128 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24129 switch (biType->builtInType) {
24130 case XML_SCHEMAS_NOTATION:
24131 ret = xmlSchemaValidateNotation(NULL,
24132 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24133 value, &val, valNeeded);
24134 break;
24135 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024136 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024137 if (valNeeded)
24138 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24139 value, &val, node);
24140 else
24141 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24142 value, NULL, node);
24143 break;
24144 }
24145 } else {
24146 /*
24147 * Validation via a public API is not implemented yet.
24148 */
24149 TODO
24150 goto internal_error;
24151 }
24152 if (ret != 0) {
24153 if (ret < 0) {
24154 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24155 "validating against a built-in type");
24156 goto internal_error;
24157 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024158 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024159 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24160 else
24161 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24162 }
24163 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24164 /*
24165 * Check facets.
24166 */
24167 ret = xmlSchemaValidateFacets(actxt, node, type,
24168 (xmlSchemaValType) biType->builtInType, value, val,
24169 0, fireErrors);
24170 if (ret != 0) {
24171 if (ret < 0) {
24172 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24173 "validating facets of atomic simple type");
24174 goto internal_error;
24175 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024176 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024177 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24178 else
24179 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24180 }
24181 }
24182 if (fireErrors && (ret > 0))
24183 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024184 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024185
24186 xmlSchemaTypePtr itemType;
24187 const xmlChar *cur, *end;
24188 xmlChar *tmpValue = NULL;
24189 unsigned long len = 0;
24190 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24191 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24192 * of white space separated tokens, each of which ·match·es a literal
24193 * in the ·lexical space· of {item type definition}
24194 */
24195 /*
24196 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24197 * the list type has an enum or pattern facet.
24198 */
24199 NORMALIZE(type);
24200 /*
24201 * VAL TODO: Optimize validation of empty values.
24202 * VAL TODO: We do not have computed values for lists.
24203 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024204 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024205 cur = value;
24206 do {
24207 while (IS_BLANK_CH(*cur))
24208 cur++;
24209 end = cur;
24210 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24211 end++;
24212 if (end == cur)
24213 break;
24214 tmpValue = xmlStrndup(cur, end - cur);
24215 len++;
24216
24217 if (valNeeded)
24218 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24219 tmpValue, &curVal, fireErrors, 0, 1);
24220 else
24221 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24222 tmpValue, NULL, fireErrors, 0, 1);
24223 FREE_AND_NULL(tmpValue);
24224 if (curVal != NULL) {
24225 /*
24226 * Add to list of computed values.
24227 */
24228 if (val == NULL)
24229 val = curVal;
24230 else
24231 xmlSchemaValueAppend(prevVal, curVal);
24232 prevVal = curVal;
24233 curVal = NULL;
24234 }
24235 if (ret != 0) {
24236 if (ret < 0) {
24237 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24238 "validating an item of list simple type");
24239 goto internal_error;
24240 }
24241 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24242 break;
24243 }
24244 cur = end;
24245 } while (*cur != 0);
24246 FREE_AND_NULL(tmpValue);
24247 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24248 /*
24249 * Apply facets (pattern, enumeration).
24250 */
24251 ret = xmlSchemaValidateFacets(actxt, node, type,
24252 XML_SCHEMAS_UNKNOWN, value, val,
24253 len, fireErrors);
24254 if (ret != 0) {
24255 if (ret < 0) {
24256 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24257 "validating facets of list simple type");
24258 goto internal_error;
24259 }
24260 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24261 }
24262 }
24263 if (fireErrors && (ret > 0)) {
24264 /*
24265 * Report the normalized value.
24266 */
24267 normalize = 1;
24268 NORMALIZE(type);
24269 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24270 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024271 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024272 xmlSchemaTypeLinkPtr memberLink;
24273 /*
24274 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24275 * not apply directly; however, the normalization behavior of ·union·
24276 * types is controlled by the value of whiteSpace on that one of the
24277 * ·memberTypes· against which the ·union· is successfully validated.
24278 *
24279 * This means that the value is normalized by the first validating
24280 * member type, then the facets of the union type are applied. This
24281 * needs changing of the value!
24282 */
24283
24284 /*
24285 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24286 * literal in the ·lexical space· of at least one member of
24287 * {member type definitions}
24288 */
24289 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24290 if (memberLink == NULL) {
24291 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24292 "union simple type has no member types");
24293 goto internal_error;
24294 }
24295 /*
24296 * Always normalize union type values, since we currently
24297 * cannot store the whitespace information with the value
24298 * itself; otherwise a later value-comparison would be
24299 * not possible.
24300 */
24301 while (memberLink != NULL) {
24302 if (valNeeded)
24303 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24304 memberLink->type, value, &val, 0, 1, 0);
24305 else
24306 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24307 memberLink->type, value, NULL, 0, 1, 0);
24308 if (ret <= 0)
24309 break;
24310 memberLink = memberLink->next;
24311 }
24312 if (ret != 0) {
24313 if (ret < 0) {
24314 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24315 "validating members of union simple type");
24316 goto internal_error;
24317 }
24318 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24319 }
24320 /*
24321 * Apply facets (pattern, enumeration).
24322 */
24323 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24324 /*
24325 * The normalization behavior of ·union· types is controlled by
24326 * the value of whiteSpace on that one of the ·memberTypes·
24327 * against which the ·union· is successfully validated.
24328 */
24329 NORMALIZE(memberLink->type);
24330 ret = xmlSchemaValidateFacets(actxt, node, type,
24331 XML_SCHEMAS_UNKNOWN, value, val,
24332 0, fireErrors);
24333 if (ret != 0) {
24334 if (ret < 0) {
24335 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24336 "validating facets of union simple type");
24337 goto internal_error;
24338 }
24339 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24340 }
24341 }
24342 if (fireErrors && (ret > 0))
24343 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24344 }
24345
24346 if (normValue != NULL)
24347 xmlFree(normValue);
24348 if (ret == 0) {
24349 if (retVal != NULL)
24350 *retVal = val;
24351 else if (val != NULL)
24352 xmlSchemaFreeValue(val);
24353 } else if (val != NULL)
24354 xmlSchemaFreeValue(val);
24355 return (ret);
24356internal_error:
24357 if (normValue != NULL)
24358 xmlFree(normValue);
24359 if (val != NULL)
24360 xmlSchemaFreeValue(val);
24361 return (-1);
24362}
24363
24364static int
24365xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24366 const xmlChar *value,
24367 const xmlChar **nsName,
24368 const xmlChar **localName)
24369{
24370 int ret = 0;
24371
24372 if ((nsName == NULL) || (localName == NULL))
24373 return (-1);
24374 *nsName = NULL;
24375 *localName = NULL;
24376
24377 ret = xmlValidateQName(value, 1);
24378 if (ret == -1)
24379 return (-1);
24380 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024381 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024382 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24383 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24384 return (1);
24385 }
24386 {
24387 xmlChar *local = NULL;
24388 xmlChar *prefix;
24389
24390 /*
24391 * NOTE: xmlSplitQName2 will return a duplicated
24392 * string.
24393 */
24394 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024395 if (local == NULL)
24396 *localName = xmlDictLookup(vctxt->dict, value, -1);
24397 else {
24398 *localName = xmlDictLookup(vctxt->dict, local, -1);
24399 xmlFree(local);
24400 }
24401
24402 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24403
24404 if (prefix != NULL) {
24405 xmlFree(prefix);
24406 /*
24407 * A namespace must be found if the prefix is NOT NULL.
24408 */
24409 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024410 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024411 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024412 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024413 "The QName value '%s' has no "
24414 "corresponding namespace declaration in scope",
24415 value, NULL);
24416 return (2);
24417 }
24418 }
24419 }
24420 return (0);
24421}
24422
24423static int
24424xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24425 xmlSchemaAttrInfoPtr iattr,
24426 xmlSchemaTypePtr *localType,
24427 xmlSchemaElementPtr elemDecl)
24428{
24429 int ret = 0;
24430 /*
24431 * cvc-elt (3.3.4) : (4)
24432 * AND
24433 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24434 * (1.2.1.2.1) - (1.2.1.2.4)
24435 * Handle 'xsi:type'.
24436 */
24437 if (localType == NULL)
24438 return (-1);
24439 *localType = NULL;
24440 if (iattr == NULL)
24441 return (0);
24442 else {
24443 const xmlChar *nsName = NULL, *local = NULL;
24444 /*
24445 * TODO: We should report a *warning* that the type was overriden
24446 * by the instance.
24447 */
24448 ACTIVATE_ATTRIBUTE(iattr);
24449 /*
24450 * (cvc-elt) (3.3.4) : (4.1)
24451 * (cvc-assess-elt) (1.2.1.2.2)
24452 */
24453 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24454 &nsName, &local);
24455 if (ret != 0) {
24456 if (ret < 0) {
24457 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24458 "calling xmlSchemaQNameExpand() to validate the "
24459 "attribute 'xsi:type'");
24460 goto internal_error;
24461 }
24462 goto exit;
24463 }
24464 /*
24465 * (cvc-elt) (3.3.4) : (4.2)
24466 * (cvc-assess-elt) (1.2.1.2.3)
24467 */
24468 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24469 if (*localType == NULL) {
24470 xmlChar *str = NULL;
24471
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024472 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024473 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024474 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024475 "The QName value '%s' of the xsi:type attribute does not "
24476 "resolve to a type definition",
24477 xmlSchemaFormatQName(&str, nsName, local), NULL);
24478 FREE_AND_NULL(str);
24479 ret = vctxt->err;
24480 goto exit;
24481 }
24482 if (elemDecl != NULL) {
24483 int set = 0;
24484
24485 /*
24486 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24487 * "The ·local type definition· must be validly
24488 * derived from the {type definition} given the union of
24489 * the {disallowed substitutions} and the {type definition}'s
24490 * {prohibited substitutions}, as defined in
24491 * Type Derivation OK (Complex) (§3.4.6)
24492 * (if it is a complex type definition),
24493 * or given {disallowed substitutions} as defined in Type
24494 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24495 * definition)."
24496 *
24497 * {disallowed substitutions}: the "block" on the element decl.
24498 * {prohibited substitutions}: the "block" on the type def.
24499 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024500 /*
24501 * OPTIMIZE TODO: We could map types already evaluated
24502 * to be validly derived from other types to avoid checking
24503 * this over and over for the same types.
24504 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024505 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24506 (elemDecl->subtypes->flags &
24507 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24508 set |= SUBSET_EXTENSION;
24509
24510 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24511 (elemDecl->subtypes->flags &
24512 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24513 set |= SUBSET_RESTRICTION;
24514
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024515 /*
24516 * REMOVED and CHANGED since this produced a parser context
24517 * which adds to the string dict of the schema. So this would
24518 * change the schema and we don't want this. We don't need
24519 * the parser context anymore.
24520 *
24521 * if ((vctxt->pctxt == NULL) &&
24522 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24523 * return (-1);
24524 */
24525
24526 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024527 elemDecl->subtypes, set) != 0) {
24528 xmlChar *str = NULL;
24529
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024530 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024531 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24532 "The type definition '%s', specified by xsi:type, is "
24533 "blocked or not validly derived from the type definition "
24534 "of the element declaration",
24535 xmlSchemaFormatQName(&str,
24536 (*localType)->targetNamespace,
24537 (*localType)->name),
24538 NULL);
24539 FREE_AND_NULL(str);
24540 ret = vctxt->err;
24541 *localType = NULL;
24542 }
24543 }
24544 }
24545exit:
24546 ACTIVATE_ELEM;
24547 return (ret);
24548internal_error:
24549 ACTIVATE_ELEM;
24550 return (-1);
24551}
24552
24553static int
24554xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24555{
24556 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024557 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024558
24559 /*
24560 * cvc-elt (3.3.4) : 1
24561 */
24562 if (elemDecl == NULL) {
24563 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24564 "No matching declaration available");
24565 return (vctxt->err);
24566 }
24567 /*
24568 * cvc-elt (3.3.4) : 2
24569 */
24570 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24571 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24572 "The element declaration is abstract");
24573 return (vctxt->err);
24574 }
24575 if (actualType == NULL) {
24576 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24577 "The type definition is absent");
24578 return (XML_SCHEMAV_CVC_TYPE_1);
24579 }
24580 if (vctxt->nbAttrInfos != 0) {
24581 int ret;
24582 xmlSchemaAttrInfoPtr iattr;
24583 /*
24584 * cvc-elt (3.3.4) : 3
24585 * Handle 'xsi:nil'.
24586 */
24587 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24588 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24589 if (iattr) {
24590 ACTIVATE_ATTRIBUTE(iattr);
24591 /*
24592 * Validate the value.
24593 */
24594 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024595 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024596 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24597 iattr->value, &(iattr->val), 1, 0, 0);
24598 ACTIVATE_ELEM;
24599 if (ret < 0) {
24600 VERROR_INT("xmlSchemaValidateElemDecl",
24601 "calling xmlSchemaVCheckCVCSimpleType() to "
24602 "validate the attribute 'xsi:nil'");
24603 return (-1);
24604 }
24605 if (ret == 0) {
24606 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24607 /*
24608 * cvc-elt (3.3.4) : 3.1
24609 */
24610 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24611 "The element is not 'nillable'");
24612 /* Does not return an error on purpose. */
24613 } else {
24614 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24615 /*
24616 * cvc-elt (3.3.4) : 3.2.2
24617 */
24618 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24619 (elemDecl->value != NULL)) {
24620 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24621 "The element cannot be 'nilled' because "
24622 "there is a fixed value constraint defined "
24623 "for it");
24624 /* Does not return an error on purpose. */
24625 } else
24626 vctxt->inode->flags |=
24627 XML_SCHEMA_ELEM_INFO_NILLED;
24628 }
24629 }
24630 }
24631 }
24632 /*
24633 * cvc-elt (3.3.4) : 4
24634 * Handle 'xsi:type'.
24635 */
24636 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24637 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24638 if (iattr) {
24639 xmlSchemaTypePtr localType = NULL;
24640
24641 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24642 elemDecl);
24643 if (ret != 0) {
24644 if (ret == -1) {
24645 VERROR_INT("xmlSchemaValidateElemDecl",
24646 "calling xmlSchemaProcessXSIType() to "
24647 "process the attribute 'xsi:type'");
24648 return (-1);
24649 }
24650 /* Does not return an error on purpose. */
24651 }
24652 if (localType != NULL) {
24653 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24654 actualType = localType;
24655 }
24656 }
24657 }
24658 /*
24659 * IDC: Register identity-constraint XPath matchers.
24660 */
24661 if ((elemDecl->idcs != NULL) &&
24662 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24663 return (-1);
24664 /*
24665 * No actual type definition.
24666 */
24667 if (actualType == NULL) {
24668 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24669 "The type definition is absent");
24670 return (XML_SCHEMAV_CVC_TYPE_1);
24671 }
24672 /*
24673 * Remember the actual type definition.
24674 */
24675 vctxt->inode->typeDef = actualType;
24676
24677 return (0);
24678}
24679
24680static int
24681xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24682{
24683 xmlSchemaAttrInfoPtr iattr;
24684 int ret = 0, i;
24685
24686 /*
24687 * SPEC cvc-type (3.1.1)
24688 * "The attributes of must be empty, excepting those whose namespace
24689 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24690 * whose local name is one of type, nil, schemaLocation or
24691 * noNamespaceSchemaLocation."
24692 */
24693 if (vctxt->nbAttrInfos == 0)
24694 return (0);
24695 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24696 iattr = vctxt->attrInfos[i];
24697 if (! iattr->metaType) {
24698 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024699 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024700 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24701 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24702 }
24703 }
24704 ACTIVATE_ELEM
24705 return (ret);
24706}
24707
24708/*
24709* Cleanup currently used attribute infos.
24710*/
24711static void
24712xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24713{
24714 int i;
24715 xmlSchemaAttrInfoPtr attr;
24716
24717 if (vctxt->nbAttrInfos == 0)
24718 return;
24719 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24720 attr = vctxt->attrInfos[i];
24721 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24722 if (attr->localName != NULL)
24723 xmlFree((xmlChar *) attr->localName);
24724 if (attr->nsName != NULL)
24725 xmlFree((xmlChar *) attr->nsName);
24726 }
24727 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24728 if (attr->value != NULL)
24729 xmlFree((xmlChar *) attr->value);
24730 }
24731 if (attr->val != NULL) {
24732 xmlSchemaFreeValue(attr->val);
24733 attr->val = NULL;
24734 }
24735 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24736 }
24737 vctxt->nbAttrInfos = 0;
24738}
24739
24740/*
24741* 3.4.4 Complex Type Definition Validation Rules
24742* Element Locally Valid (Complex Type) (cvc-complex-type)
24743* 3.2.4 Attribute Declaration Validation Rules
24744* Validation Rule: Attribute Locally Valid (cvc-attribute)
24745* Attribute Locally Valid (Use) (cvc-au)
24746*
24747* Only "assessed" attribute information items will be visible to
24748* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24749*/
24750static int
24751xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24752{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024753 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24754 xmlSchemaItemListPtr attrUseList;
24755 xmlSchemaAttributeUsePtr attrUse = NULL;
24756 xmlSchemaAttributePtr attrDecl = NULL;
24757 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24758 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024759 int xpathRes = 0, res, wildIDs = 0, fixed;
24760
24761 /*
24762 * SPEC (cvc-attribute)
24763 * (1) "The declaration must not be ·absent· (see Missing
24764 * Sub-components (§5.3) for how this can fail to be
24765 * the case)."
24766 * (2) "Its {type definition} must not be absent."
24767 *
24768 * NOTE (1) + (2): This is not handled here, since we currently do not
24769 * allow validation against schemas which have missing sub-components.
24770 *
24771 * SPEC (cvc-complex-type)
24772 * (3) "For each attribute information item in the element information
24773 * item's [attributes] excepting those whose [namespace name] is
24774 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24775 * [local name] is one of type, nil, schemaLocation or
24776 * noNamespaceSchemaLocation, the appropriate case among the following
24777 * must be true:
24778 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024779 */
24780 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24781 /*
24782 * @nbAttrs is the number of attributes present in the instance.
24783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024784 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024785 if (attrUseList != NULL)
24786 nbUses = attrUseList->nbItems;
24787 else
24788 nbUses = 0;
24789 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024790 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024791 attrUse = attrUseList->items[i];
24792 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24793 for (j = 0; j < nbAttrs; j++) {
24794 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024795 /*
24796 * SPEC (cvc-complex-type) (3)
24797 * Skip meta attributes.
24798 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024799 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024800 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024801 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024802 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024803 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024804 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024805 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024806 continue;
24807 found = 1;
24808 /*
24809 * SPEC (cvc-complex-type)
24810 * (3.1) "If there is among the {attribute uses} an attribute
24811 * use with an {attribute declaration} whose {name} matches
24812 * the attribute information item's [local name] and whose
24813 * {target namespace} is identical to the attribute information
24814 * item's [namespace name] (where an ·absent· {target namespace}
24815 * is taken to be identical to a [namespace name] with no value),
24816 * then the attribute information must be ·valid· with respect
24817 * to that attribute use as per Attribute Locally Valid (Use)
24818 * (§3.5.4). In this case the {attribute declaration} of that
24819 * attribute use is the ·context-determined declaration· for the
24820 * attribute information item with respect to Schema-Validity
24821 * Assessment (Attribute) (§3.2.4) and
24822 * Assessment Outcome (Attribute) (§3.2.5).
24823 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024824 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24825 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024826 /*
24827 * Context-determined declaration.
24828 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024829 iattr->decl = attrDecl;
24830 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024831 break;
24832 }
24833
24834 if (found)
24835 continue;
24836
24837 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24838 /*
24839 * Handle non-existent, required attributes.
24840 *
24841 * SPEC (cvc-complex-type)
24842 * (4) "The {attribute declaration} of each attribute use in
24843 * the {attribute uses} whose {required} is true matches one
24844 * of the attribute information items in the element information
24845 * item's [attributes] as per clause 3.1 above."
24846 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024847 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24848 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024849 VERROR_INT(
24850 "xmlSchemaVAttributesComplex",
24851 "calling xmlSchemaGetFreshAttrInfo()");
24852 return (-1);
24853 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024854 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24855 tmpiattr->use = attrUse;
24856 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024857 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24858 ((attrUse->defValue != NULL) ||
24859 (attrDecl->defValue != NULL))) {
24860 /*
24861 * Handle non-existent, optional, default/fixed attributes.
24862 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024863 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24864 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024865 VERROR_INT(
24866 "xmlSchemaVAttributesComplex",
24867 "calling xmlSchemaGetFreshAttrInfo()");
24868 return (-1);
24869 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024870 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24871 tmpiattr->use = attrUse;
24872 tmpiattr->decl = attrDecl;
24873 tmpiattr->typeDef = attrDecl->subtypes;
24874 tmpiattr->localName = attrDecl->name;
24875 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024876 }
24877 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024878
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024879 if (vctxt->nbAttrInfos == 0)
24880 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024881 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024882 /*
24883 * Validate against the wildcard.
24884 */
24885 if (type->attributeWildcard != NULL) {
24886 /*
24887 * SPEC (cvc-complex-type)
24888 * (3.2.1) "There must be an {attribute wildcard}."
24889 */
24890 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024891 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024892 /*
24893 * SPEC (cvc-complex-type) (3)
24894 * Skip meta attributes.
24895 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024896 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024897 continue;
24898 /*
24899 * SPEC (cvc-complex-type)
24900 * (3.2.2) "The attribute information item must be ·valid· with
24901 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24902 *
24903 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24904 * "... its [namespace name] must be ·valid· with respect to
24905 * the wildcard constraint, as defined in Wildcard allows
24906 * Namespace Name (§3.10.4)."
24907 */
24908 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024909 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024910 /*
24911 * Handle processContents.
24912 *
24913 * SPEC (cvc-wildcard):
24914 * processContents | context-determined declaration:
24915 * "strict" "mustFind"
24916 * "lax" "none"
24917 * "skip" "skip"
24918 */
24919 if (type->attributeWildcard->processContents ==
24920 XML_SCHEMAS_ANY_SKIP) {
24921 /*
24922 * context-determined declaration = "skip"
24923 *
24924 * SPEC PSVI Assessment Outcome (Attribute)
24925 * [validity] = "notKnown"
24926 * [validation attempted] = "none"
24927 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024928 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024929 continue;
24930 }
24931 /*
24932 * Find an attribute declaration.
24933 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024934 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24935 iattr->localName, iattr->nsName);
24936 if (iattr->decl != NULL) {
24937 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024938 /*
24939 * SPEC (cvc-complex-type)
24940 * (5) "Let [Definition:] the wild IDs be the set of
24941 * all attribute information item to which clause 3.2
24942 * applied and whose ·validation· resulted in a
24943 * ·context-determined declaration· of mustFind or no
24944 * ·context-determined declaration· at all, and whose
24945 * [local name] and [namespace name] resolve (as
24946 * defined by QName resolution (Instance) (§3.15.4)) to
24947 * an attribute declaration whose {type definition} is
24948 * or is derived from ID. Then all of the following
24949 * must be true:"
24950 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024951 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024952 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024953 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024954 /*
24955 * SPEC (5.1) "There must be no more than one
24956 * item in ·wild IDs·."
24957 */
24958 if (wildIDs != 0) {
24959 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024960 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024961 TODO
24962 continue;
24963 }
24964 wildIDs++;
24965 /*
24966 * SPEC (cvc-complex-type)
24967 * (5.2) "If ·wild IDs· is non-empty, there must not
24968 * be any attribute uses among the {attribute uses}
24969 * whose {attribute declaration}'s {type definition}
24970 * is or is derived from ID."
24971 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024972 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024973 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024974 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024975 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024976 /* URGENT VAL TODO: implement */
24977 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024978 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024979 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024980 }
24981 }
24982 }
24983 } else if (type->attributeWildcard->processContents ==
24984 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024985 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024986 /*
24987 * SPEC PSVI Assessment Outcome (Attribute)
24988 * [validity] = "notKnown"
24989 * [validation attempted] = "none"
24990 */
24991 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024992 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024993 }
24994 }
24995 }
24996 }
24997
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024998 if (vctxt->nbAttrInfos == 0)
24999 return (0);
25000
25001 /*
25002 * Validate values, create default attributes, evaluate IDCs.
25003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025004 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025005 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025006 /*
25007 * VAL TODO: Note that we won't try to resolve IDCs to
25008 * "lax" and "skip" validated attributes. Check what to
25009 * do in this case.
25010 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025011 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25012 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025013 continue;
25014 /*
25015 * VAL TODO: What to do if the type definition is missing?
25016 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025017 if (iattr->typeDef == NULL) {
25018 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025019 continue;
25020 }
25021
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025022 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025023 fixed = 0;
25024 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025025
25026 if (vctxt->xpathStates != NULL) {
25027 /*
25028 * Evaluate IDCs.
25029 */
25030 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25031 XML_ATTRIBUTE_NODE);
25032 if (xpathRes == -1) {
25033 VERROR_INT("xmlSchemaVAttributesComplex",
25034 "calling xmlSchemaXPathEvaluate()");
25035 goto internal_error;
25036 }
25037 }
25038
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025039 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025040 /*
25041 * Default/fixed attributes.
25042 */
25043 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025044 if (iattr->use->defValue != NULL) {
25045 iattr->value = (xmlChar *) iattr->use->defValue;
25046 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025047 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025048 iattr->value = (xmlChar *) iattr->decl->defValue;
25049 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025050 }
25051 /*
25052 * IDCs will consume the precomputed default value,
25053 * so we need to clone it.
25054 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025055 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025056 VERROR_INT("xmlSchemaVAttributesComplex",
25057 "default/fixed value on an attribute use was "
25058 "not precomputed");
25059 goto internal_error;
25060 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025061 iattr->val = xmlSchemaCopyValue(iattr->val);
25062 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025063 VERROR_INT("xmlSchemaVAttributesComplex",
25064 "calling xmlSchemaCopyValue()");
25065 goto internal_error;
25066 }
25067 }
25068 /*
25069 * PSVI: Add the default attribute to the current element.
25070 * VAL TODO: Should we use the *normalized* value? This currently
25071 * uses the *initial* value.
25072 */
25073 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025074 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025075 xmlChar *normValue;
25076 const xmlChar *value;
25077
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025078 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025079 /*
25080 * Normalize the value.
25081 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025082 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25083 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025084 if (normValue != NULL)
25085 value = BAD_CAST normValue;
25086
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025087 if (iattr->nsName == NULL) {
25088 if (xmlNewProp(iattr->node->parent,
25089 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025090 VERROR_INT("xmlSchemaVAttributesComplex",
25091 "callling xmlNewProp()");
25092 if (normValue != NULL)
25093 xmlFree(normValue);
25094 goto internal_error;
25095 }
25096 } else {
25097 xmlNsPtr ns;
25098
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025099 ns = xmlSearchNsByHref(iattr->node->doc,
25100 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025101 if (ns == NULL) {
25102 xmlChar prefix[12];
25103 int counter = 0;
25104
25105 /*
25106 * Create a namespace declaration on the validation
25107 * root node if no namespace declaration is in scope.
25108 */
25109 do {
25110 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025111 ns = xmlSearchNs(iattr->node->doc,
25112 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025113 if (counter > 1000) {
25114 VERROR_INT(
25115 "xmlSchemaVAttributesComplex",
25116 "could not compute a ns prefix for a "
25117 "default/fixed attribute");
25118 if (normValue != NULL)
25119 xmlFree(normValue);
25120 goto internal_error;
25121 }
25122 } while (ns != NULL);
25123 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025124 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025125 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025126 /*
25127 * TODO:
25128 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25129 * If we have QNames: do we need to ensure there's a
25130 * prefix defined for the QName?
25131 */
25132 xmlNewNsProp(iattr->node->parent, ns,
25133 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025134 }
25135 if (normValue != NULL)
25136 xmlFree(normValue);
25137 }
25138 /*
25139 * Go directly to IDC evaluation.
25140 */
25141 goto eval_idcs;
25142 }
25143 /*
25144 * Validate the value.
25145 */
25146 if (vctxt->value != NULL) {
25147 /*
25148 * Free last computed value; just for safety reasons.
25149 */
25150 xmlSchemaFreeValue(vctxt->value);
25151 vctxt->value = NULL;
25152 }
25153 /*
25154 * Note that the attribute *use* can be unavailable, if
25155 * the attribute was a wild attribute.
25156 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025157 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25158 ((iattr->use != NULL) &&
25159 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025160 fixed = 1;
25161 else
25162 fixed = 0;
25163 /*
25164 * SPEC (cvc-attribute)
25165 * (3) "The item's ·normalized value· must be locally ·valid·
25166 * with respect to that {type definition} as per
25167 * String Valid (§3.14.4)."
25168 *
25169 * VAL TODO: Do we already have the
25170 * "normalized attribute value" here?
25171 */
25172 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025173 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025174 /*
25175 * Request a computed value.
25176 */
25177 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025178 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025179 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025180 1, 1, 0);
25181 } else {
25182 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025183 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025184 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025185 1, 0, 0);
25186 }
25187
25188 if (res != 0) {
25189 if (res == -1) {
25190 VERROR_INT("xmlSchemaVAttributesComplex",
25191 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25192 goto internal_error;
25193 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025194 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025195 /*
25196 * SPEC PSVI Assessment Outcome (Attribute)
25197 * [validity] = "invalid"
25198 */
25199 goto eval_idcs;
25200 }
25201
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025202 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025203 /*
25204 * SPEC Attribute Locally Valid (Use) (cvc-au)
25205 * "For an attribute information item to be·valid·
25206 * with respect to an attribute use its *normalized*
25207 * value· must match the *canonical* lexical
25208 * representation of the attribute use's {value
25209 * constraint}value, if it is present and fixed."
25210 *
25211 * VAL TODO: The requirement for the *canonical* value
25212 * will be removed in XML Schema 1.1.
25213 */
25214 /*
25215 * SPEC Attribute Locally Valid (cvc-attribute)
25216 * (4) "The item's *actual* value· must match the *value* of
25217 * the {value constraint}, if it is present and fixed."
25218 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025219 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025220 /* VAL TODO: A value was not precomputed. */
25221 TODO
25222 goto eval_idcs;
25223 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025224 if ((iattr->use != NULL) &&
25225 (iattr->use->defValue != NULL)) {
25226 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025227 /* VAL TODO: A default value was not precomputed. */
25228 TODO
25229 goto eval_idcs;
25230 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025231 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025232 /*
25233 if (xmlSchemaCompareValuesWhtsp(attr->val,
25234 (xmlSchemaWhitespaceValueType) ws,
25235 attr->use->defVal,
25236 (xmlSchemaWhitespaceValueType) ws) != 0) {
25237 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025238 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25239 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025240 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025241 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025242 /* VAL TODO: A default value was not precomputed. */
25243 TODO
25244 goto eval_idcs;
25245 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025246 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025247 /*
25248 if (xmlSchemaCompareValuesWhtsp(attr->val,
25249 (xmlSchemaWhitespaceValueType) ws,
25250 attrDecl->defVal,
25251 (xmlSchemaWhitespaceValueType) ws) != 0) {
25252 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025253 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25254 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025255 }
25256 /*
25257 * [validity] = "valid"
25258 */
25259 }
25260eval_idcs:
25261 /*
25262 * Evaluate IDCs.
25263 */
25264 if (xpathRes) {
25265 if (xmlSchemaXPathProcessHistory(vctxt,
25266 vctxt->depth +1) == -1) {
25267 VERROR_INT("xmlSchemaVAttributesComplex",
25268 "calling xmlSchemaXPathEvaluate()");
25269 goto internal_error;
25270 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025271 } else if (vctxt->xpathStates != NULL)
25272 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025273 }
25274
25275 /*
25276 * Report errors.
25277 */
25278 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025279 iattr = vctxt->attrInfos[i];
25280 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25281 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25282 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25283 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025284 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025285 ACTIVATE_ATTRIBUTE(iattr);
25286 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025287 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25288 xmlChar *str = NULL;
25289 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025290 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025291 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25292 "The attribute '%s' is required but missing",
25293 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025294 iattr->decl->targetNamespace,
25295 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025296 NULL);
25297 FREE_AND_NULL(str)
25298 break;
25299 }
25300 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25301 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25302 "The type definition is absent");
25303 break;
25304 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025305 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025306 XML_SCHEMAV_CVC_AU, NULL, NULL,
25307 "The value '%s' does not match the fixed "
25308 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025309 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025310 break;
25311 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25312 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25313 "No matching global attribute declaration available, but "
25314 "demanded by the strict wildcard");
25315 break;
25316 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025317 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025318 break;
25319 /*
25320 * MAYBE VAL TODO: One might report different error messages
25321 * for the following errors.
25322 */
25323 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025324 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025325 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025326 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025327 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025328 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025329 }
25330 break;
25331 default:
25332 break;
25333 }
25334 }
25335
25336 ACTIVATE_ELEM;
25337 return (0);
25338internal_error:
25339 ACTIVATE_ELEM;
25340 return (-1);
25341}
25342
25343static int
25344xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25345 int *skip)
25346{
25347 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25348 /*
25349 * The namespace of the element was already identified to be
25350 * matching the wildcard.
25351 */
25352 if ((skip == NULL) || (wild == NULL) ||
25353 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25354 VERROR_INT("xmlSchemaValidateElemWildcard",
25355 "bad arguments");
25356 return (-1);
25357 }
25358 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025359 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25360 /*
25361 * URGENT VAL TODO: Either we need to position the stream to the
25362 * next sibling, or walk the whole subtree.
25363 */
25364 *skip = 1;
25365 return (0);
25366 }
25367 {
25368 xmlSchemaElementPtr decl = NULL;
25369
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025370 decl = xmlSchemaGetElem(vctxt->schema,
25371 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025372 if (decl != NULL) {
25373 vctxt->inode->decl = decl;
25374 return (0);
25375 }
25376 }
25377 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25378 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025379 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025380 "No matching global element declaration available, but "
25381 "demanded by the strict wildcard");
25382 return (vctxt->err);
25383 }
25384 if (vctxt->nbAttrInfos != 0) {
25385 xmlSchemaAttrInfoPtr iattr;
25386 /*
25387 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25388 * (1.2.1.2.1) - (1.2.1.2.3 )
25389 *
25390 * Use the xsi:type attribute for the type definition.
25391 */
25392 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25393 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25394 if (iattr != NULL) {
25395 if (xmlSchemaProcessXSIType(vctxt, iattr,
25396 &(vctxt->inode->typeDef), NULL) == -1) {
25397 VERROR_INT("xmlSchemaValidateElemWildcard",
25398 "calling xmlSchemaProcessXSIType() to "
25399 "process the attribute 'xsi:nil'");
25400 return (-1);
25401 }
25402 /*
25403 * Don't return an error on purpose.
25404 */
25405 return (0);
25406 }
25407 }
25408 /*
25409 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25410 *
25411 * Fallback to "anyType".
25412 */
25413 vctxt->inode->typeDef =
25414 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25415 return (0);
25416}
25417
25418/*
25419* xmlSchemaCheckCOSValidDefault:
25420*
25421* This will be called if: not nilled, no content and a default/fixed
25422* value is provided.
25423*/
25424
25425static int
25426xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25427 const xmlChar *value,
25428 xmlSchemaValPtr *val)
25429{
25430 int ret = 0;
25431 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25432
25433 /*
25434 * cos-valid-default:
25435 * Schema Component Constraint: Element Default Valid (Immediate)
25436 * For a string to be a valid default with respect to a type
25437 * definition the appropriate case among the following must be true:
25438 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025439 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025440 /*
25441 * Complex type.
25442 *
25443 * SPEC (2.1) "its {content type} must be a simple type definition
25444 * or mixed."
25445 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25446 * type}'s particle must be ·emptiable· as defined by
25447 * Particle Emptiable (§3.9.6)."
25448 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025449 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25450 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25451 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025452 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25453 /* NOTE that this covers (2.2.2) as well. */
25454 VERROR(ret, NULL,
25455 "For a string to be a valid default, the type definition "
25456 "must be a simple type or a complex type with simple content "
25457 "or mixed content and a particle emptiable");
25458 return(ret);
25459 }
25460 }
25461 /*
25462 * 1 If the type definition is a simple type definition, then the string
25463 * must be ·valid· with respect to that definition as defined by String
25464 * Valid (§3.14.4).
25465 *
25466 * AND
25467 *
25468 * 2.2.1 If the {content type} is a simple type definition, then the
25469 * string must be ·valid· with respect to that simple type definition
25470 * as defined by String Valid (§3.14.4).
25471 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025472 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025473
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025474 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025475 NULL, inode->typeDef, value, val, 1, 1, 0);
25476
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025477 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025478
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025479 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025480 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25481 }
25482 if (ret < 0) {
25483 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25484 "calling xmlSchemaVCheckCVCSimpleType()");
25485 }
25486 return (ret);
25487}
25488
25489static void
25490xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25491 const xmlChar * name ATTRIBUTE_UNUSED,
25492 xmlSchemaElementPtr item,
25493 xmlSchemaNodeInfoPtr inode)
25494{
25495 inode->decl = item;
25496#ifdef DEBUG_CONTENT
25497 {
25498 xmlChar *str = NULL;
25499
25500 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25501 xmlGenericError(xmlGenericErrorContext,
25502 "AUTOMATON callback for '%s' [declaration]\n",
25503 xmlSchemaFormatQName(&str,
25504 inode->localName, inode->nsName));
25505 } else {
25506 xmlGenericError(xmlGenericErrorContext,
25507 "AUTOMATON callback for '%s' [wildcard]\n",
25508 xmlSchemaFormatQName(&str,
25509 inode->localName, inode->nsName));
25510
25511 }
25512 FREE_AND_NULL(str)
25513 }
25514#endif
25515}
25516
25517static int
25518xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025519{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025520 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25521 if (vctxt->inode == NULL) {
25522 VERROR_INT("xmlSchemaValidatorPushElem",
25523 "calling xmlSchemaGetFreshElemInfo()");
25524 return (-1);
25525 }
25526 vctxt->nbAttrInfos = 0;
25527 return (0);
25528}
25529
25530static int
25531xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25532 xmlSchemaNodeInfoPtr inode,
25533 xmlSchemaTypePtr type,
25534 const xmlChar *value)
25535{
25536 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25537 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025538 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025539 type, value, &(inode->val), 1, 1, 0));
25540 else
25541 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025542 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025543 type, value, NULL, 1, 0, 0));
25544}
25545
25546
25547
25548/*
25549* Process END of element.
25550*/
25551static int
25552xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25553{
25554 int ret = 0;
25555 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25556
25557 if (vctxt->nbAttrInfos != 0)
25558 xmlSchemaClearAttrInfos(vctxt);
25559 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25560 /*
25561 * This element was not expected;
25562 * we will not validate child elements of broken parents.
25563 * Skip validation of all content of the parent.
25564 */
25565 vctxt->skipDepth = vctxt->depth -1;
25566 goto end_elem;
25567 }
25568 if ((inode->typeDef == NULL) ||
25569 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25570 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025571 * 1. the type definition might be missing if the element was
25572 * error prone
25573 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025574 */
25575 goto end_elem;
25576 }
25577 /*
25578 * Check the content model.
25579 */
25580 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25581 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25582
25583 /*
25584 * Workaround for "anyType".
25585 */
25586 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25587 goto character_content;
25588
25589 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25590 xmlChar *values[10];
25591 int terminal, nbval = 10, nbneg;
25592
25593 if (inode->regexCtxt == NULL) {
25594 /*
25595 * Create the regex context.
25596 */
25597 inode->regexCtxt =
25598 xmlRegNewExecCtxt(inode->typeDef->contModel,
25599 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25600 vctxt);
25601 if (inode->regexCtxt == NULL) {
25602 VERROR_INT("xmlSchemaValidatorPopElem",
25603 "failed to create a regex context");
25604 goto internal_error;
25605 }
25606#ifdef DEBUG_AUTOMATA
25607 xmlGenericError(xmlGenericErrorContext,
25608 "AUTOMATON create on '%s'\n", inode->localName);
25609#endif
25610 }
25611 /*
25612 * Get hold of the still expected content, since a further
25613 * call to xmlRegExecPushString() will loose this information.
25614 */
25615 xmlRegExecNextValues(inode->regexCtxt,
25616 &nbval, &nbneg, &values[0], &terminal);
25617 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25618 if (ret <= 0) {
25619 /*
25620 * Still missing something.
25621 */
25622 ret = 1;
25623 inode->flags |=
25624 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025625 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025626 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25627 "Missing child element(s)",
25628 nbval, nbneg, values);
25629#ifdef DEBUG_AUTOMATA
25630 xmlGenericError(xmlGenericErrorContext,
25631 "AUTOMATON missing ERROR on '%s'\n",
25632 inode->localName);
25633#endif
25634 } else {
25635 /*
25636 * Content model is satisfied.
25637 */
25638 ret = 0;
25639#ifdef DEBUG_AUTOMATA
25640 xmlGenericError(xmlGenericErrorContext,
25641 "AUTOMATON succeeded on '%s'\n",
25642 inode->localName);
25643#endif
25644 }
25645
25646 }
25647 }
25648 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25649 goto end_elem;
25650
25651character_content:
25652
25653 if (vctxt->value != NULL) {
25654 xmlSchemaFreeValue(vctxt->value);
25655 vctxt->value = NULL;
25656 }
25657 /*
25658 * Check character content.
25659 */
25660 if (inode->decl == NULL) {
25661 /*
25662 * Speedup if no declaration exists.
25663 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025664 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025665 ret = xmlSchemaVCheckINodeDataType(vctxt,
25666 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025667 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025668 ret = xmlSchemaVCheckINodeDataType(vctxt,
25669 inode, inode->typeDef->contentTypeDef,
25670 inode->value);
25671 }
25672 if (ret < 0) {
25673 VERROR_INT("xmlSchemaValidatorPopElem",
25674 "calling xmlSchemaVCheckCVCSimpleType()");
25675 goto internal_error;
25676 }
25677 goto end_elem;
25678 }
25679 /*
25680 * cvc-elt (3.3.4) : 5
25681 * The appropriate case among the following must be true:
25682 */
25683 /*
25684 * cvc-elt (3.3.4) : 5.1
25685 * If the declaration has a {value constraint},
25686 * the item has neither element nor character [children] and
25687 * clause 3.2 has not applied, then all of the following must be true:
25688 */
25689 if ((inode->decl->value != NULL) &&
25690 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25691 (! INODE_NILLED(inode))) {
25692 /*
25693 * cvc-elt (3.3.4) : 5.1.1
25694 * If the ·actual type definition· is a ·local type definition·
25695 * then the canonical lexical representation of the {value constraint}
25696 * value must be a valid default for the ·actual type definition· as
25697 * defined in Element Default Valid (Immediate) (§3.3.6).
25698 */
25699 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025700 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025701 * NOTE: Although the *canonical* value is stated, it is not
25702 * relevant if canonical or not. Additionally XML Schema 1.1
25703 * will removed this requirement as well.
25704 */
25705 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25706
25707 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25708 inode->decl->value, &(inode->val));
25709 if (ret != 0) {
25710 if (ret < 0) {
25711 VERROR_INT("xmlSchemaValidatorPopElem",
25712 "calling xmlSchemaCheckCOSValidDefault()");
25713 goto internal_error;
25714 }
25715 goto end_elem;
25716 }
25717 /*
25718 * Stop here, to avoid redundant validation of the value
25719 * (see following).
25720 */
25721 goto default_psvi;
25722 }
25723 /*
25724 * cvc-elt (3.3.4) : 5.1.2
25725 * The element information item with the canonical lexical
25726 * representation of the {value constraint} value used as its
25727 * ·normalized value· must be ·valid· with respect to the
25728 * ·actual type definition· as defined by Element Locally Valid (Type)
25729 * (§3.3.4).
25730 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025731 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025732 ret = xmlSchemaVCheckINodeDataType(vctxt,
25733 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025734 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025735 ret = xmlSchemaVCheckINodeDataType(vctxt,
25736 inode, inode->typeDef->contentTypeDef,
25737 inode->decl->value);
25738 }
25739 if (ret != 0) {
25740 if (ret < 0) {
25741 VERROR_INT("xmlSchemaValidatorPopElem",
25742 "calling xmlSchemaVCheckCVCSimpleType()");
25743 goto internal_error;
25744 }
25745 goto end_elem;
25746 }
25747
25748default_psvi:
25749 /*
25750 * PSVI: Create a text node on the instance element.
25751 */
25752 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25753 (inode->node != NULL)) {
25754 xmlNodePtr textChild;
25755 xmlChar *normValue;
25756 /*
25757 * VAL TODO: Normalize the value.
25758 */
25759 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25760 inode->decl->value);
25761 if (normValue != NULL) {
25762 textChild = xmlNewText(BAD_CAST normValue);
25763 xmlFree(normValue);
25764 } else
25765 textChild = xmlNewText(inode->decl->value);
25766 if (textChild == NULL) {
25767 VERROR_INT("xmlSchemaValidatorPopElem",
25768 "calling xmlNewText()");
25769 goto internal_error;
25770 } else
25771 xmlAddChild(inode->node, textChild);
25772 }
25773
25774 } else if (! INODE_NILLED(inode)) {
25775 /*
25776 * 5.2.1 The element information item must be ·valid· with respect
25777 * to the ·actual type definition· as defined by Element Locally
25778 * Valid (Type) (§3.3.4).
25779 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025780 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025781 /*
25782 * SPEC (cvc-type) (3.1)
25783 * "If the type definition is a simple type definition, ..."
25784 * (3.1.3) "If clause 3.2 of Element Locally Valid
25785 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25786 * must be ·valid· with respect to the type definition as defined
25787 * by String Valid (§3.14.4).
25788 */
25789 ret = xmlSchemaVCheckINodeDataType(vctxt,
25790 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025791 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025792 /*
25793 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25794 * definition, then the element information item must be
25795 * ·valid· with respect to the type definition as per
25796 * Element Locally Valid (Complex Type) (§3.4.4);"
25797 *
25798 * SPEC (cvc-complex-type) (2.2)
25799 * "If the {content type} is a simple type definition, ...
25800 * the ·normalized value· of the element information item is
25801 * ·valid· with respect to that simple type definition as
25802 * defined by String Valid (§3.14.4)."
25803 */
25804 ret = xmlSchemaVCheckINodeDataType(vctxt,
25805 inode, inode->typeDef->contentTypeDef, inode->value);
25806 }
25807 if (ret != 0) {
25808 if (ret < 0) {
25809 VERROR_INT("xmlSchemaValidatorPopElem",
25810 "calling xmlSchemaVCheckCVCSimpleType()");
25811 goto internal_error;
25812 }
25813 goto end_elem;
25814 }
25815 /*
25816 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25817 * not applied, all of the following must be true:
25818 */
25819 if ((inode->decl->value != NULL) &&
25820 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25821
25822 /*
25823 * TODO: We will need a computed value, when comparison is
25824 * done on computed values.
25825 */
25826 /*
25827 * 5.2.2.1 The element information item must have no element
25828 * information item [children].
25829 */
25830 if (inode->flags &
25831 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25832 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25833 VERROR(ret, NULL,
25834 "The content must not containt element nodes since "
25835 "there is a fixed value constraint");
25836 goto end_elem;
25837 } else {
25838 /*
25839 * 5.2.2.2 The appropriate case among the following must
25840 * be true:
25841 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025842 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025843 /*
25844 * 5.2.2.2.1 If the {content type} of the ·actual type
25845 * definition· is mixed, then the *initial value* of the
25846 * item must match the canonical lexical representation
25847 * of the {value constraint} value.
25848 *
25849 * ... the *initial value* of an element information
25850 * item is the string composed of, in order, the
25851 * [character code] of each character information item in
25852 * the [children] of that element information item.
25853 */
25854 if (! xmlStrEqual(inode->value, inode->decl->value)){
25855 /*
25856 * VAL TODO: Report invalid & expected values as well.
25857 * VAL TODO: Implement the canonical stuff.
25858 */
25859 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025860 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025861 ret, NULL, NULL,
25862 "The initial value '%s' does not match the fixed "
25863 "value constraint '%s'",
25864 inode->value, inode->decl->value);
25865 goto end_elem;
25866 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025867 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025868 /*
25869 * 5.2.2.2.2 If the {content type} of the ·actual type
25870 * definition· is a simple type definition, then the
25871 * *actual value* of the item must match the canonical
25872 * lexical representation of the {value constraint} value.
25873 */
25874 /*
25875 * VAL TODO: *actual value* is the normalized value, impl.
25876 * this.
25877 * VAL TODO: Report invalid & expected values as well.
25878 * VAL TODO: Implement a comparison with the computed values.
25879 */
25880 if (! xmlStrEqual(inode->value,
25881 inode->decl->value)) {
25882 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025883 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025884 ret, NULL, NULL,
25885 "The actual value '%s' does not match the fixed "
25886 "value constraint '%s'",
25887 inode->value,
25888 inode->decl->value);
25889 goto end_elem;
25890 }
25891 }
25892 }
25893 }
25894 }
25895
25896end_elem:
25897 if (vctxt->depth < 0) {
25898 /* TODO: raise error? */
25899 return (0);
25900 }
25901 if (vctxt->depth == vctxt->skipDepth)
25902 vctxt->skipDepth = -1;
25903 /*
25904 * Evaluate the history of XPath state objects.
25905 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025906 if (inode->appliedXPath &&
25907 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025908 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025909 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025910 * MAYBE TODO:
25911 * SPEC (6) "The element information item must be ·valid· with
25912 * respect to each of the {identity-constraint definitions} as per
25913 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025914 */
25915 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025916 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25917 * need to be built in any case.
25918 * We will currently build IDC node-tables and bubble them only if
25919 * keyrefs do exist.
25920 */
25921
25922 /*
25923 * Add the current IDC target-nodes to the IDC node-tables.
25924 */
25925 if ((inode->idcMatchers != NULL) &&
25926 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25927 {
25928 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25929 goto internal_error;
25930 }
25931 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025932 * Validate IDC keyrefs.
25933 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025934 if (vctxt->inode->hasKeyrefs)
25935 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25936 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025937 /*
25938 * Merge/free the IDC table.
25939 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025940 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025941#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025942 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025943 inode->nsName,
25944 inode->localName,
25945 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025946#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025947 if ((vctxt->depth > 0) &&
25948 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25949 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025950 /*
25951 * Merge the IDC node table with the table of the parent node.
25952 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025953 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25954 goto internal_error;
25955 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025956 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025957 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025958 * Clear the current ielem.
25959 * VAL TODO: Don't free the PSVI IDC tables if they are
25960 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025961 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025962 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025963 /*
25964 * Skip further processing if we are on the validation root.
25965 */
25966 if (vctxt->depth == 0) {
25967 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025968 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025969 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025970 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025971 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025972 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025973 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025974 if (vctxt->aidcs != NULL) {
25975 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25976 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025977 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025978 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025979 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025980 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025981 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025982 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025983 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025984 }
25985 aidc = aidc->next;
25986 } while (aidc != NULL);
25987 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025988 vctxt->depth--;
25989 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025990 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025991 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025992 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25993 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025994 return (ret);
25995
25996internal_error:
25997 vctxt->err = -1;
25998 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025999}
26000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026001/*
26002* 3.4.4 Complex Type Definition Validation Rules
26003* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26004*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026005static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026007{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026008 xmlSchemaNodeInfoPtr pielem;
26009 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026010 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026011
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026012 if (vctxt->depth <= 0) {
26013 VERROR_INT("xmlSchemaValidateChildElem",
26014 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026015 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026016 }
26017 pielem = vctxt->elemInfos[vctxt->depth -1];
26018 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26019 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026020 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026021 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026022 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026023 if (INODE_NILLED(pielem)) {
26024 /*
26025 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26026 */
26027 ACTIVATE_PARENT_ELEM;
26028 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26029 VERROR(ret, NULL,
26030 "Neither character nor element content is allowed, "
26031 "because the element was 'nilled'");
26032 ACTIVATE_ELEM;
26033 goto unexpected_elem;
26034 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026035
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026036 ptype = pielem->typeDef;
26037
26038 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26039 /*
26040 * Workaround for "anyType": we have currently no content model
26041 * assigned for "anyType", so handle it explicitely.
26042 * "anyType" has an unbounded, lax "any" wildcard.
26043 */
26044 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26045 vctxt->inode->localName,
26046 vctxt->inode->nsName);
26047
26048 if (vctxt->inode->decl == NULL) {
26049 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026050 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026051 * Process "xsi:type".
26052 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026053 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026054 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26055 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26056 if (iattr != NULL) {
26057 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26058 &(vctxt->inode->typeDef), NULL);
26059 if (ret != 0) {
26060 if (ret == -1) {
26061 VERROR_INT("xmlSchemaValidateChildElem",
26062 "calling xmlSchemaProcessXSIType() to "
26063 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026064 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026065 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026066 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026068 } else {
26069 /*
26070 * Fallback to "anyType".
26071 *
26072 * SPEC (cvc-assess-elt)
26073 * "If the item cannot be ·strictly assessed·, [...]
26074 * an element information item's schema validity may be laxly
26075 * assessed if its ·context-determined declaration· is not
26076 * skip by ·validating· with respect to the ·ur-type
26077 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26078 */
26079 vctxt->inode->typeDef =
26080 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026081 }
26082 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026083 return (0);
26084 }
26085
26086 switch (ptype->contentType) {
26087 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026088 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026089 * SPEC (2.1) "If the {content type} is empty, then the
26090 * element information item has no character or element
26091 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026092 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026093 ACTIVATE_PARENT_ELEM
26094 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26095 VERROR(ret, NULL,
26096 "Element content is not allowed, "
26097 "because the content type is empty");
26098 ACTIVATE_ELEM
26099 goto unexpected_elem;
26100 break;
26101
26102 case XML_SCHEMA_CONTENT_MIXED:
26103 case XML_SCHEMA_CONTENT_ELEMENTS: {
26104 xmlRegExecCtxtPtr regexCtxt;
26105 xmlChar *values[10];
26106 int terminal, nbval = 10, nbneg;
26107
26108 /* VAL TODO: Optimized "anyType" validation.*/
26109
26110 if (ptype->contModel == NULL) {
26111 VERROR_INT("xmlSchemaValidateChildElem",
26112 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026113 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026114 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026115 /*
26116 * Safety belf for evaluation if the cont. model was already
26117 * examined to be invalid.
26118 */
26119 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26120 VERROR_INT("xmlSchemaValidateChildElem",
26121 "validating elem, but elem content is already invalid");
26122 return (-1);
26123 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026124
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026125 regexCtxt = pielem->regexCtxt;
26126 if (regexCtxt == NULL) {
26127 /*
26128 * Create the regex context.
26129 */
26130 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26131 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26132 vctxt);
26133 if (regexCtxt == NULL) {
26134 VERROR_INT("xmlSchemaValidateChildElem",
26135 "failed to create a regex context");
26136 return (-1);
26137 }
26138 pielem->regexCtxt = regexCtxt;
26139#ifdef DEBUG_AUTOMATA
26140 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26141 pielem->localName);
26142#endif
26143 }
26144
26145 /*
26146 * SPEC (2.4) "If the {content type} is element-only or mixed,
26147 * then the sequence of the element information item's
26148 * element information item [children], if any, taken in
26149 * order, is ·valid· with respect to the {content type}'s
26150 * particle, as defined in Element Sequence Locally Valid
26151 * (Particle) (§3.9.4)."
26152 */
26153 ret = xmlRegExecPushString2(regexCtxt,
26154 vctxt->inode->localName,
26155 vctxt->inode->nsName,
26156 vctxt->inode);
26157#ifdef DEBUG_AUTOMATA
26158 if (ret < 0)
26159 xmlGenericError(xmlGenericErrorContext,
26160 "AUTOMATON push ERROR for '%s' on '%s'\n",
26161 vctxt->inode->localName, pielem->localName);
26162 else
26163 xmlGenericError(xmlGenericErrorContext,
26164 "AUTOMATON push OK for '%s' on '%s'\n",
26165 vctxt->inode->localName, pielem->localName);
26166#endif
26167 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26168 VERROR_INT("xmlSchemaValidateChildElem",
26169 "calling xmlRegExecPushString2()");
26170 return (-1);
26171 }
26172 if (ret < 0) {
26173 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26174 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026175 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026176 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26177 "This element is not expected",
26178 nbval, nbneg, values);
26179 ret = vctxt->err;
26180 goto unexpected_elem;
26181 } else
26182 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026183 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026184 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026185 case XML_SCHEMA_CONTENT_SIMPLE:
26186 case XML_SCHEMA_CONTENT_BASIC:
26187 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026188 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026189 /*
26190 * SPEC (cvc-complex-type) (2.2)
26191 * "If the {content type} is a simple type definition, then
26192 * the element information item has no element information
26193 * item [children], ..."
26194 */
26195 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26196 VERROR(ret, NULL, "Element content is not allowed, "
26197 "because the content type is a simple type definition");
26198 } else {
26199 /*
26200 * SPEC (cvc-type) (3.1.2) "The element information item must
26201 * have no element information item [children]."
26202 */
26203 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26204 VERROR(ret, NULL, "Element content is not allowed, "
26205 "because the type definition is simple");
26206 }
26207 ACTIVATE_ELEM
26208 ret = vctxt->err;
26209 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026210 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026211
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026212 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026213 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026214 }
26215 return (ret);
26216unexpected_elem:
26217 /*
26218 * Pop this element and set the skipDepth to skip
26219 * all further content of the parent element.
26220 */
26221 vctxt->skipDepth = vctxt->depth;
26222 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26223 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26224 return (ret);
26225}
26226
26227#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26228#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26229#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26230
26231static int
26232xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26233 int nodeType, const xmlChar *value, int len,
26234 int mode, int *consumed)
26235{
26236 /*
26237 * Unfortunately we have to duplicate the text sometimes.
26238 * OPTIMIZE: Maybe we could skip it, if:
26239 * 1. content type is simple
26240 * 2. whitespace is "collapse"
26241 * 3. it consists of whitespace only
26242 *
26243 * Process character content.
26244 */
26245 if (consumed != NULL)
26246 *consumed = 0;
26247 if (INODE_NILLED(vctxt->inode)) {
26248 /*
26249 * SPEC cvc-elt (3.3.4 - 3.2.1)
26250 * "The element information item must have no character or
26251 * element information item [children]."
26252 */
26253 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26254 "Neither character nor element content is allowed "
26255 "because the element is 'nilled'");
26256 return (vctxt->err);
26257 }
26258 /*
26259 * SPEC (2.1) "If the {content type} is empty, then the
26260 * element information item has no character or element
26261 * information item [children]."
26262 */
26263 if (vctxt->inode->typeDef->contentType ==
26264 XML_SCHEMA_CONTENT_EMPTY) {
26265 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26266 "Character content is not allowed, "
26267 "because the content type is empty");
26268 return (vctxt->err);
26269 }
26270
26271 if (vctxt->inode->typeDef->contentType ==
26272 XML_SCHEMA_CONTENT_ELEMENTS) {
26273 if ((nodeType != XML_TEXT_NODE) ||
26274 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26275 /*
26276 * SPEC cvc-complex-type (2.3)
26277 * "If the {content type} is element-only, then the
26278 * element information item has no character information
26279 * item [children] other than those whose [character
26280 * code] is defined as a white space in [XML 1.0 (Second
26281 * Edition)]."
26282 */
26283 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26284 "Character content other than whitespace is not allowed "
26285 "because the content type is 'element-only'");
26286 return (vctxt->err);
26287 }
26288 return (0);
26289 }
26290
26291 if ((value == NULL) || (value[0] == 0))
26292 return (0);
26293 /*
26294 * Save the value.
26295 * NOTE that even if the content type is *mixed*, we need the
26296 * *initial value* for default/fixed value constraints.
26297 */
26298 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26299 ((vctxt->inode->decl == NULL) ||
26300 (vctxt->inode->decl->value == NULL)))
26301 return (0);
26302
26303 if (vctxt->inode->value == NULL) {
26304 /*
26305 * Set the value.
26306 */
26307 switch (mode) {
26308 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26309 /*
26310 * When working on a tree.
26311 */
26312 vctxt->inode->value = value;
26313 break;
26314 case XML_SCHEMA_PUSH_TEXT_CREATED:
26315 /*
26316 * When working with the reader.
26317 * The value will be freed by the element info.
26318 */
26319 vctxt->inode->value = value;
26320 if (consumed != NULL)
26321 *consumed = 1;
26322 vctxt->inode->flags |=
26323 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26324 break;
26325 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26326 /*
26327 * When working with SAX.
26328 * The value will be freed by the element info.
26329 */
26330 if (len != -1)
26331 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26332 else
26333 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26334 vctxt->inode->flags |=
26335 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26336 break;
26337 default:
26338 break;
26339 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026340 } else {
26341 if (len < 0)
26342 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026343 /*
26344 * Concat the value.
26345 */
26346 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026347 vctxt->inode->value = BAD_CAST xmlStrncat(
26348 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026349 } else {
26350 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026351 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026352 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26353 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026354 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026355
26356 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026357}
26358
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026359static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026360xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026361{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026362 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026363
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026364 if ((vctxt->skipDepth != -1) &&
26365 (vctxt->depth >= vctxt->skipDepth)) {
26366 VERROR_INT("xmlSchemaValidateElem",
26367 "in skip-state");
26368 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026370 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026371 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026372 * We will stop validation if there was an error during
26373 * dynamic schema construction.
26374 * Note that we simply set @skipDepth to 0, this could
26375 * mean that a streaming document via SAX would be
26376 * still read to the end but it won't be validated any more.
26377 * TODO: If we are sure how to stop the validation at once
26378 * for all input scenarios, then this should be changed to
26379 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026380 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026381 ret = xmlSchemaAssembleByXSI(vctxt);
26382 if (ret != 0) {
26383 if (ret == -1)
26384 goto internal_error;
26385 vctxt->skipDepth = 0;
26386 return(ret);
26387 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026388 }
26389 if (vctxt->depth > 0) {
26390 /*
26391 * Validate this element against the content model
26392 * of the parent.
26393 */
26394 ret = xmlSchemaValidateChildElem(vctxt);
26395 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026396 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026397 VERROR_INT("xmlSchemaValidateElem",
26398 "calling xmlSchemaStreamValidateChildElement()");
26399 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026401 goto exit;
26402 }
26403 if (vctxt->depth == vctxt->skipDepth)
26404 goto exit;
26405 if ((vctxt->inode->decl == NULL) &&
26406 (vctxt->inode->typeDef == NULL)) {
26407 VERROR_INT("xmlSchemaValidateElem",
26408 "the child element was valid but neither the "
26409 "declaration nor the type was set");
26410 goto internal_error;
26411 }
26412 } else {
26413 /*
26414 * Get the declaration of the validation root.
26415 */
26416 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26417 vctxt->inode->localName,
26418 vctxt->inode->nsName);
26419 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026420 ret = XML_SCHEMAV_CVC_ELT_1;
26421 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026422 "No matching global declaration available "
26423 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026424 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026425 }
26426 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026427
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026428 if (vctxt->inode->decl == NULL)
26429 goto type_validation;
26430
26431 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26432 int skip;
26433 /*
26434 * Wildcards.
26435 */
26436 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26437 if (ret != 0) {
26438 if (ret < 0) {
26439 VERROR_INT("xmlSchemaValidateElem",
26440 "calling xmlSchemaValidateElemWildcard()");
26441 goto internal_error;
26442 }
26443 goto exit;
26444 }
26445 if (skip) {
26446 vctxt->skipDepth = vctxt->depth;
26447 goto exit;
26448 }
26449 /*
26450 * The declaration might be set by the wildcard validation,
26451 * when the processContents is "lax" or "strict".
26452 */
26453 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26454 /*
26455 * Clear the "decl" field to not confuse further processing.
26456 */
26457 vctxt->inode->decl = NULL;
26458 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026459 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026460 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026461 /*
26462 * Validate against the declaration.
26463 */
26464 ret = xmlSchemaValidateElemDecl(vctxt);
26465 if (ret != 0) {
26466 if (ret < 0) {
26467 VERROR_INT("xmlSchemaValidateElem",
26468 "calling xmlSchemaValidateElemDecl()");
26469 goto internal_error;
26470 }
26471 goto exit;
26472 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026473 /*
26474 * Validate against the type definition.
26475 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026476type_validation:
26477
26478 if (vctxt->inode->typeDef == NULL) {
26479 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26480 ret = XML_SCHEMAV_CVC_TYPE_1;
26481 VERROR(ret, NULL,
26482 "The type definition is absent");
26483 goto exit;
26484 }
26485 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26486 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26487 ret = XML_SCHEMAV_CVC_TYPE_2;
26488 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026489 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026490 goto exit;
26491 }
26492 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026493 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026494 * during validation against the declaration. This must be done
26495 * _before_ attribute validation.
26496 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026497 if (vctxt->xpathStates != NULL) {
26498 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026499 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026500 if (ret == -1) {
26501 VERROR_INT("xmlSchemaValidateElem",
26502 "calling xmlSchemaXPathEvaluate()");
26503 goto internal_error;
26504 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026505 }
26506 /*
26507 * Validate attributes.
26508 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026509 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026510 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026511 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026512
26513 ret = xmlSchemaVAttributesComplex(vctxt);
26514 }
26515 } else if (vctxt->nbAttrInfos != 0) {
26516
26517 ret = xmlSchemaVAttributesSimple(vctxt);
26518 }
26519 /*
26520 * Clear registered attributes.
26521 */
26522 if (vctxt->nbAttrInfos != 0)
26523 xmlSchemaClearAttrInfos(vctxt);
26524 if (ret == -1) {
26525 VERROR_INT("xmlSchemaValidateElem",
26526 "calling attributes validation");
26527 goto internal_error;
26528 }
26529 /*
26530 * Don't return an error if attributes are invalid on purpose.
26531 */
26532 ret = 0;
26533
26534exit:
26535 if (ret != 0)
26536 vctxt->skipDepth = vctxt->depth;
26537 return (ret);
26538internal_error:
26539 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026540}
26541
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026542#ifdef XML_SCHEMA_READER_ENABLED
26543static int
26544xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026545{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026546 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26547 int depth, nodeType, ret = 0, consumed;
26548 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026549
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026550 vctxt->depth = -1;
26551 ret = xmlTextReaderRead(vctxt->reader);
26552 /*
26553 * Move to the document element.
26554 */
26555 while (ret == 1) {
26556 nodeType = xmlTextReaderNodeType(vctxt->reader);
26557 if (nodeType == XML_ELEMENT_NODE)
26558 goto root_found;
26559 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026560 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026561 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026562
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026563root_found:
26564
26565 do {
26566 depth = xmlTextReaderDepth(vctxt->reader);
26567 nodeType = xmlTextReaderNodeType(vctxt->reader);
26568
26569 if (nodeType == XML_ELEMENT_NODE) {
26570
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026571 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026572 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26573 VERROR_INT("xmlSchemaVReaderWalk",
26574 "calling xmlSchemaValidatorPushElem()");
26575 goto internal_error;
26576 }
26577 ielem = vctxt->inode;
26578 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26579 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26580 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26581 /*
26582 * Is the element empty?
26583 */
26584 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26585 if (ret == -1) {
26586 VERROR_INT("xmlSchemaVReaderWalk",
26587 "calling xmlTextReaderIsEmptyElement()");
26588 goto internal_error;
26589 }
26590 if (ret) {
26591 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26592 }
26593 /*
26594 * Register attributes.
26595 */
26596 vctxt->nbAttrInfos = 0;
26597 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26598 if (ret == -1) {
26599 VERROR_INT("xmlSchemaVReaderWalk",
26600 "calling xmlTextReaderMoveToFirstAttribute()");
26601 goto internal_error;
26602 }
26603 if (ret == 1) {
26604 do {
26605 /*
26606 * VAL TODO: How do we know that the reader works on a
26607 * node tree, to be able to pass a node here?
26608 */
26609 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26610 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26611 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26612 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26613
26614 VERROR_INT("xmlSchemaVReaderWalk",
26615 "calling xmlSchemaValidatorPushAttribute()");
26616 goto internal_error;
26617 }
26618 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26619 if (ret == -1) {
26620 VERROR_INT("xmlSchemaVReaderWalk",
26621 "calling xmlTextReaderMoveToFirstAttribute()");
26622 goto internal_error;
26623 }
26624 } while (ret == 1);
26625 /*
26626 * Back to element position.
26627 */
26628 ret = xmlTextReaderMoveToElement(vctxt->reader);
26629 if (ret == -1) {
26630 VERROR_INT("xmlSchemaVReaderWalk",
26631 "calling xmlTextReaderMoveToElement()");
26632 goto internal_error;
26633 }
26634 }
26635 /*
26636 * Validate the element.
26637 */
26638 ret= xmlSchemaValidateElem(vctxt);
26639 if (ret != 0) {
26640 if (ret == -1) {
26641 VERROR_INT("xmlSchemaVReaderWalk",
26642 "calling xmlSchemaValidateElem()");
26643 goto internal_error;
26644 }
26645 goto exit;
26646 }
26647 if (vctxt->depth == vctxt->skipDepth) {
26648 int curDepth;
26649 /*
26650 * Skip all content.
26651 */
26652 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26653 ret = xmlTextReaderRead(vctxt->reader);
26654 curDepth = xmlTextReaderDepth(vctxt->reader);
26655 while ((ret == 1) && (curDepth != depth)) {
26656 ret = xmlTextReaderRead(vctxt->reader);
26657 curDepth = xmlTextReaderDepth(vctxt->reader);
26658 }
26659 if (ret < 0) {
26660 /*
26661 * VAL TODO: A reader error occured; what to do here?
26662 */
26663 ret = 1;
26664 goto exit;
26665 }
26666 }
26667 goto leave_elem;
26668 }
26669 /*
26670 * READER VAL TODO: Is an END_ELEM really never called
26671 * if the elem is empty?
26672 */
26673 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26674 goto leave_elem;
26675 } else if (nodeType == END_ELEM) {
26676 /*
26677 * Process END of element.
26678 */
26679leave_elem:
26680 ret = xmlSchemaValidatorPopElem(vctxt);
26681 if (ret != 0) {
26682 if (ret < 0) {
26683 VERROR_INT("xmlSchemaVReaderWalk",
26684 "calling xmlSchemaValidatorPopElem()");
26685 goto internal_error;
26686 }
26687 goto exit;
26688 }
26689 if (vctxt->depth >= 0)
26690 ielem = vctxt->inode;
26691 else
26692 ielem = NULL;
26693 } else if ((nodeType == XML_TEXT_NODE) ||
26694 (nodeType == XML_CDATA_SECTION_NODE) ||
26695 (nodeType == WHTSP) ||
26696 (nodeType == SIGN_WHTSP)) {
26697 /*
26698 * Process character content.
26699 */
26700 xmlChar *value;
26701
26702 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26703 nodeType = XML_TEXT_NODE;
26704
26705 value = xmlTextReaderValue(vctxt->reader);
26706 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26707 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26708 if (! consumed)
26709 xmlFree(value);
26710 if (ret == -1) {
26711 VERROR_INT("xmlSchemaVReaderWalk",
26712 "calling xmlSchemaVPushText()");
26713 goto internal_error;
26714 }
26715 } else if ((nodeType == XML_ENTITY_NODE) ||
26716 (nodeType == XML_ENTITY_REF_NODE)) {
26717 /*
26718 * VAL TODO: What to do with entities?
26719 */
26720 TODO
26721 }
26722 /*
26723 * Read next node.
26724 */
26725 ret = xmlTextReaderRead(vctxt->reader);
26726 } while (ret == 1);
26727
26728exit:
26729 return (ret);
26730internal_error:
26731 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026732}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026733#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026734
26735/************************************************************************
26736 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026737 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026738 * *
26739 ************************************************************************/
26740
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026741/*
26742* Process text content.
26743*/
26744static void
26745xmlSchemaSAXHandleText(void *ctx,
26746 const xmlChar * ch,
26747 int len)
26748{
26749 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26750
26751 if (vctxt->depth < 0)
26752 return;
26753 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26754 return;
26755 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26756 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26757 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26758 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26759 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26760 "calling xmlSchemaVPushText()");
26761 vctxt->err = -1;
26762 xmlStopParser(vctxt->parserCtxt);
26763 }
26764}
26765
26766/*
26767* Process CDATA content.
26768*/
26769static void
26770xmlSchemaSAXHandleCDataSection(void *ctx,
26771 const xmlChar * ch,
26772 int len)
26773{
26774 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26775
26776 if (vctxt->depth < 0)
26777 return;
26778 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26779 return;
26780 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26781 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26782 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26783 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26784 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26785 "calling xmlSchemaVPushText()");
26786 vctxt->err = -1;
26787 xmlStopParser(vctxt->parserCtxt);
26788 }
26789}
26790
26791static void
26792xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26793 const xmlChar * name ATTRIBUTE_UNUSED)
26794{
26795 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26796
26797 if (vctxt->depth < 0)
26798 return;
26799 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26800 return;
26801 /* SAX VAL TODO: What to do here? */
26802 TODO
26803}
26804
26805static void
26806xmlSchemaSAXHandleStartElementNs(void *ctx,
26807 const xmlChar * localname,
26808 const xmlChar * prefix ATTRIBUTE_UNUSED,
26809 const xmlChar * URI,
26810 int nb_namespaces,
26811 const xmlChar ** namespaces,
26812 int nb_attributes,
26813 int nb_defaulted ATTRIBUTE_UNUSED,
26814 const xmlChar ** attributes)
26815{
26816 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26817 int ret;
26818 xmlSchemaNodeInfoPtr ielem;
26819 int i, j;
26820
26821 /*
26822 * SAX VAL TODO: What to do with nb_defaulted?
26823 */
26824 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026825 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026826 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026827 vctxt->depth++;
26828 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026829 return;
26830 /*
26831 * Push the element.
26832 */
26833 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26834 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26835 "calling xmlSchemaValidatorPushElem()");
26836 goto internal_error;
26837 }
26838 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026839 /*
26840 * TODO: Is this OK?
26841 */
26842 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026843 ielem->localName = localname;
26844 ielem->nsName = URI;
26845 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26846 /*
26847 * Register namespaces on the elem info.
26848 */
26849 if (nb_namespaces != 0) {
26850 /*
26851 * Although the parser builds its own namespace list,
26852 * we have no access to it, so we'll use an own one.
26853 */
26854 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26855 /*
26856 * Store prefix and namespace name.
26857 */
26858 if (ielem->nsBindings == NULL) {
26859 ielem->nsBindings =
26860 (const xmlChar **) xmlMalloc(10 *
26861 sizeof(const xmlChar *));
26862 if (ielem->nsBindings == NULL) {
26863 xmlSchemaVErrMemory(vctxt,
26864 "allocating namespace bindings for SAX validation",
26865 NULL);
26866 goto internal_error;
26867 }
26868 ielem->nbNsBindings = 0;
26869 ielem->sizeNsBindings = 5;
26870 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26871 ielem->sizeNsBindings *= 2;
26872 ielem->nsBindings =
26873 (const xmlChar **) xmlRealloc(
26874 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026875 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026876 if (ielem->nsBindings == NULL) {
26877 xmlSchemaVErrMemory(vctxt,
26878 "re-allocating namespace bindings for SAX validation",
26879 NULL);
26880 goto internal_error;
26881 }
26882 }
26883
26884 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26885 if (namespaces[j+1][0] == 0) {
26886 /*
26887 * Handle xmlns="".
26888 */
26889 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26890 } else
26891 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26892 namespaces[j+1];
26893 ielem->nbNsBindings++;
26894 }
26895 }
26896 /*
26897 * Register attributes.
26898 * SAX VAL TODO: We are not adding namespace declaration
26899 * attributes yet.
26900 */
26901 if (nb_attributes != 0) {
26902 xmlChar *value;
26903
26904 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26905 /*
26906 * Duplicate the value.
26907 */
26908 value = xmlStrndup(attributes[j+3],
26909 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026910 /*
26911 * TODO: Set the node line.
26912 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026913 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026914 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026915 value, 1);
26916 if (ret == -1) {
26917 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26918 "calling xmlSchemaValidatorPushAttribute()");
26919 goto internal_error;
26920 }
26921 }
26922 }
26923 /*
26924 * Validate the element.
26925 */
26926 ret = xmlSchemaValidateElem(vctxt);
26927 if (ret != 0) {
26928 if (ret == -1) {
26929 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26930 "calling xmlSchemaValidateElem()");
26931 goto internal_error;
26932 }
26933 goto exit;
26934 }
26935
26936exit:
26937 return;
26938internal_error:
26939 vctxt->err = -1;
26940 xmlStopParser(vctxt->parserCtxt);
26941 return;
26942}
26943
26944static void
26945xmlSchemaSAXHandleEndElementNs(void *ctx,
26946 const xmlChar * localname ATTRIBUTE_UNUSED,
26947 const xmlChar * prefix ATTRIBUTE_UNUSED,
26948 const xmlChar * URI ATTRIBUTE_UNUSED)
26949{
26950 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26951 int res;
26952
26953 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026954 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026955 */
26956 if (vctxt->skipDepth != -1) {
26957 if (vctxt->depth > vctxt->skipDepth) {
26958 vctxt->depth--;
26959 return;
26960 } else
26961 vctxt->skipDepth = -1;
26962 }
26963 /*
26964 * SAX VAL TODO: Just a temporary check.
26965 */
26966 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26967 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26968 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26969 "elem pop mismatch");
26970 }
26971 res = xmlSchemaValidatorPopElem(vctxt);
26972 if (res != 0) {
26973 if (res < 0) {
26974 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26975 "calling xmlSchemaValidatorPopElem()");
26976 goto internal_error;
26977 }
26978 goto exit;
26979 }
26980exit:
26981 return;
26982internal_error:
26983 vctxt->err = -1;
26984 xmlStopParser(vctxt->parserCtxt);
26985 return;
26986}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026987
Daniel Veillard4255d502002-04-16 15:50:10 +000026988/************************************************************************
26989 * *
26990 * Validation interfaces *
26991 * *
26992 ************************************************************************/
26993
26994/**
26995 * xmlSchemaNewValidCtxt:
26996 * @schema: a precompiled XML Schemas
26997 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026998 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026999 *
27000 * Returns the validation context or NULL in case of error
27001 */
27002xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027003xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27004{
Daniel Veillard4255d502002-04-16 15:50:10 +000027005 xmlSchemaValidCtxtPtr ret;
27006
27007 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27008 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027009 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027010 return (NULL);
27011 }
27012 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027013 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027014 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027015 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027016 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027017 return (ret);
27018}
27019
27020/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027021 * xmlSchemaClearValidCtxt:
27022 * @ctxt: the schema validation context
27023 *
27024 * Free the resources associated to the schema validation context;
27025 * leaves some fields alive intended for reuse of the context.
27026 */
27027static void
27028xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27029{
27030 if (vctxt == NULL)
27031 return;
27032
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027033 /*
27034 * TODO: Should we clear the flags?
27035 * Might be problematic if one reuses the context
27036 * and assumes that the options remain the same.
27037 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027038 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027039 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027040 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027041#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027042 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027043#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027044 vctxt->hasKeyrefs = 0;
27045
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027046 if (vctxt->value != NULL) {
27047 xmlSchemaFreeValue(vctxt->value);
27048 vctxt->value = NULL;
27049 }
27050 /*
27051 * Augmented IDC information.
27052 */
27053 if (vctxt->aidcs != NULL) {
27054 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27055 do {
27056 next = cur->next;
27057 xmlFree(cur);
27058 cur = next;
27059 } while (cur != NULL);
27060 vctxt->aidcs = NULL;
27061 }
27062 if (vctxt->idcNodes != NULL) {
27063 int i;
27064 xmlSchemaPSVIIDCNodePtr item;
27065
27066 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027067 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027068 xmlFree(item->keys);
27069 xmlFree(item);
27070 }
27071 xmlFree(vctxt->idcNodes);
27072 vctxt->idcNodes = NULL;
27073 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027074 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027075 * Note that we won't delete the XPath state pool here.
27076 */
27077 if (vctxt->xpathStates != NULL) {
27078 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27079 vctxt->xpathStates = NULL;
27080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027081 /*
27082 * Attribute info.
27083 */
27084 if (vctxt->nbAttrInfos != 0) {
27085 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027086 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027087 /*
27088 * Element info.
27089 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027090 if (vctxt->elemInfos != NULL) {
27091 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027092 xmlSchemaNodeInfoPtr ei;
27093
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027094 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027095 ei = vctxt->elemInfos[i];
27096 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027097 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027098 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027099 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027100 }
27101 xmlSchemaItemListClear(vctxt->nodeQNames);
27102 /* Recreate the dict. */
27103 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027104 /*
27105 * TODO: Is is save to recreate it? Do we have a scenario
27106 * where the user provides the dict?
27107 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027108 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027109}
27110
27111/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027112 * xmlSchemaFreeValidCtxt:
27113 * @ctxt: the schema validation context
27114 *
27115 * Free the resources associated to the schema validation context
27116 */
27117void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027118xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27119{
Daniel Veillard4255d502002-04-16 15:50:10 +000027120 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027121 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027122 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027123 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027124 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027125 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027126 if (ctxt->idcNodes != NULL) {
27127 int i;
27128 xmlSchemaPSVIIDCNodePtr item;
27129
27130 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027131 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027132 xmlFree(item->keys);
27133 xmlFree(item);
27134 }
27135 xmlFree(ctxt->idcNodes);
27136 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027137 if (ctxt->idcKeys != NULL) {
27138 int i;
27139 for (i = 0; i < ctxt->nbIdcKeys; i++)
27140 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27141 xmlFree(ctxt->idcKeys);
27142 }
27143
27144 if (ctxt->xpathStates != NULL)
27145 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27146 if (ctxt->xpathStatePool != NULL)
27147 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27148
27149 /*
27150 * Augmented IDC information.
27151 */
27152 if (ctxt->aidcs != NULL) {
27153 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27154 do {
27155 next = cur->next;
27156 xmlFree(cur);
27157 cur = next;
27158 } while (cur != NULL);
27159 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027160 if (ctxt->attrInfos != NULL) {
27161 int i;
27162 xmlSchemaAttrInfoPtr attr;
27163
27164 /* Just a paranoid call to the cleanup. */
27165 if (ctxt->nbAttrInfos != 0)
27166 xmlSchemaClearAttrInfos(ctxt);
27167 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27168 attr = ctxt->attrInfos[i];
27169 xmlFree(attr);
27170 }
27171 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027172 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027173 if (ctxt->elemInfos != NULL) {
27174 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027175 xmlSchemaNodeInfoPtr ei;
27176
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027177 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027178 ei = ctxt->elemInfos[i];
27179 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027180 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027181 xmlSchemaClearElemInfo(ei);
27182 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027183 }
27184 xmlFree(ctxt->elemInfos);
27185 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027186 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027187 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027188 if (ctxt->dict != NULL)
27189 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027190 xmlFree(ctxt);
27191}
27192
27193/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027194 * xmlSchemaIsValid:
27195 * @ctxt: the schema validation context
27196 *
27197 * Check if any error was detected during validation.
27198 *
27199 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27200 * of internal error.
27201 */
27202int
27203xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27204{
27205 if (ctxt == NULL)
27206 return(-1);
27207 return(ctxt->err == 0);
27208}
27209
27210/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027211 * xmlSchemaSetValidErrors:
27212 * @ctxt: a schema validation context
27213 * @err: the error function
27214 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027215 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027216 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027217 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027218 */
27219void
27220xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027221 xmlSchemaValidityErrorFunc err,
27222 xmlSchemaValidityWarningFunc warn, void *ctx)
27223{
Daniel Veillard4255d502002-04-16 15:50:10 +000027224 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027225 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027226 ctxt->error = err;
27227 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027228 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027229 if (ctxt->pctxt != NULL)
27230 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027231}
27232
27233/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027234 * xmlSchemaSetValidStructuredErrors:
27235 * @ctxt: a schema validation context
27236 * @serror: the structured error function
27237 * @ctx: the functions context
27238 *
27239 * Set the structured error callback
27240 */
27241void
27242xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027243 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027244{
27245 if (ctxt == NULL)
27246 return;
27247 ctxt->serror = serror;
27248 ctxt->error = NULL;
27249 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027250 ctxt->errCtxt = ctx;
27251 if (ctxt->pctxt != NULL)
27252 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027253}
27254
27255/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027256 * xmlSchemaGetValidErrors:
27257 * @ctxt: a XML-Schema validation context
27258 * @err: the error function result
27259 * @warn: the warning function result
27260 * @ctx: the functions context result
27261 *
27262 * Get the error and warning callback informations
27263 *
27264 * Returns -1 in case of error and 0 otherwise
27265 */
27266int
27267xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027268 xmlSchemaValidityErrorFunc * err,
27269 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027270{
27271 if (ctxt == NULL)
27272 return (-1);
27273 if (err != NULL)
27274 *err = ctxt->error;
27275 if (warn != NULL)
27276 *warn = ctxt->warning;
27277 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027278 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027279 return (0);
27280}
27281
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027282
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027283/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027284 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027285 * @ctxt: a schema validation context
27286 * @options: a combination of xmlSchemaValidOption
27287 *
27288 * Sets the options to be used during the validation.
27289 *
27290 * Returns 0 in case of success, -1 in case of an
27291 * API error.
27292 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027293int
27294xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27295 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027296
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027297{
27298 int i;
27299
27300 if (ctxt == NULL)
27301 return (-1);
27302 /*
27303 * WARNING: Change the start value if adding to the
27304 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027305 * TODO: Is there an other, more easy to maintain,
27306 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027307 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027308 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027309 if (options & 1<<i)
27310 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027311 }
27312 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027313 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027314}
27315
27316/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027317 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027318 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027319 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027320 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027321 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027322 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027323 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027324int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027325xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027326
27327{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027328 if (ctxt == NULL)
27329 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027330 else
27331 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027332}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027333
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027334static int
27335xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27336{
27337 xmlAttrPtr attr;
27338 int ret = 0;
27339 xmlSchemaNodeInfoPtr ielem = NULL;
27340 xmlNodePtr node, valRoot;
27341 const xmlChar *nsName;
27342
27343 /* DOC VAL TODO: Move this to the start function. */
27344 valRoot = xmlDocGetRootElement(vctxt->doc);
27345 if (valRoot == NULL) {
27346 /* VAL TODO: Error code? */
27347 VERROR(1, NULL, "The document has no document element");
27348 return (1);
27349 }
27350 vctxt->depth = -1;
27351 vctxt->validationRoot = valRoot;
27352 node = valRoot;
27353 while (node != NULL) {
27354 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27355 goto next_sibling;
27356 if (node->type == XML_ELEMENT_NODE) {
27357
27358 /*
27359 * Init the node-info.
27360 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027361 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027362 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27363 goto internal_error;
27364 ielem = vctxt->inode;
27365 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027366 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027367 ielem->localName = node->name;
27368 if (node->ns != NULL)
27369 ielem->nsName = node->ns->href;
27370 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27371 /*
27372 * Register attributes.
27373 * DOC VAL TODO: We do not register namespace declaration
27374 * attributes yet.
27375 */
27376 vctxt->nbAttrInfos = 0;
27377 if (node->properties != NULL) {
27378 attr = node->properties;
27379 do {
27380 if (attr->ns != NULL)
27381 nsName = attr->ns->href;
27382 else
27383 nsName = NULL;
27384 ret = xmlSchemaValidatorPushAttribute(vctxt,
27385 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027386 /*
27387 * Note that we give it the line number of the
27388 * parent element.
27389 */
27390 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027391 attr->name, nsName, 0,
27392 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27393 if (ret == -1) {
27394 VERROR_INT("xmlSchemaDocWalk",
27395 "calling xmlSchemaValidatorPushAttribute()");
27396 goto internal_error;
27397 }
27398 attr = attr->next;
27399 } while (attr);
27400 }
27401 /*
27402 * Validate the element.
27403 */
27404 ret = xmlSchemaValidateElem(vctxt);
27405 if (ret != 0) {
27406 if (ret == -1) {
27407 VERROR_INT("xmlSchemaDocWalk",
27408 "calling xmlSchemaValidateElem()");
27409 goto internal_error;
27410 }
27411 /*
27412 * Don't stop validation; just skip the content
27413 * of this element.
27414 */
27415 goto leave_node;
27416 }
27417 if ((vctxt->skipDepth != -1) &&
27418 (vctxt->depth >= vctxt->skipDepth))
27419 goto leave_node;
27420 } else if ((node->type == XML_TEXT_NODE) ||
27421 (node->type == XML_CDATA_SECTION_NODE)) {
27422 /*
27423 * Process character content.
27424 */
27425 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27426 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27427 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27428 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27429 if (ret < 0) {
27430 VERROR_INT("xmlSchemaVDocWalk",
27431 "calling xmlSchemaVPushText()");
27432 goto internal_error;
27433 }
27434 /*
27435 * DOC VAL TODO: Should we skip further validation of the
27436 * element content here?
27437 */
27438 } else if ((node->type == XML_ENTITY_NODE) ||
27439 (node->type == XML_ENTITY_REF_NODE)) {
27440 /*
27441 * DOC VAL TODO: What to do with entities?
27442 */
27443 TODO
27444 } else {
27445 goto leave_node;
27446 /*
27447 * DOC VAL TODO: XInclude nodes, etc.
27448 */
27449 }
27450 /*
27451 * Walk the doc.
27452 */
27453 if (node->children != NULL) {
27454 node = node->children;
27455 continue;
27456 }
27457leave_node:
27458 if (node->type == XML_ELEMENT_NODE) {
27459 /*
27460 * Leaving the scope of an element.
27461 */
27462 if (node != vctxt->inode->node) {
27463 VERROR_INT("xmlSchemaVDocWalk",
27464 "element position mismatch");
27465 goto internal_error;
27466 }
27467 ret = xmlSchemaValidatorPopElem(vctxt);
27468 if (ret != 0) {
27469 if (ret < 0) {
27470 VERROR_INT("xmlSchemaVDocWalk",
27471 "calling xmlSchemaValidatorPopElem()");
27472 goto internal_error;
27473 }
27474 }
27475 if (node == valRoot)
27476 goto exit;
27477 }
27478next_sibling:
27479 if (node->next != NULL)
27480 node = node->next;
27481 else {
27482 node = node->parent;
27483 goto leave_node;
27484 }
27485 }
27486
27487exit:
27488 return (ret);
27489internal_error:
27490 return (-1);
27491}
27492
27493static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027494xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027495 /*
27496 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027498 vctxt->err = 0;
27499 vctxt->nberrors = 0;
27500 vctxt->depth = -1;
27501 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027502 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027503 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027504#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027505 vctxt->createIDCNodeTables = 1;
27506#else
27507 vctxt->createIDCNodeTables = 0;
27508#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027509 /*
27510 * Create a schema + parser if necessary.
27511 */
27512 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027513 xmlSchemaParserCtxtPtr pctxt;
27514
27515 vctxt->xsiAssemble = 1;
27516 /*
27517 * If not schema was given then we will create a schema
27518 * dynamically using XSI schema locations.
27519 *
27520 * Create the schema parser context.
27521 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027522 if ((vctxt->pctxt == NULL) &&
27523 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27524 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027525 pctxt = vctxt->pctxt;
27526 pctxt->xsiAssemble = 1;
27527 /*
27528 * Create the schema.
27529 */
27530 vctxt->schema = xmlSchemaNewSchema(pctxt);
27531 if (vctxt->schema == NULL)
27532 return (-1);
27533 /*
27534 * Create the schema construction context.
27535 */
27536 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27537 if (pctxt->constructor == NULL)
27538 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027539 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027540 /*
27541 * Take ownership of the constructor to be able to free it.
27542 */
27543 pctxt->ownsConstructor = 1;
27544 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027545 /*
27546 * Augment the IDC definitions.
27547 */
27548 if (vctxt->schema->idcDef != NULL) {
27549 xmlHashScan(vctxt->schema->idcDef,
27550 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27551 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027552 return(0);
27553}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027554
Daniel Veillardf10ae122005-07-10 19:03:16 +000027555static void
27556xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027557 if (vctxt->xsiAssemble) {
27558 if (vctxt->schema != NULL) {
27559 xmlSchemaFree(vctxt->schema);
27560 vctxt->schema = NULL;
27561 }
27562 }
27563 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027564}
27565
27566static int
27567xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27568{
27569 int ret = 0;
27570
27571 if (xmlSchemaPreRun(vctxt) < 0)
27572 return(-1);
27573
27574 if (vctxt->doc != NULL) {
27575 /*
27576 * Tree validation.
27577 */
27578 ret = xmlSchemaVDocWalk(vctxt);
27579#ifdef LIBXML_READER_ENABLED
27580 } else if (vctxt->reader != NULL) {
27581 /*
27582 * XML Reader validation.
27583 */
27584#ifdef XML_SCHEMA_READER_ENABLED
27585 ret = xmlSchemaVReaderWalk(vctxt);
27586#endif
27587#endif
27588 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27589 /*
27590 * SAX validation.
27591 */
27592 ret = xmlParseDocument(vctxt->parserCtxt);
27593 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027594 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027595 "no instance to validate");
27596 ret = -1;
27597 }
27598
27599 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027600 if (ret == 0)
27601 ret = vctxt->err;
27602 return (ret);
27603}
27604
27605/**
27606 * xmlSchemaValidateOneElement:
27607 * @ctxt: a schema validation context
27608 * @elem: an element node
27609 *
27610 * Validate a branch of a tree, starting with the given @elem.
27611 *
27612 * Returns 0 if the element and its subtree is valid, a positive error
27613 * code number otherwise and -1 in case of an internal or API error.
27614 */
27615int
27616xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27617{
27618 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27619 return (-1);
27620
27621 if (ctxt->schema == NULL)
27622 return (-1);
27623
27624 ctxt->doc = elem->doc;
27625 ctxt->node = elem;
27626 ctxt->validationRoot = elem;
27627 return(xmlSchemaVStart(ctxt));
27628}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027629
Daniel Veillard259f0df2004-08-18 09:13:18 +000027630/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027631 * xmlSchemaValidateDoc:
27632 * @ctxt: a schema validation context
27633 * @doc: a parsed document tree
27634 *
27635 * Validate a document tree in memory.
27636 *
27637 * Returns 0 if the document is schemas valid, a positive error code
27638 * number otherwise and -1 in case of internal or API error.
27639 */
27640int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027641xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27642{
Daniel Veillard4255d502002-04-16 15:50:10 +000027643 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027644 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027645
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027646 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027647 ctxt->node = xmlDocGetRootElement(doc);
27648 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027649 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027650 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27651 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027652 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027653 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027654 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027655 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027656 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027657}
27658
Daniel Veillardcdc82732005-07-08 15:04:06 +000027659
27660/************************************************************************
27661 * *
27662 * Function and data for SAX streaming API *
27663 * *
27664 ************************************************************************/
27665typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27666typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27667
27668struct _xmlSchemaSplitSAXData {
27669 xmlSAXHandlerPtr user_sax;
27670 void *user_data;
27671 xmlSchemaValidCtxtPtr ctxt;
27672 xmlSAXHandlerPtr schemas_sax;
27673};
27674
Daniel Veillard971771e2005-07-09 17:32:57 +000027675#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27676
27677struct _xmlSchemaSAXPlug {
27678 unsigned int magic;
27679
27680 /* the original callbacks informations */
27681 xmlSAXHandlerPtr *user_sax_ptr;
27682 xmlSAXHandlerPtr user_sax;
27683 void **user_data_ptr;
27684 void *user_data;
27685
27686 /* the block plugged back and validation informations */
27687 xmlSAXHandler schemas_sax;
27688 xmlSchemaValidCtxtPtr ctxt;
27689};
27690
Daniel Veillardcdc82732005-07-08 15:04:06 +000027691/* All those functions just bounces to the user provided SAX handlers */
27692static void
27693internalSubsetSplit(void *ctx, const xmlChar *name,
27694 const xmlChar *ExternalID, const xmlChar *SystemID)
27695{
Daniel Veillard971771e2005-07-09 17:32:57 +000027696 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027697 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27698 (ctxt->user_sax->internalSubset != NULL))
27699 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27700 SystemID);
27701}
27702
27703static int
27704isStandaloneSplit(void *ctx)
27705{
Daniel Veillard971771e2005-07-09 17:32:57 +000027706 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027707 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27708 (ctxt->user_sax->isStandalone != NULL))
27709 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27710 return(0);
27711}
27712
27713static int
27714hasInternalSubsetSplit(void *ctx)
27715{
Daniel Veillard971771e2005-07-09 17:32:57 +000027716 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027717 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27718 (ctxt->user_sax->hasInternalSubset != NULL))
27719 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27720 return(0);
27721}
27722
27723static int
27724hasExternalSubsetSplit(void *ctx)
27725{
Daniel Veillard971771e2005-07-09 17:32:57 +000027726 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027727 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27728 (ctxt->user_sax->hasExternalSubset != NULL))
27729 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27730 return(0);
27731}
27732
27733static void
27734externalSubsetSplit(void *ctx, const xmlChar *name,
27735 const xmlChar *ExternalID, const xmlChar *SystemID)
27736{
Daniel Veillard971771e2005-07-09 17:32:57 +000027737 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027738 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27739 (ctxt->user_sax->internalSubset != NULL))
27740 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27741 SystemID);
27742}
27743
27744static xmlParserInputPtr
27745resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27746{
Daniel Veillard971771e2005-07-09 17:32:57 +000027747 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027748 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27749 (ctxt->user_sax->resolveEntity != NULL))
27750 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27751 systemId));
27752 return(NULL);
27753}
27754
27755static xmlEntityPtr
27756getEntitySplit(void *ctx, const xmlChar *name)
27757{
Daniel Veillard971771e2005-07-09 17:32:57 +000027758 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027759 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27760 (ctxt->user_sax->getEntity != NULL))
27761 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27762 return(NULL);
27763}
27764
27765static xmlEntityPtr
27766getParameterEntitySplit(void *ctx, const xmlChar *name)
27767{
Daniel Veillard971771e2005-07-09 17:32:57 +000027768 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027769 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27770 (ctxt->user_sax->getParameterEntity != NULL))
27771 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27772 return(NULL);
27773}
27774
27775
27776static void
27777entityDeclSplit(void *ctx, const xmlChar *name, int type,
27778 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27779{
Daniel Veillard971771e2005-07-09 17:32:57 +000027780 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027781 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27782 (ctxt->user_sax->entityDecl != NULL))
27783 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27784 systemId, content);
27785}
27786
27787static void
27788attributeDeclSplit(void *ctx, const xmlChar * elem,
27789 const xmlChar * name, int type, int def,
27790 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27791{
Daniel Veillard971771e2005-07-09 17:32:57 +000027792 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027793 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27794 (ctxt->user_sax->attributeDecl != NULL)) {
27795 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27796 def, defaultValue, tree);
27797 } else {
27798 xmlFreeEnumeration(tree);
27799 }
27800}
27801
27802static void
27803elementDeclSplit(void *ctx, const xmlChar *name, int type,
27804 xmlElementContentPtr content)
27805{
Daniel Veillard971771e2005-07-09 17:32:57 +000027806 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027807 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27808 (ctxt->user_sax->elementDecl != NULL))
27809 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27810}
27811
27812static void
27813notationDeclSplit(void *ctx, const xmlChar *name,
27814 const xmlChar *publicId, const xmlChar *systemId)
27815{
Daniel Veillard971771e2005-07-09 17:32:57 +000027816 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027817 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27818 (ctxt->user_sax->notationDecl != NULL))
27819 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27820 systemId);
27821}
27822
27823static void
27824unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27825 const xmlChar *publicId, const xmlChar *systemId,
27826 const xmlChar *notationName)
27827{
Daniel Veillard971771e2005-07-09 17:32:57 +000027828 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027829 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27830 (ctxt->user_sax->unparsedEntityDecl != NULL))
27831 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27832 systemId, notationName);
27833}
27834
27835static void
27836setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27837{
Daniel Veillard971771e2005-07-09 17:32:57 +000027838 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027839 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27840 (ctxt->user_sax->setDocumentLocator != NULL))
27841 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27842}
27843
27844static void
27845startDocumentSplit(void *ctx)
27846{
Daniel Veillard971771e2005-07-09 17:32:57 +000027847 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027848 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27849 (ctxt->user_sax->startDocument != NULL))
27850 ctxt->user_sax->startDocument(ctxt->user_data);
27851}
27852
27853static void
27854endDocumentSplit(void *ctx)
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->endDocument != NULL))
27859 ctxt->user_sax->endDocument(ctxt->user_data);
27860}
27861
27862static void
27863processingInstructionSplit(void *ctx, const xmlChar *target,
27864 const xmlChar *data)
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->processingInstruction != NULL))
27869 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27870}
27871
27872static void
27873commentSplit(void *ctx, const xmlChar *value)
27874{
Daniel Veillard971771e2005-07-09 17:32:57 +000027875 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027876 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27877 (ctxt->user_sax->comment != NULL))
27878 ctxt->user_sax->comment(ctxt->user_data, value);
27879}
27880
27881/*
27882 * Varargs error callbacks to the user application, harder ...
27883 */
27884
Daniel Veillardffa3c742005-07-21 13:24:09 +000027885static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027886warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027887 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027888 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27889 (ctxt->user_sax->warning != NULL)) {
27890 TODO
27891 }
27892}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027893static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027894errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027895 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027896 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27897 (ctxt->user_sax->error != NULL)) {
27898 TODO
27899 }
27900}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027901static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027902fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027903 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027904 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27905 (ctxt->user_sax->fatalError != NULL)) {
27906 TODO
27907 }
27908}
27909
27910/*
27911 * Those are function where both the user handler and the schemas handler
27912 * need to be called.
27913 */
27914static void
27915charactersSplit(void *ctx, const xmlChar *ch, int len)
27916{
Daniel Veillard971771e2005-07-09 17:32:57 +000027917 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027918 if (ctxt == NULL)
27919 return;
27920 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27921 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27922 if (ctxt->ctxt != NULL)
27923 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27924}
27925
27926static void
27927ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27928{
Daniel Veillard971771e2005-07-09 17:32:57 +000027929 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027930 if (ctxt == NULL)
27931 return;
27932 if ((ctxt->user_sax != NULL) &&
27933 (ctxt->user_sax->ignorableWhitespace != NULL))
27934 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27935 if (ctxt->ctxt != NULL)
27936 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27937}
27938
27939static void
27940cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27941{
Daniel Veillard971771e2005-07-09 17:32:57 +000027942 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027943 if (ctxt == NULL)
27944 return;
27945 if ((ctxt->user_sax != NULL) &&
27946 (ctxt->user_sax->ignorableWhitespace != NULL))
27947 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27948 if (ctxt->ctxt != NULL)
27949 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27950}
27951
27952static void
27953referenceSplit(void *ctx, const xmlChar *name)
27954{
Daniel Veillard971771e2005-07-09 17:32:57 +000027955 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027956 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27957 (ctxt->user_sax->reference != NULL))
27958 ctxt->user_sax->reference(ctxt->user_data, name);
27959 if (ctxt->ctxt != NULL)
27960 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27961}
27962
27963static void
27964startElementNsSplit(void *ctx, const xmlChar * localname,
27965 const xmlChar * prefix, const xmlChar * URI,
27966 int nb_namespaces, const xmlChar ** namespaces,
27967 int nb_attributes, int nb_defaulted,
27968 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027969 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027970 if (ctxt == NULL)
27971 return;
27972 if ((ctxt->user_sax != NULL) &&
27973 (ctxt->user_sax->startElementNs != NULL))
27974 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27975 URI, nb_namespaces, namespaces,
27976 nb_attributes, nb_defaulted,
27977 attributes);
27978 if (ctxt->ctxt != NULL)
27979 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27980 URI, nb_namespaces, namespaces,
27981 nb_attributes, nb_defaulted,
27982 attributes);
27983}
27984
27985static void
27986endElementNsSplit(void *ctx, const xmlChar * localname,
27987 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027988 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027989 if (ctxt == NULL)
27990 return;
27991 if ((ctxt->user_sax != NULL) &&
27992 (ctxt->user_sax->endElementNs != NULL))
27993 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27994 if (ctxt->ctxt != NULL)
27995 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27996}
27997
Daniel Veillard4255d502002-04-16 15:50:10 +000027998/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027999 * xmlSchemaSAXPlug:
28000 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028001 * @sax: a pointer to the original xmlSAXHandlerPtr
28002 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028003 *
28004 * Plug a SAX based validation layer in a SAX parsing event flow.
28005 * The original @saxptr and @dataptr data are replaced by new pointers
28006 * but the calls to the original will be maintained.
28007 *
28008 * Returns a pointer to a data structure needed to unplug the validation layer
28009 * or NULL in case of errors.
28010 */
28011xmlSchemaSAXPlugPtr
28012xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28013 xmlSAXHandlerPtr *sax, void **user_data)
28014{
28015 xmlSchemaSAXPlugPtr ret;
28016 xmlSAXHandlerPtr old_sax;
28017
28018 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28019 return(NULL);
28020
28021 /*
28022 * We only allow to plug into SAX2 event streams
28023 */
28024 old_sax = *sax;
28025 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28026 return(NULL);
28027 if ((old_sax != NULL) &&
28028 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28029 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28030 return(NULL);
28031
28032 /*
28033 * everything seems right allocate the local data needed for that layer
28034 */
28035 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28036 if (ret == NULL) {
28037 return(NULL);
28038 }
28039 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28040 ret->magic = XML_SAX_PLUG_MAGIC;
28041 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28042 ret->ctxt = ctxt;
28043 ret->user_sax_ptr = sax;
28044 ret->user_sax = old_sax;
28045 if (old_sax == NULL) {
28046 /*
28047 * go direct, no need for the split block and functions.
28048 */
28049 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28050 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28051 /*
28052 * Note that we use the same text-function for both, to prevent
28053 * the parser from testing for ignorable whitespace.
28054 */
28055 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28056 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28057
28058 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28059 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28060
28061 ret->user_data = ctxt;
28062 *user_data = ctxt;
28063 } else {
28064 /*
28065 * for each callback unused by Schemas initialize it to the Split
28066 * routine only if non NULL in the user block, this can speed up
28067 * things at the SAX level.
28068 */
28069 if (old_sax->internalSubset != NULL)
28070 ret->schemas_sax.internalSubset = internalSubsetSplit;
28071 if (old_sax->isStandalone != NULL)
28072 ret->schemas_sax.isStandalone = isStandaloneSplit;
28073 if (old_sax->hasInternalSubset != NULL)
28074 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28075 if (old_sax->hasExternalSubset != NULL)
28076 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28077 if (old_sax->resolveEntity != NULL)
28078 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28079 if (old_sax->getEntity != NULL)
28080 ret->schemas_sax.getEntity = getEntitySplit;
28081 if (old_sax->entityDecl != NULL)
28082 ret->schemas_sax.entityDecl = entityDeclSplit;
28083 if (old_sax->notationDecl != NULL)
28084 ret->schemas_sax.notationDecl = notationDeclSplit;
28085 if (old_sax->attributeDecl != NULL)
28086 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28087 if (old_sax->elementDecl != NULL)
28088 ret->schemas_sax.elementDecl = elementDeclSplit;
28089 if (old_sax->unparsedEntityDecl != NULL)
28090 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28091 if (old_sax->setDocumentLocator != NULL)
28092 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28093 if (old_sax->startDocument != NULL)
28094 ret->schemas_sax.startDocument = startDocumentSplit;
28095 if (old_sax->endDocument != NULL)
28096 ret->schemas_sax.endDocument = endDocumentSplit;
28097 if (old_sax->processingInstruction != NULL)
28098 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28099 if (old_sax->comment != NULL)
28100 ret->schemas_sax.comment = commentSplit;
28101 if (old_sax->warning != NULL)
28102 ret->schemas_sax.warning = warningSplit;
28103 if (old_sax->error != NULL)
28104 ret->schemas_sax.error = errorSplit;
28105 if (old_sax->fatalError != NULL)
28106 ret->schemas_sax.fatalError = fatalErrorSplit;
28107 if (old_sax->getParameterEntity != NULL)
28108 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28109 if (old_sax->externalSubset != NULL)
28110 ret->schemas_sax.externalSubset = externalSubsetSplit;
28111
28112 /*
28113 * the 6 schemas callback have to go to the splitter functions
28114 * Note that we use the same text-function for ignorableWhitespace
28115 * if possible, to prevent the parser from testing for ignorable
28116 * whitespace.
28117 */
28118 ret->schemas_sax.characters = charactersSplit;
28119 if ((old_sax->ignorableWhitespace != NULL) &&
28120 (old_sax->ignorableWhitespace != old_sax->characters))
28121 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28122 else
28123 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28124 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28125 ret->schemas_sax.reference = referenceSplit;
28126 ret->schemas_sax.startElementNs = startElementNsSplit;
28127 ret->schemas_sax.endElementNs = endElementNsSplit;
28128
28129 ret->user_data_ptr = user_data;
28130 ret->user_data = *user_data;
28131 *user_data = ret;
28132 }
28133
28134 /*
28135 * plug the pointers back.
28136 */
28137 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028138 ctxt->sax = *sax;
28139 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28140 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028141 return(ret);
28142}
28143
28144/**
28145 * xmlSchemaSAXUnplug:
28146 * @plug: a data structure returned by xmlSchemaSAXPlug
28147 *
28148 * Unplug a SAX based validation layer in a SAX parsing event flow.
28149 * The original pointers used in the call are restored.
28150 *
28151 * Returns 0 in case of success and -1 in case of failure.
28152 */
28153int
28154xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28155{
28156 xmlSAXHandlerPtr *sax;
28157 void **user_data;
28158
28159 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28160 return(-1);
28161 plug->magic = 0;
28162
Daniel Veillardf10ae122005-07-10 19:03:16 +000028163 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028164 /* restore the data */
28165 sax = plug->user_sax_ptr;
28166 *sax = plug->user_sax;
28167 if (plug->user_sax != NULL) {
28168 user_data = plug->user_data_ptr;
28169 *user_data = plug->user_data;
28170 }
28171
28172 /* free and return */
28173 xmlFree(plug);
28174 return(0);
28175}
28176
28177/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028178 * xmlSchemaValidateStream:
28179 * @ctxt: a schema validation context
28180 * @input: the input to use for reading the data
28181 * @enc: an optional encoding information
28182 * @sax: a SAX handler for the resulting events
28183 * @user_data: the context to provide to the SAX handler.
28184 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028185 * Validate an input based on a flow of SAX event from the parser
28186 * and forward the events to the @sax handler with the provided @user_data
28187 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028188 *
28189 * Returns 0 if the document is schemas valid, a positive error code
28190 * number otherwise and -1 in case of internal or API error.
28191 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028192int
Daniel Veillard4255d502002-04-16 15:50:10 +000028193xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028194 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28195 xmlSAXHandlerPtr sax, void *user_data)
28196{
Daniel Veillard971771e2005-07-09 17:32:57 +000028197 xmlSchemaSAXPlugPtr plug = NULL;
28198 xmlSAXHandlerPtr old_sax = NULL;
28199 xmlParserCtxtPtr pctxt = NULL;
28200 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028201 int ret;
28202
Daniel Veillard4255d502002-04-16 15:50:10 +000028203 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028204 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028205
Daniel Veillardcdc82732005-07-08 15:04:06 +000028206 /*
28207 * prepare the parser
28208 */
28209 pctxt = xmlNewParserCtxt();
28210 if (pctxt == NULL)
28211 return (-1);
28212 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028213 pctxt->sax = sax;
28214 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028215#if 0
28216 if (options)
28217 xmlCtxtUseOptions(pctxt, options);
28218#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028219 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028220
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028221 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028222 if (inputStream == NULL) {
28223 ret = -1;
28224 goto done;
28225 }
28226 inputPush(pctxt, inputStream);
28227 ctxt->parserCtxt = pctxt;
28228 ctxt->input = input;
28229
28230 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028231 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028232 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028233 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28234 if (plug == NULL) {
28235 ret = -1;
28236 goto done;
28237 }
28238 ctxt->input = input;
28239 ctxt->enc = enc;
28240 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028241 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28242 ret = xmlSchemaVStart(ctxt);
28243
28244 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28245 ret = ctxt->parserCtxt->errNo;
28246 if (ret == 0)
28247 ret = 1;
28248 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028249
28250done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028251 ctxt->parserCtxt = NULL;
28252 ctxt->sax = NULL;
28253 ctxt->input = NULL;
28254 if (plug != NULL) {
28255 xmlSchemaSAXUnplug(plug);
28256 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028257 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028258 if (pctxt != NULL) {
28259 pctxt->sax = old_sax;
28260 xmlFreeParserCtxt(pctxt);
28261 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028262 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028263}
28264
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028265/**
28266 * xmlSchemaValidateFile:
28267 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028268 * @filename: the URI of the instance
28269 * @options: a future set of options, currently unused
28270 *
28271 * Do a schemas validation of the given resource, it will use the
28272 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028273 *
28274 * Returns 0 if the document is valid, a positive error code
28275 * number otherwise and -1 in case of an internal or API error.
28276 */
28277int
28278xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028279 const char * filename,
28280 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028281{
28282 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028283 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028284
28285 if ((ctxt == NULL) || (filename == NULL))
28286 return (-1);
28287
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028288 input = xmlParserInputBufferCreateFilename(filename,
28289 XML_CHAR_ENCODING_NONE);
28290 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028291 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028292 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28293 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028294 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028295}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028296
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028297#define bottom_xmlschemas
28298#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028299#endif /* LIBXML_SCHEMAS_ENABLED */