blob: 951899910b69ce33fdc7aeb14d25bd98ccb5560e [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 */
584 xmlSchemaValidError err;
585 int nberrors;
586 xmlStructuredErrorFunc serror;
587
588 xmlSchemaConstructionCtxtPtr constructor;
589 int ownsConstructor; /* TODO: Move this to parser *flags*. */
590
591 /* xmlSchemaPtr topschema; */
592 /* xmlHashTablePtr namespaces; */
593
594 xmlSchemaPtr schema; /* The main schema in use */
595 int counter;
596
597 const xmlChar *URL;
598 xmlDocPtr doc;
599 int preserve; /* Whether the doc should be freed */
600
601 const char *buffer;
602 int size;
603
604 /*
605 * Used to build complex element content models
606 */
607 xmlAutomataPtr am;
608 xmlAutomataStatePtr start;
609 xmlAutomataStatePtr end;
610 xmlAutomataStatePtr state;
611
612 xmlDictPtr dict; /* dictionnary for interned string names */
613 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
614 int options;
615 xmlSchemaValidCtxtPtr vctxt;
616 int isS4S;
617 int isRedefine;
618 int xsiAssemble;
619 int stop; /* If the parser should stop; i.e. a critical error. */
620 const xmlChar *targetNamespace;
621 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
622
623 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
624 int redefCounter; /* Used for redefinitions. */
625 xmlSchemaItemListPtr attrProhibs;
626};
627
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000628/**
629 * xmlSchemaQNameRef:
630 *
631 * A component reference item (not a schema component)
632 * (Extends xmlSchemaBasicItem)
633 */
634typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
635typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
636struct _xmlSchemaQNameRef {
637 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000638 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000639 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000640 const xmlChar *name;
641 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000642 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000643};
644
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645/**
646 * xmlSchemaParticle:
647 *
648 * A particle component.
649 * (Extends xmlSchemaTreeItem)
650 */
651typedef struct _xmlSchemaParticle xmlSchemaParticle;
652typedef xmlSchemaParticle *xmlSchemaParticlePtr;
653struct _xmlSchemaParticle {
654 xmlSchemaTypeType type;
655 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000656 xmlSchemaTreeItemPtr next; /* next particle */
657 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
658 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
659 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000660 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000661 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662 xmlNodePtr node;
663};
664
665/**
666 * xmlSchemaModelGroup:
667 *
668 * A model group component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
672typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
673struct _xmlSchemaModelGroup {
674 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
675 xmlSchemaAnnotPtr annot;
676 xmlSchemaTreeItemPtr next; /* not used */
677 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
678 xmlNodePtr node;
679};
680
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000681#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000682#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000683/**
684 * xmlSchemaModelGroupDef:
685 *
686 * A model group definition component.
687 * (Extends xmlSchemaTreeItem)
688 */
689typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
690typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
691struct _xmlSchemaModelGroupDef {
692 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
693 xmlSchemaAnnotPtr annot;
694 xmlSchemaTreeItemPtr next; /* not used */
695 xmlSchemaTreeItemPtr children; /* the "model group" */
696 const xmlChar *name;
697 const xmlChar *targetNamespace;
698 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000699 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000700};
701
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000702typedef struct _xmlSchemaIDC xmlSchemaIDC;
703typedef xmlSchemaIDC *xmlSchemaIDCPtr;
704
705/**
706 * xmlSchemaIDCSelect:
707 *
708 * The identity-constraint "field" and "selector" item, holding the
709 * XPath expression.
710 */
711typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
712typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000713struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000714 xmlSchemaIDCSelectPtr next;
715 xmlSchemaIDCPtr idc;
716 int index; /* an index position if significant for IDC key-sequences */
717 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000718 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000719};
720
721/**
722 * xmlSchemaIDC:
723 *
724 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000725 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000726 */
727
728struct _xmlSchemaIDC {
729 xmlSchemaTypeType type;
730 xmlSchemaAnnotPtr annot;
731 xmlSchemaIDCPtr next;
732 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000733 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 const xmlChar *targetNamespace;
735 xmlSchemaIDCSelectPtr selector;
736 xmlSchemaIDCSelectPtr fields;
737 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000738 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000739};
740
741/**
742 * xmlSchemaIDCAug:
743 *
744 * The augmented IDC information used for validation.
745 */
746typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
747typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
748struct _xmlSchemaIDCAug {
749 xmlSchemaIDCAugPtr next; /* next in a list */
750 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000751 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000752 tables need to be bubbled upwards */
753};
754
755/**
756 * xmlSchemaPSVIIDCKeySequence:
757 *
758 * The key sequence of a node table item.
759 */
760typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
761typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
762struct _xmlSchemaPSVIIDCKey {
763 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000764 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000765};
766
767/**
768 * xmlSchemaPSVIIDCNode:
769 *
770 * The node table item of a node table.
771 */
772typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
773typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
774struct _xmlSchemaPSVIIDCNode {
775 xmlNodePtr node;
776 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000777 int nodeLine;
778 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000779
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000780};
781
782/**
783 * xmlSchemaPSVIIDCBinding:
784 *
785 * The identity-constraint binding item of the [identity-constraint table].
786 */
787typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
788typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
789struct _xmlSchemaPSVIIDCBinding {
790 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
791 xmlSchemaIDCPtr definition; /* the IDC definition */
792 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
793 int nbNodes; /* number of entries in the node table */
794 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000795 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000796};
797
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000798
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000799#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
800#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
801
802#define XPATH_STATE_OBJ_MATCHES -2
803#define XPATH_STATE_OBJ_BLOCKED -3
804
805typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
806typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
807
808/**
809 * xmlSchemaIDCStateObj:
810 *
811 * The state object used to evaluate XPath expressions.
812 */
813typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
814typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
815struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000816 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000817 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000818 int depth; /* depth of creation */
819 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000820 int nbHistory;
821 int sizeHistory;
822 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
823 matcher */
824 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000825 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000826};
827
828#define IDC_MATCHER 0
829
830/**
831 * xmlSchemaIDCMatcher:
832 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000833 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000834 */
835struct _xmlSchemaIDCMatcher {
836 int type;
837 int depth; /* the tree depth at creation time */
838 xmlSchemaIDCMatcherPtr next; /* next in the list */
839 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000840 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000841 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
842 elements */
843 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000844 int targetDepth;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000845 xmlSchemaItemListPtr targets; /* list of target-node
846 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000847};
848
849/*
850* Element info flags.
851*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000852#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
853#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
854#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
855#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
856
857#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
858#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
859#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
860
861#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
862#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
863#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
864#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000865
866/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000867 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000868 *
869 * Holds information of an element node.
870 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000871struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000872 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000873 xmlNodePtr node;
874 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000875 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000876 const xmlChar *nsName;
877 const xmlChar *value;
878 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000879 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000880
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000881 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000883 int valNeeded;
884 int normVal;
885
886 xmlSchemaElementPtr decl; /* the element/attribute declaration */
887 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000888 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
889 for the scope element*/
890 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
891 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000892 xmlRegExecCtxtPtr regexCtxt;
893
894 const xmlChar **nsBindings; /* Namespace bindings on this element */
895 int nbNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000896 int sizeNsBindings;
897
898 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000899 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000900};
901
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000902#define XML_SCHEMAS_ATTR_UNKNOWN 1
903#define XML_SCHEMAS_ATTR_ASSESSED 2
904#define XML_SCHEMAS_ATTR_PROHIBITED 3
905#define XML_SCHEMAS_ATTR_ERR_MISSING 4
906#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
907#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
908#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
909#define XML_SCHEMAS_ATTR_DEFAULT 8
910#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
911#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
912#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
913#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
914#define XML_SCHEMAS_ATTR_WILD_SKIP 13
915#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
916#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
917#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
918#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000919/*
920* @metaType values of xmlSchemaAttrInfo.
921*/
922#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
923#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
924#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
926#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000928typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
929typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
930struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000931 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000932 xmlNodePtr node;
933 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000934 const xmlChar *localName;
935 const xmlChar *nsName;
936 const xmlChar *value;
937 xmlSchemaValPtr val; /* the pre-computed value if any */
938 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
939 int flags; /* combination of node info flags */
940
941 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000942 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000943 int state;
944 int metaType;
945 const xmlChar *vcValue; /* the value constraint value */
946 xmlSchemaNodeInfoPtr parent;
947};
948
949
950#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000951/**
952 * xmlSchemaValidCtxt:
953 *
954 * A Schemas validation context
955 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000956struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000957 int type;
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
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017846xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17847 xmlSchemaTypePtr type)
17848{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017849 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017850 xmlGenericError(xmlGenericErrorContext,
17851 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017852 type->node->doc->URL,
17853 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017854 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017855 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017856 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017857 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017858 switch (type->contentType) {
17859 case XML_SCHEMA_CONTENT_SIMPLE:
17860 xmlGenericError(xmlGenericErrorContext, "simple\n");
17861 break;
17862 case XML_SCHEMA_CONTENT_ELEMENTS:
17863 xmlGenericError(xmlGenericErrorContext, "elements\n");
17864 break;
17865 case XML_SCHEMA_CONTENT_UNKNOWN:
17866 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17867 break;
17868 case XML_SCHEMA_CONTENT_EMPTY:
17869 xmlGenericError(xmlGenericErrorContext, "empty\n");
17870 break;
17871 case XML_SCHEMA_CONTENT_MIXED:
17872 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017873 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017874 xmlGenericError(xmlGenericErrorContext,
17875 "mixed as emptiable particle\n");
17876 else
17877 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17878 break;
17879 /* Removed, since not used. */
17880 /*
17881 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17882 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17883 break;
17884 */
17885 case XML_SCHEMA_CONTENT_BASIC:
17886 xmlGenericError(xmlGenericErrorContext, "basic\n");
17887 break;
17888 default:
17889 xmlGenericError(xmlGenericErrorContext,
17890 "not registered !!!\n");
17891 break;
17892 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017893 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017894}
Daniel Veillard8651f532002-04-17 09:06:27 +000017895#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017896
17897/*
17898* 3.14.6 Constraints on Simple Type Definition Schema Components
17899*/
17900static int
17901xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17902 xmlSchemaTypePtr type)
17903{
17904 int res, olderrs = pctxt->nberrors;
17905
17906 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17907 return(-1);
17908
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017909 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017910 return(0);
17911
17912 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17913 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17914
17915 if (type->baseType == NULL) {
17916 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17917 "missing baseType");
17918 goto exit_failure;
17919 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017920 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017921 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017922 /*
17923 * If a member type of a union is a union itself, we need to substitute
17924 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017925 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17926 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017927 */
17928 if ((type->memberTypes != NULL) &&
17929 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17930 return(-1);
17931 /*
17932 * SPEC src-simple-type 1
17933 * "The corresponding simple type definition, if any, must satisfy
17934 * the conditions set out in Constraints on Simple Type Definition
17935 * Schema Components (§3.14.6)."
17936 */
17937 /*
17938 * Schema Component Constraint: Simple Type Definition Properties Correct
17939 * (st-props-correct)
17940 */
17941 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17942 HFAILURE HERROR
17943 /*
17944 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17945 * (cos-st-restricts)
17946 */
17947 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17948 HFAILURE HERROR
17949 /*
17950 * TODO: Removed the error report, since it got annoying to get an
17951 * extra error report, if anything failed until now.
17952 * Enable this if needed.
17953 *
17954 * xmlSchemaPErr(ctxt, type->node,
17955 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17956 * "Simple type '%s' does not satisfy the constraints "
17957 * "on simple type definitions.\n",
17958 * type->name, NULL);
17959 */
17960 /*
17961 * Schema Component Constraint: Simple Type Restriction (Facets)
17962 * (st-restrict-facets)
17963 */
17964 res = xmlSchemaCheckFacetValues(type, pctxt);
17965 HFAILURE HERROR
17966 if ((type->facetSet != NULL) ||
17967 (type->baseType->facetSet != NULL)) {
17968 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17969 HFAILURE HERROR
17970 }
17971 /*
17972 * Whitespace value.
17973 */
17974 res = xmlSchemaTypeFixupWhitespace(type);
17975 HFAILURE HERROR
17976 xmlSchemaTypeFixupOptimFacets(type);
17977
17978exit_error:
17979#ifdef DEBUG_TYPE
17980 xmlSchemaDebugFixedType(pctxt, type);
17981#endif
17982 if (olderrs != pctxt->nberrors)
17983 return(pctxt->err);
17984 return(0);
17985
17986exit_failure:
17987#ifdef DEBUG_TYPE
17988 xmlSchemaDebugFixedType(pctxt, type);
17989#endif
17990 return(-1);
17991}
17992
17993static int
17994xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17995 xmlSchemaTypePtr type)
17996{
17997 int res = 0, olderrs = pctxt->nberrors;
17998 xmlSchemaTypePtr baseType = type->baseType;
17999
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018000 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018001 return(0);
18002 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18003 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018004 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018005 "missing baseType");
18006 goto exit_failure;
18007 }
18008 /*
18009 * Fixup the base type.
18010 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018011 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018012 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018013 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18014 /*
18015 * Skip fixup if the base type is invalid.
18016 * TODO: Generate a warning!
18017 */
18018 return(0);
18019 }
18020 /*
18021 * This basically checks if the base type can be derived.
18022 */
18023 res = xmlSchemaCheckSRCCT(pctxt, type);
18024 HFAILURE HERROR
18025 /*
18026 * Fixup the content type.
18027 */
18028 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18029 /*
18030 * Corresponds to <complexType><simpleContent>...
18031 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018032 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018033 (baseType->contentTypeDef != NULL) &&
18034 (WXS_IS_RESTRICTION(type))) {
18035 xmlSchemaTypePtr contentBase, content;
18036#ifdef ENABLE_NAMED_LOCALS
18037 char buf[30];
18038 const xmlChar *tmpname;
18039#endif
18040 /*
18041 * SPEC (1) If <restriction> + base type is <complexType>,
18042 * "whose own {content type} is a simple type..."
18043 */
18044 if (type->contentTypeDef != NULL) {
18045 /*
18046 * SPEC (1.1) "the simple type definition corresponding to the
18047 * <simpleType> among the [children] of <restriction> if there
18048 * is one;"
18049 * Note that this "<simpleType> among the [children]" was put
18050 * into ->contentTypeDef during parsing.
18051 */
18052 contentBase = type->contentTypeDef;
18053 type->contentTypeDef = NULL;
18054 } else {
18055 /*
18056 * (1.2) "...otherwise (<restriction> has no <simpleType>
18057 * among its [children]), the simple type definition which
18058 * is the {content type} of the ... base type."
18059 */
18060 contentBase = baseType->contentTypeDef;
18061 }
18062 /*
18063 * SPEC
18064 * "... a simple type definition which restricts the simple
18065 * type definition identified in clause 1.1 or clause 1.2
18066 * with a set of facet components"
18067 *
18068 * Create the anonymous simple type, which will be the content
18069 * type of the complex type.
18070 */
18071#ifdef ENABLE_NAMED_LOCALS
18072 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18073 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018074 content = xmlSchemaAddType(pctxt, pctxt->schema,
18075 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018076 type->node, 0);
18077#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018078 content = xmlSchemaAddType(pctxt, pctxt->schema,
18079 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018080 type->node, 0);
18081#endif
18082 if (content == NULL)
18083 goto exit_failure;
18084 /*
18085 * We will use the same node as for the <complexType>
18086 * to have it somehow anchored in the schema doc.
18087 */
18088 content->type = XML_SCHEMA_TYPE_SIMPLE;
18089 content->baseType = contentBase;
18090 /*
18091 * Move the facets, previously anchored on the
18092 * complexType during parsing.
18093 */
18094 content->facets = type->facets;
18095 type->facets = NULL;
18096 content->facetSet = type->facetSet;
18097 type->facetSet = NULL;
18098
18099 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018100 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018101 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018102 /*
18103 * Fixup the newly created type. We don't need to check
18104 * for circularity here.
18105 */
18106 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18107 HFAILURE HERROR
18108 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18109 HFAILURE HERROR
18110
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018111 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018112 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18113 (WXS_IS_RESTRICTION(type))) {
18114 /*
18115 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18116 * an emptiable particle, then a simple type definition which
18117 * restricts the <restriction>'s <simpleType> child.
18118 */
18119 if ((type->contentTypeDef == NULL) ||
18120 (type->contentTypeDef->baseType == NULL)) {
18121 /*
18122 * TODO: Check if this ever happens.
18123 */
18124 xmlSchemaPCustomErr(pctxt,
18125 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018126 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018127 "Internal error: xmlSchemaTypeFixup, "
18128 "complex type '%s': the <simpleContent><restriction> "
18129 "is missing a <simpleType> child, but was not catched "
18130 "by xmlSchemaCheckSRCCT()", type->name);
18131 goto exit_failure;
18132 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018133 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018134 /*
18135 * SPEC (3) If <extension> + base is <complexType> with
18136 * <simpleType> content, "...then the {content type} of that
18137 * complex type definition"
18138 */
18139 if (baseType->contentTypeDef == NULL) {
18140 /*
18141 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18142 * should have catched this already.
18143 */
18144 xmlSchemaPCustomErr(pctxt,
18145 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018146 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018147 "Internal error: xmlSchemaTypeFixup, "
18148 "complex type '%s': the <extension>ed base type is "
18149 "a complex type with no simple content type",
18150 type->name);
18151 goto exit_failure;
18152 }
18153 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018154 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018155 /*
18156 * SPEC (4) <extension> + base is <simpleType>
18157 * "... then that simple type definition"
18158 */
18159 type->contentTypeDef = baseType;
18160 } else {
18161 /*
18162 * TODO: Check if this ever happens.
18163 */
18164 xmlSchemaPCustomErr(pctxt,
18165 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018166 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018167 "Internal error: xmlSchemaTypeFixup, "
18168 "complex type '%s' with <simpleContent>: unhandled "
18169 "derivation case", type->name);
18170 goto exit_failure;
18171 }
18172 } else {
18173 int dummySequence = 0;
18174 xmlSchemaParticlePtr particle =
18175 (xmlSchemaParticlePtr) type->subtypes;
18176 /*
18177 * Corresponds to <complexType><complexContent>...
18178 *
18179 * NOTE that the effective mixed was already set during parsing of
18180 * <complexType> and <complexContent>; its flag value is
18181 * XML_SCHEMAS_TYPE_MIXED.
18182 *
18183 * Compute the "effective content":
18184 * (2.1.1) + (2.1.2) + (2.1.3)
18185 */
18186 if ((particle == NULL) ||
18187 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18188 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18189 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18190 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18191 (particle->minOccurs == 0))) &&
18192 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18193 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18194 /*
18195 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18196 * a particle whose properties are as follows:..."
18197 *
18198 * Empty sequence model group with
18199 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18200 * NOTE that we sill assign it the <complexType> node to
18201 * somehow anchor it in the doc.
18202 */
18203 if ((particle == NULL) ||
18204 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18205 /*
18206 * Create the particle.
18207 */
18208 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18209 type->node, 1, 1);
18210 if (particle == NULL)
18211 goto exit_failure;
18212 /*
18213 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018214 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018215 particle->children = (xmlSchemaTreeItemPtr)
18216 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18217 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18218 if (particle->children == NULL)
18219 goto exit_failure;
18220
18221 type->subtypes = (xmlSchemaTypePtr) particle;
18222 }
18223 dummySequence = 1;
18224 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18225 } else {
18226 /*
18227 * SPEC (2.1.5) "otherwise empty"
18228 */
18229 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18230 }
18231 } else {
18232 /*
18233 * SPEC (2.2) "otherwise the particle corresponding to the
18234 * <all>, <choice>, <group> or <sequence> among the
18235 * [children]."
18236 */
18237 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18238 }
18239 /*
18240 * Compute the "content type".
18241 */
18242 if (WXS_IS_RESTRICTION(type)) {
18243 /*
18244 * SPEC (3.1) "If <restriction>..."
18245 * (3.1.1) + (3.1.2) */
18246 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18247 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18248 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18249 }
18250 } else {
18251 /*
18252 * SPEC (3.2) "If <extension>..."
18253 */
18254 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18255 /*
18256 * SPEC (3.2.1)
18257 */
18258 type->contentType = baseType->contentType;
18259 type->subtypes = baseType->subtypes;
18260 /*
18261 * NOTE that the effective mixed is ignored here.
18262 */
18263 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18264 /*
18265 * SPEC (3.2.2)
18266 */
18267 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18268 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18269 } else {
18270 /*
18271 * SPEC (3.2.3)
18272 */
18273 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18274 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18275 /*
18276 * "A model group whose {compositor} is sequence and whose
18277 * {particles} are..."
18278 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018279 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18280 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18281 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18282 XML_SCHEMA_TYPE_ALL))
18283 {
18284 /*
18285 * SPEC cos-all-limited (1)
18286 */
18287 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18288 /* TODO: error code */
18289 XML_SCHEMAP_COS_ALL_LIMITED,
18290 WXS_ITEM_NODE(type), NULL,
18291 "The type has an 'all' model group in its "
18292 "{content type} and thus cannot be derived from "
18293 "a non-empty type, since this would produce a "
18294 "'sequence' model group containing the 'all' "
18295 "model group; 'all' model groups are not "
18296 "allowed to appear inside other model groups",
18297 NULL, NULL);
18298
18299 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18300 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18301 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18302 XML_SCHEMA_TYPE_ALL))
18303 {
18304 /*
18305 * SPEC cos-all-limited (1)
18306 */
18307 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18308 /* TODO: error code */
18309 XML_SCHEMAP_COS_ALL_LIMITED,
18310 WXS_ITEM_NODE(type), NULL,
18311 "A type cannot be derived by extension from a type "
18312 "which has an 'all' model group in its "
18313 "{content type}, since this would produce a "
18314 "'sequence' model group containing the 'all' "
18315 "model group; 'all' model groups are not "
18316 "allowed to appear inside other model groups",
18317 NULL, NULL);
18318
18319 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018320 xmlSchemaTreeItemPtr effectiveContent =
18321 (xmlSchemaTreeItemPtr) type->subtypes;
18322 /*
18323 * Create the particle.
18324 */
18325 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18326 type->node, 1, 1);
18327 if (particle == NULL)
18328 goto exit_failure;
18329 /*
18330 * Create the "sequence" model group.
18331 */
18332 particle->children = (xmlSchemaTreeItemPtr)
18333 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18334 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18335 if (particle->children == NULL)
18336 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018337 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018338 /*
18339 * SPEC "the particle of the {content type} of
18340 * the ... base ..."
18341 * Create a duplicate of the base type's particle
18342 * and assign its "term" to it.
18343 */
18344 particle->children->children =
18345 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18346 pctxt->schema, type->node,
18347 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18348 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18349 if (particle->children->children == NULL)
18350 goto exit_failure;
18351 particle = (xmlSchemaParticlePtr)
18352 particle->children->children;
18353 particle->children =
18354 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18355 /*
18356 * SPEC "followed by the ·effective content·."
18357 */
18358 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018359 /*
18360 * This all will result in:
18361 * new-particle
18362 * --> new-sequence(
18363 * new-particle
18364 * --> base-model,
18365 * this-particle
18366 * --> this-model
18367 * )
18368 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018369 } else {
18370 /*
18371 * This is the case when there is already an empty
18372 * <sequence> with minOccurs==maxOccurs==1.
18373 * Just add the base types's content type.
18374 * NOTE that, although we miss to add an intermediate
18375 * <sequence>, this should produce no difference to
18376 * neither the regex compilation of the content model,
18377 * nor to the complex type contraints.
18378 */
18379 particle->children->children =
18380 (xmlSchemaTreeItemPtr) baseType->subtypes;
18381 }
18382 }
18383 }
18384 }
18385 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018386 * Now fixup attribute uses:
18387 * - expand attr. group references
18388 * - intersect attribute wildcards
18389 * - inherit attribute uses of the base type
18390 * - inherit or union attr. wildcards if extending
18391 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018392 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018393 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018394 HFAILURE HERROR
18395 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018396 * Apply the complex type component constraints; this will not
18397 * check attributes, since this is done in
18398 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018399 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018400 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018401 HFAILURE HERROR
18402
18403#ifdef DEBUG_TYPE
18404 xmlSchemaDebugFixedType(pctxt, type);
18405#endif
18406 if (olderrs != pctxt->nberrors)
18407 return(pctxt->err);
18408 else
18409 return(0);
18410
18411exit_error:
18412 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18413#ifdef DEBUG_TYPE
18414 xmlSchemaDebugFixedType(pctxt, type);
18415#endif
18416 return(pctxt->err);
18417
18418exit_failure:
18419 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18420#ifdef DEBUG_TYPE
18421 xmlSchemaDebugFixedType(pctxt, type);
18422#endif
18423 return(-1);
18424}
18425
18426
18427/**
18428 * xmlSchemaTypeFixup:
18429 * @typeDecl: the schema type definition
18430 * @ctxt: the schema parser context
18431 *
18432 * Fixes the content model of the type.
18433 * URGENT TODO: We need an int result!
18434 */
18435static int
18436xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018437 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018438{
18439 if (type == NULL)
18440 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018441 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18442 AERROR_INT("xmlSchemaTypeFixup",
18443 "this function needs a parser context");
18444 return(-1);
18445 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018446 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018447 return(0);
18448 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018449 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018450 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018451 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018452 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018453}
18454
18455/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018456 * xmlSchemaCheckFacet:
18457 * @facet: the facet
18458 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018459 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018460 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018461 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018462 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018463 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018464 * Returns 0 if valid, a positive error code if not valid and
18465 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018466 */
18467int
18468xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018469 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018470 xmlSchemaParserCtxtPtr pctxt,
18471 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018472{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018473 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018474
Daniel Veillardce682bc2004-11-05 17:22:25 +000018475 if ((facet == NULL) || (typeDecl == NULL))
18476 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018477 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018478 * TODO: will the parser context be given if used from
18479 * the relaxNG module?
18480 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018481 if (pctxt == NULL)
18482 ctxtGiven = 0;
18483 else
18484 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018485
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018486 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018487 case XML_SCHEMA_FACET_MININCLUSIVE:
18488 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18489 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018490 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18491 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018492 /*
18493 * Okay we need to validate the value
18494 * at that point.
18495 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018496 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018497
18498 /* 4.3.5.5 Constraints on enumeration Schema Components
18499 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018500 * It is an ·error· if any member of {value} is not in the
18501 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018502 *
18503 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018504 * The value ·must· be in the
18505 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018506 */
18507 /*
18508 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018509 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018510 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018511 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018512 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018513 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018514 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018515 */
18516 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18517 base = typeDecl->baseType;
18518 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 PERROR_INT("xmlSchemaCheckFacet",
18520 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018521 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018523 } else
18524 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018525
18526 if (! ctxtGiven) {
18527 /*
18528 * A context is needed if called from RelaxNG.
18529 */
18530 pctxt = xmlSchemaNewParserCtxt("*");
18531 if (pctxt == NULL)
18532 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018533 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018534 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018535 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018536 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537 * facet->node is just the node holding the facet
18538 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018539 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018540 */
18541 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018542 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018543 facet->value, &(facet->val), 1, 1, 0);
18544 if (ret != 0) {
18545 if (ret < 0) {
18546 /* No error message for RelaxNG. */
18547 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018548 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018549 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18550 "Internal error: xmlSchemaCheckFacet, "
18551 "failed to validate the value '%s' of the "
18552 "facet '%s' against the base type",
18553 facet->value, xmlSchemaFacetTypeToString(facet->type));
18554 }
18555 goto internal_error;
18556 }
18557 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18558 /* No error message for RelaxNG. */
18559 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018560 xmlChar *str = NULL;
18561
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018562 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018563 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018564 "The value '%s' of the facet does not validate "
18565 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566 facet->value,
18567 xmlSchemaFormatQName(&str,
18568 base->targetNamespace, base->name));
18569 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 goto exit;
18572 } else if (facet->val == NULL) {
18573 if (ctxtGiven) {
18574 PERROR_INT("xmlSchemaCheckFacet",
18575 "value was not computed");
18576 }
18577 TODO
18578 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018579 break;
18580 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018581 case XML_SCHEMA_FACET_PATTERN:
18582 facet->regexp = xmlRegexpCompile(facet->value);
18583 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018584 ret = XML_SCHEMAP_REGEXP_INVALID;
18585 /* No error message for RelaxNG. */
18586 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018587 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018588 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018589 "The value '%s' of the facet 'pattern' is not a "
18590 "valid regular expression",
18591 facet->value, NULL);
18592 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018593 }
18594 break;
18595 case XML_SCHEMA_FACET_TOTALDIGITS:
18596 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18597 case XML_SCHEMA_FACET_LENGTH:
18598 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018599 case XML_SCHEMA_FACET_MINLENGTH:
18600
18601 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18602 ret = xmlSchemaValidatePredefinedType(
18603 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18604 facet->value, &(facet->val));
18605 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018606 ret = xmlSchemaValidatePredefinedType(
18607 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18608 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018609 }
18610 if (ret != 0) {
18611 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018612 /* No error message for RelaxNG. */
18613 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018614 PERROR_INT("xmlSchemaCheckFacet",
18615 "validating facet value");
18616 }
18617 goto internal_error;
18618 }
18619 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18620 /* No error message for RelaxNG. */
18621 if (ctxtGiven) {
18622 /* error code */
18623 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18624 ret, facet->node, WXS_BASIC_CAST typeDecl,
18625 "The value '%s' of the facet '%s' is not a valid '%s'",
18626 facet->value,
18627 xmlSchemaFacetTypeToString(facet->type),
18628 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18629 BAD_CAST "nonNegativeInteger" :
18630 BAD_CAST "positiveInteger",
18631 NULL);
18632 }
18633 }
18634 break;
18635
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018636 case XML_SCHEMA_FACET_WHITESPACE:{
18637 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18638 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18639 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18640 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18641 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18642 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18643 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018644 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18645 /* No error message for RelaxNG. */
18646 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018647 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018648 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018649 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018650 "The value '%s' of the facet 'whitespace' is not "
18651 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018652 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018653 }
18654 }
18655 default:
18656 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018658exit:
18659 if ((! ctxtGiven) && (pctxt != NULL))
18660 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018661 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018662internal_error:
18663 if ((! ctxtGiven) && (pctxt != NULL))
18664 xmlSchemaFreeParserCtxt(pctxt);
18665 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018666}
18667
18668/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018669 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018670 * @typeDecl: the schema type definition
18671 * @ctxt: the schema parser context
18672 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018673 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018674 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018675static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018676xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018677 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018678{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018679 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018680 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018681 /*
18682 * NOTE: It is intended to use the facets list, instead
18683 * of facetSet.
18684 */
18685 if (typeDecl->facets != NULL) {
18686 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018687
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018688 /*
18689 * Temporarily assign the "schema" to the validation context
18690 * of the parser context. This is needed for NOTATION validation.
18691 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018692 if (pctxt->vctxt == NULL) {
18693 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18694 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018695 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018696 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018697 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018698 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18699 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018700 facet = facet->next;
18701 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018702 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018703 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018704 if (olderrs != pctxt->nberrors)
18705 return(pctxt->err);
18706 return(0);
18707exit_failure:
18708 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018709}
18710
18711/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018712 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018713 * @ctxtMGroup: the searched model group
18714 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018715 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018716 *
18717 * This one is intended to be used by
18718 * xmlSchemaCheckGroupDefCircular only.
18719 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018720 * Returns the particle with the circular model group definition reference,
18721 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018722 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018723static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018724xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018725 xmlSchemaTreeItemPtr particle)
18726{
18727 xmlSchemaTreeItemPtr circ = NULL;
18728 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018729 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018730
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018731 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018732 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018733 if (term == NULL)
18734 continue;
18735 switch (term->type) {
18736 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018737 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018738 if (gdef == groupDef)
18739 return (particle);
18740 /*
18741 * Mark this model group definition to avoid infinite
18742 * recursion on circular references not yet examined.
18743 */
18744 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18745 continue;
18746 if (gdef->children != NULL) {
18747 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18748 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18749 gdef->children->children);
18750 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18751 if (circ != NULL)
18752 return (circ);
18753 }
18754 break;
18755 case XML_SCHEMA_TYPE_SEQUENCE:
18756 case XML_SCHEMA_TYPE_CHOICE:
18757 case XML_SCHEMA_TYPE_ALL:
18758 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18759 if (circ != NULL)
18760 return (circ);
18761 break;
18762 default:
18763 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018764 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018765 }
18766 return (NULL);
18767}
18768
18769/**
18770 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018771 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018772 * @ctxt: the parser context
18773 * @name: the name
18774 *
18775 * Checks for circular references to model group definitions.
18776 */
18777static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018778xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018779 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018780{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018781 /*
18782 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018783 * 2 Circular groups are disallowed. That is, within the {particles}
18784 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018785 * is the group itself.
18786 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018787 if ((item == NULL) ||
18788 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18789 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018790 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018791 {
18792 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018793
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018794 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018795 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018796 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018797 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018798 * TODO: The error report is not adequate: this constraint
18799 * is defined for model groups but not definitions, but since
18800 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018801 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018802 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018803 */
18804 xmlSchemaPCustomErr(ctxt,
18805 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018806 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018807 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018808 "defined", xmlSchemaFormatQName(&str,
18809 item->targetNamespace, item->name));
18810 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018811 /*
18812 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018813 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018814 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018815 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018816 }
18817 }
18818}
18819
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018820/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018821 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018822 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018823 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018824 *
18825 * Assigns the model group of model group definitions to the "term"
18826 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018827 * In xmlSchemaResolveModelGroupParticleReferences the model group
18828 * definitions were assigned to the "term", since needed for the
18829 * circularity check.
18830 *
18831 * Schema Component Constraint:
18832 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018833 */
18834static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018835xmlSchemaModelGroupToModelGroupDefFixup(
18836 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18837 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018838{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018839 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18840
18841 while (particle != NULL) {
18842 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18843 ((WXS_PARTICLE_TERM(particle))->type !=
18844 XML_SCHEMA_TYPE_GROUP))
18845 {
18846 particle = WXS_PTC_CAST particle->next;
18847 continue;
18848 }
18849 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18850 /*
18851 * TODO: Remove the particle.
18852 */
18853 WXS_PARTICLE_TERM(particle) = NULL;
18854 particle = WXS_PTC_CAST particle->next;
18855 continue;
18856 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018857 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018858 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018859 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018860 WXS_PARTICLE_TERM(particle) =
18861 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18862
18863 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018864 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018865}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018866
18867/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018868 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018869 * @ctxtGr: the searched attribute group
18870 * @attr: the current attribute list to be processed
18871 *
18872 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018873 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018874 *
18875 * Returns the circular attribute grou reference, otherwise NULL.
18876 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018877static xmlSchemaQNameRefPtr
18878xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18879 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018880{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018881 xmlSchemaAttributeGroupPtr gr;
18882 xmlSchemaQNameRefPtr ref, circ;
18883 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018884 /*
18885 * We will search for an attribute group reference which
18886 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018887 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018888 for (i = 0; i < list->nbItems; i++) {
18889 ref = list->items[i];
18890 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18891 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18892 (ref->item != NULL))
18893 {
18894 gr = WXS_ATTR_GROUP_CAST ref->item;
18895 if (gr == ctxtGr)
18896 return(ref);
18897 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18898 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018899 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018900 * Mark as visited to avoid infinite recursion on
18901 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018902 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018903 if ((gr->attrUses) &&
18904 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18905 {
18906 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18907 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18908 (xmlSchemaItemListPtr) gr->attrUses);
18909 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18910 if (circ != NULL)
18911 return (circ);
18912 }
18913
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018914 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018915 }
18916 return (NULL);
18917}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018918
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018919/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018920 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018921 * attrGr: the attribute group definition
18922 * @ctxt: the parser context
18923 * @name: the name
18924 *
18925 * Checks for circular references of attribute groups.
18926 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018927static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018928xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018929 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018930{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018931 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018932 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018933 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018934 * 3 Circular group reference is disallowed outside <redefine>.
18935 * That is, unless this element information item's parent is
18936 * <redefine>, then among the [children], if any, there must
18937 * not be an <attributeGroup> with ref [attribute] which resolves
18938 * to the component corresponding to this <attributeGroup>. Indirect
18939 * circularity is also ruled out. That is, when QName resolution
18940 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18941 * any <attributeGroup>s with a ref [attribute] among the [children],
18942 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018943 * which resolves to the component corresponding to this <attributeGroup>.
18944 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018945 if (attrGr->attrUses == NULL)
18946 return(0);
18947 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18948 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018949 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018950 xmlSchemaQNameRefPtr circ;
18951
18952 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18953 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018954 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018955 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018956 /*
18957 * TODO: Report the referenced attr group as QName.
18958 */
18959 xmlSchemaPCustomErr(ctxt,
18960 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018961 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018962 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018963 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18964 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018965 /*
18966 * NOTE: We will cut the reference to avoid further
18967 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018968 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018969 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018970 circ->item = NULL;
18971 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018972 }
18973 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018974 return(0);
18975}
18976
18977static int
18978xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18979 xmlSchemaAttributeGroupPtr attrGr);
18980
18981/**
18982 * xmlSchemaExpandAttributeGroupRefs:
18983 * @pctxt: the parser context
18984 * @node: the node of the component holding the attribute uses
18985 * @completeWild: the intersected wildcard to be returned
18986 * @list: the attribute uses
18987 *
18988 * Substitutes contained attribute group references
18989 * for their attribute uses. Wilcards are intersected.
18990 * Attribute use prohibitions are removed from the list
18991 * and returned via the @prohibs list.
18992 * Pointlessness of attr. prohibs, if a matching attr. decl
18993 * is existent a well, are checked.
18994 */
18995static int
18996xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
18997 xmlSchemaBasicItemPtr item,
18998 xmlSchemaWildcardPtr *completeWild,
18999 xmlSchemaItemListPtr list,
19000 xmlSchemaItemListPtr prohibs)
19001{
19002 xmlSchemaAttributeGroupPtr gr;
19003 xmlSchemaAttributeUsePtr use;
19004 xmlSchemaItemListPtr sublist;
19005 int i, j;
19006 int created = (*completeWild == NULL) ? 0 : 1;
19007
19008 if (prohibs)
19009 prohibs->nbItems = 0;
19010
19011 for (i = 0; i < list->nbItems; i++) {
19012 use = list->items[i];
19013
19014 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19015 if (prohibs == NULL) {
19016 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19017 "unexpected attr prohibition found");
19018 return(-1);
19019 }
19020 /*
19021 * Remove from attribute uses.
19022 */
19023 if (xmlSchemaItemListRemove(list, i) == -1)
19024 return(-1);
19025 i--;
19026 /*
19027 * Note that duplicate prohibitions were already
19028 * handled at parsing time.
19029 */
19030 /*
19031 * Add to list of prohibitions.
19032 */
19033 xmlSchemaItemListAddSize(prohibs, 2, use);
19034 continue;
19035 }
19036 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19037 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19038 {
19039 if ((WXS_QNAME_CAST use)->item == NULL)
19040 return(-1);
19041 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19042 /*
19043 * Expand the referenced attr. group.
19044 * TODO: remove this, this is done in a previous step, so
19045 * already done here.
19046 */
19047 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19048 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19049 return(-1);
19050 }
19051 /*
19052 * Build the 'complete' wildcard; i.e. intersect multiple
19053 * wildcards.
19054 */
19055 if (gr->attributeWildcard != NULL) {
19056 if (*completeWild == NULL) {
19057 *completeWild = gr->attributeWildcard;
19058 } else {
19059 if (! created) {
19060 xmlSchemaWildcardPtr tmpWild;
19061
19062 /*
19063 * Copy the first encountered wildcard as context,
19064 * except for the annotation.
19065 *
19066 * Although the complete wildcard might not correspond
19067 * to any node in the schema, we will anchor it on
19068 * the node of the owner component.
19069 */
19070 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19071 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19072 WXS_ITEM_NODE(item));
19073 if (tmpWild == NULL)
19074 return(-1);
19075 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19076 tmpWild, *completeWild) == -1)
19077 return (-1);
19078 tmpWild->processContents = (*completeWild)->processContents;
19079 *completeWild = tmpWild;
19080 created = 1;
19081 }
19082
19083 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19084 gr->attributeWildcard) == -1)
19085 return(-1);
19086 }
19087 }
19088 /*
19089 * Just remove the reference if the referenced group does not
19090 * contain any attribute uses.
19091 */
19092 if (gr->attrUses == NULL) {
19093 if (xmlSchemaItemListRemove(list, i) == -1)
19094 return(-1);
19095 i--;
19096 continue;
19097 }
19098 /*
19099 * Add the attribute uses.
19100 */
19101 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19102 if (sublist->nbItems != 0) {
19103 list->items[i] = sublist->items[0];
19104 if (sublist->nbItems != 1) {
19105 for (j = 1; j < sublist->nbItems; j++) {
19106 i++;
19107 if (xmlSchemaItemListInsert(list,
19108 sublist->items[j], i) == -1)
19109 return(-1);
19110 }
19111 }
19112 }
19113 }
19114
19115 }
19116 /*
19117 * Handle pointless prohibitions of declared attributes.
19118 */
19119 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19120 xmlSchemaAttributeUseProhibPtr prohib;
19121
19122 for (i = prohibs->nbItems -1; i >= 0; i--) {
19123 prohib = prohibs->items[i];
19124 for (j = 0; j < list->nbItems; j++) {
19125 use = list->items[j];
19126
19127 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19128 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19129 {
19130 xmlChar *str = NULL;
19131
19132 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19133 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19134 prohib->node, NULL,
19135 "Skipping pointless attribute use prohibition "
19136 "'%s', since a corresponding attribute use "
19137 "exists already in the type definition",
19138 xmlSchemaFormatQName(&str,
19139 prohib->targetNamespace, prohib->name),
19140 NULL, NULL);
19141 FREE_AND_NULL(str);
19142 /*
19143 * Remove the prohibition.
19144 */
19145 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19146 return(-1);
19147 break;
19148 }
19149 }
19150 }
19151 }
19152 return(0);
19153}
19154
19155/**
19156 * xmlSchemaAttributeGroupExpandRefs:
19157 * @pctxt: the parser context
19158 * @attrGr: the attribute group definition
19159 *
19160 * Computation of:
19161 * {attribute uses} property
19162 * {attribute wildcard} property
19163 *
19164 * Substitutes contained attribute group references
19165 * for their attribute uses. Wilcards are intersected.
19166 */
19167static int
19168xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19169 xmlSchemaAttributeGroupPtr attrGr)
19170{
19171 if ((attrGr->attrUses == NULL) ||
19172 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19173 return(0);
19174
19175 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19176 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19177 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19178 return(-1);
19179 return(0);
19180}
19181
19182/**
19183 * xmlSchemaAttributeGroupExpandRefs:
19184 * @pctxt: the parser context
19185 * @attrGr: the attribute group definition
19186 *
19187 * Substitutes contained attribute group references
19188 * for their attribute uses. Wilcards are intersected.
19189 *
19190 * Schema Component Constraint:
19191 * Attribute Group Definition Properties Correct (ag-props-correct)
19192 */
19193static int
19194xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19195 xmlSchemaAttributeGroupPtr attrGr)
19196{
19197 /*
19198 * SPEC ag-props-correct
19199 * (1) "The values of the properties of an attribute group definition
19200 * must be as described in the property tableau in The Attribute
19201 * Group Definition Schema Component (§3.6.1), modulo the impact of
19202 * Missing Sub-components (§5.3);"
19203 */
19204
19205 if ((attrGr->attrUses != NULL) &&
19206 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19207 {
19208 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19209 xmlSchemaAttributeUsePtr use, tmp;
19210 int i, j, hasId = 0;
19211
19212 for (i = uses->nbItems -1; i >= 0; i--) {
19213 use = uses->items[i];
19214 /*
19215 * SPEC ag-props-correct
19216 * (2) "Two distinct members of the {attribute uses} must not have
19217 * {attribute declaration}s both of whose {name}s match and whose
19218 * {target namespace}s are identical."
19219 */
19220 if (i > 0) {
19221 for (j = i -1; j >= 0; j--) {
19222 tmp = uses->items[j];
19223 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19224 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19225 (WXS_ATTRUSE_DECL_TNS(use) ==
19226 WXS_ATTRUSE_DECL_TNS(tmp)))
19227 {
19228 xmlChar *str = NULL;
19229
19230 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19231 XML_SCHEMAP_AG_PROPS_CORRECT,
19232 attrGr->node, WXS_BASIC_CAST attrGr,
19233 "Duplicate %s",
19234 xmlSchemaGetComponentDesignation(&str, use),
19235 NULL);
19236 FREE_AND_NULL(str);
19237 /*
19238 * Remove the duplicate.
19239 */
19240 if (xmlSchemaItemListRemove(uses, i) == -1)
19241 return(-1);
19242 goto next_use;
19243 }
19244 }
19245 }
19246 /*
19247 * SPEC ag-props-correct
19248 * (3) "Two distinct members of the {attribute uses} must not have
19249 * {attribute declaration}s both of whose {type definition}s are or
19250 * are derived from ID."
19251 * TODO: Does 'derived' include member-types of unions?
19252 */
19253 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19254 if (xmlSchemaIsDerivedFromBuiltInType(
19255 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19256 {
19257 if (hasId) {
19258 xmlChar *str = NULL;
19259
19260 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19261 XML_SCHEMAP_AG_PROPS_CORRECT,
19262 attrGr->node, WXS_BASIC_CAST attrGr,
19263 "There must not exist more than one attribute "
19264 "declaration of type 'xs:ID' "
19265 "(or derived from 'xs:ID'). The %s violates this "
19266 "constraint",
19267 xmlSchemaGetComponentDesignation(&str, use),
19268 NULL);
19269 FREE_AND_NULL(str);
19270 if (xmlSchemaItemListRemove(uses, i) == -1)
19271 return(-1);
19272 }
19273 hasId = 1;
19274 }
19275 }
19276next_use: {}
19277 }
19278 }
19279 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019280}
19281
19282/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019283 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019284 * @attrgrpDecl: the schema attribute definition
19285 * @ctxt: the schema parser context
19286 * @name: the attribute name
19287 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019288 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019289 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019290static int
19291xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19292 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019293{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019294 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019295
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019296 if (ref->item != NULL)
19297 return(0);
19298 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19299 ref->name,
19300 ref->targetNamespace);
19301 if (group == NULL) {
19302 xmlSchemaPResCompAttrErr(ctxt,
19303 XML_SCHEMAP_SRC_RESOLVE,
19304 NULL, ref->node,
19305 "ref", ref->name, ref->targetNamespace,
19306 ref->itemType, NULL);
19307 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019308 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019309 ref->item = WXS_BASIC_CAST group;
19310 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019311}
19312
19313/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019314 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019315 * @item: an schema attribute declaration/use
19316 * @ctxt: a schema parser context
19317 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019318 *
19319 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019320 * Schema Component Constraint:
19321 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019322 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019323 * Validates the value constraints of an attribute declaration/use.
19324 * NOTE that this needs the simle type definitions to be already
19325 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019326 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019327static int
19328xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19329 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019330{
19331
19332 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019333 * SPEC a-props-correct (1)
19334 * "The values of the properties of an attribute declaration must
19335 * be as described in the property tableau in The Attribute
19336 * Declaration Schema Component (§3.2.1), modulo the impact of
19337 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019338 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019339
19340 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19341 return(0);
19342
19343 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019344 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019345
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019346 /*
19347 * SPEC a-props-correct (3)
19348 * "If the {type definition} is or is derived from ID then there
19349 * must not be a {value constraint}."
19350 */
19351 if (xmlSchemaIsDerivedFromBuiltInType(
19352 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19353 {
19354 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19355 XML_SCHEMAP_A_PROPS_CORRECT_3,
19356 NULL, WXS_BASIC_CAST attr,
19357 "Value constraints are not allowed if the type definition "
19358 "is or is derived from xs:ID",
19359 NULL, NULL);
19360 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019361 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019362 /*
19363 * SPEC a-props-correct (2)
19364 * "if there is a {value constraint}, the canonical lexical
19365 * representation of its value must be ·valid· with respect
19366 * to the {type definition} as defined in String Valid (§3.14.4)."
19367 * TODO: Don't care about the *cononical* stuff here, this requirement
19368 * will be removed in WXS 1.1 anyway.
19369 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019370 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019371 attr->node, WXS_ATTR_TYPEDEF(attr),
19372 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019373 1, 1, 0);
19374 if (ret != 0) {
19375 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019376 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019377 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019378 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019379 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019380 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019381 XML_SCHEMAP_A_PROPS_CORRECT_2,
19382 NULL, WXS_BASIC_CAST attr,
19383 "The value of the value constraint is not valid",
19384 NULL, NULL);
19385 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019387 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019388
19389 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019390}
19391
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019392static xmlSchemaElementPtr
19393xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19394 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019395{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019396 xmlSchemaElementPtr ret;
19397
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019398 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019399 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019400 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019401 return (ancestor);
19402
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019403 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019404 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019405 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019406 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019407 WXS_SUBST_HEAD(ancestor));
19408 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019409
19410 return (ret);
19411}
19412
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019413/**
19414 * xmlSchemaCheckElemPropsCorrect:
19415 * @ctxt: a schema parser context
19416 * @decl: the element declaration
19417 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019418 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019419 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019420 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019421 *
19422 * STATUS:
19423 * missing: (6)
19424 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019425static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019426xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19427 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019428{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019429 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019430 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019431 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019432 * SPEC (1) "The values of the properties of an element declaration
19433 * must be as described in the property tableau in The Element
19434 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19435 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019436 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019437 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19438 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019439
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019440 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019441 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019442 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019443 * affiliation}, then {scope} must be global."
19444 */
19445 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19446 xmlSchemaPCustomErr(pctxt,
19447 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019448 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019449 "Only global element declarations can have a "
19450 "substitution group affiliation", NULL);
19451 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019452 }
19453 /*
19454 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19455 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019456 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019457 * property."
19458 */
19459 if (head == elemDecl)
19460 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019461 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019462 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19463 else
19464 circ = NULL;
19465 if (circ != NULL) {
19466 xmlChar *strA = NULL, *strB = NULL;
19467
19468 xmlSchemaPCustomErrExt(pctxt,
19469 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019470 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019471 "The element declaration '%s' defines a circular "
19472 "substitution group to element declaration '%s'",
19473 xmlSchemaGetComponentQName(&strA, circ),
19474 xmlSchemaGetComponentQName(&strB, head),
19475 NULL);
19476 FREE_AND_NULL(strA)
19477 FREE_AND_NULL(strB)
19478 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19479 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019480 /*
19481 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019482 * the {type definition}
19483 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019484 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019485 * of the {substitution group exclusions} of the {substitution group
19486 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19487 * (if the {type definition} is complex) or as defined in
19488 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019489 * simple)."
19490 *
19491 * NOTE: {substitution group exclusions} means the values of the
19492 * attribute "final".
19493 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019494
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019495 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019496 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019497
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019498 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19499 set |= SUBSET_EXTENSION;
19500 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19501 set |= SUBSET_RESTRICTION;
19502
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019503 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019504 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019505 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19506
19507 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019508 xmlSchemaPCustomErrExt(pctxt,
19509 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019510 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019511 "The type definition '%s' was "
19512 "either rejected by the substitution group "
19513 "affiliation '%s', or not validly derived from its type "
19514 "definition '%s'",
19515 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019516 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019517 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019518 FREE_AND_NULL(strA)
19519 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019520 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019521 }
19522 }
19523 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019524 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019525 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019526 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019527 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019528 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019529 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019530 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019531 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019532 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019533 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019534 (WXS_IS_COMPLEX(typeDef) &&
19535 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019536 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19537 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019538
19539 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19540 xmlSchemaPCustomErr(pctxt,
19541 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019542 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019543 "The type definition (or type definition's content type) is or "
19544 "is derived from ID; value constraints are not allowed in "
19545 "conjunction with such a type definition", NULL);
19546 } else if (elemDecl->value != NULL) {
19547 int vcret;
19548 xmlNodePtr node = NULL;
19549
19550 /*
19551 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19552 * representation of its value must be ·valid· with respect to the
19553 * {type definition} as defined in Element Default Valid (Immediate)
19554 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019555 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019556 if (typeDef == NULL) {
19557 xmlSchemaPErr(pctxt, elemDecl->node,
19558 XML_SCHEMAP_INTERNAL,
19559 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19560 "type is missing... skipping validation of "
19561 "the value constraint", NULL, NULL);
19562 return (-1);
19563 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019564 if (elemDecl->node != NULL) {
19565 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19566 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19567 BAD_CAST "fixed");
19568 else
19569 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19570 BAD_CAST "default");
19571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019572 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19573 typeDef, elemDecl->value, &(elemDecl->defVal));
19574 if (vcret != 0) {
19575 if (vcret < 0) {
19576 PERROR_INT("xmlSchemaElemCheckValConstr",
19577 "failed to validate the value constraint of an "
19578 "element declaration");
19579 return (-1);
19580 }
19581 return (vcret);
19582 }
19583 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019584
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019585 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019586}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019587
19588/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019589 * xmlSchemaCheckElemSubstGroup:
19590 * @ctxt: a schema parser context
19591 * @decl: the element declaration
19592 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019593 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019594 * Schema Component Constraint:
19595 * Substitution Group (cos-equiv-class)
19596 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019597 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019598 * a list will be built for each subst. group head, holding all direct
19599 * referents to this head.
19600 * NOTE that this function needs:
19601 * 1. circular subst. groups to be checked beforehand
19602 * 2. the declaration's type to be derived from the head's type
19603 *
19604 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019605 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019606 */
19607static void
19608xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19609 xmlSchemaElementPtr elemDecl)
19610{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019611 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019612 /* SPEC (1) "Its {abstract} is false." */
19613 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19614 return;
19615 {
19616 xmlSchemaElementPtr head;
19617 xmlSchemaTypePtr headType, type;
19618 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019619 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019620 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19621 * {disallowed substitutions} as the blocking constraint, as defined in
19622 * Substitution Group OK (Transitive) (§3.3.6)."
19623 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019624 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19625 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019626 set = 0;
19627 methSet = 0;
19628 /*
19629 * The blocking constraints.
19630 */
19631 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19632 continue;
19633 headType = head->subtypes;
19634 type = elemDecl->subtypes;
19635 if (headType == type)
19636 goto add_member;
19637 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19638 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19639 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19640 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19641 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019642 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019643 * "The set of all {derivation method}s involved in the
19644 * derivation of D's {type definition} from C's {type definition}
19645 * does not intersect with the union of the blocking constraint,
19646 * C's {prohibited substitutions} (if C is complex, otherwise the
19647 * empty set) and the {prohibited substitutions} (respectively the
19648 * empty set) of any intermediate {type definition}s in the
19649 * derivation of D's {type definition} from C's {type definition}."
19650 */
19651 /*
19652 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19653 * subst.head axis, the methSet does not need to be computed for
19654 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019655 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019656 /*
19657 * The set of all {derivation method}s involved in the derivation
19658 */
19659 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019660 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019661 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19662 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019663
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019664 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019665 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19666 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19667
19668 type = type->baseType;
19669 }
19670 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019671 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019672 * the head's type.
19673 */
19674 type = elemDecl->subtypes->baseType;
19675 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019676 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019677 if ((type->flags &
19678 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19679 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19680 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19681 if ((type->flags &
19682 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19683 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19684 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19685 } else
19686 break;
19687 if (type == headType)
19688 break;
19689 type = type->baseType;
19690 }
19691 if ((set != 0) &&
19692 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19693 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19694 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19695 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19696 continue;
19697 }
19698add_member:
19699 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19700 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19701 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19702 }
19703 }
19704}
19705
19706/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019707 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019708 * @item: an schema element declaration/particle
19709 * @ctxt: a schema parser context
19710 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019711 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019712 * Validates the value constraints of an element declaration.
19713 *
19714 * Fixes finish doing the computations on the element declarations.
19715 */
19716static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019717xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019718 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019719{
19720 if (elemDecl == NULL)
19721 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019722 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19723 return;
19724 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019725 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19726 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019727}
19728
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019729/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019730 * xmlSchemaResolveModelGroupParticleReferences:
19731 * @particle: a particle component
19732 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019733 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019734 * Resolves references of a model group's {particles} to
19735 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019736 */
19737static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019738xmlSchemaResolveModelGroupParticleReferences(
19739 xmlSchemaParserCtxtPtr ctxt,
19740 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019741{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019742 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19743 xmlSchemaQNameRefPtr ref;
19744 xmlSchemaBasicItemPtr refItem;
19745
19746 /*
19747 * URGENT TODO: Test this.
19748 */
19749 while (particle != NULL) {
19750 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19751 ((WXS_PARTICLE_TERM(particle))->type !=
19752 XML_SCHEMA_EXTRA_QNAMEREF))
19753 {
19754 goto next_particle;
19755 }
19756 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019757 /*
19758 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019759 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019760 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019761 particle->children = NULL;
19762
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019763 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19764 ref->itemType, ref->name, ref->targetNamespace);
19765 if (refItem == NULL) {
19766 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019767 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019768 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019769 /* TODO: remove the particle. */
19770 goto next_particle;
19771 }
19772 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19773 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19774 /* TODO: remove the particle. */
19775 goto next_particle;
19776 /*
19777 * NOTE that we will assign the model group definition
19778 * itself to the "term" of the particle. This will ease
19779 * the check for circular model group definitions. After
19780 * that the "term" will be assigned the model group of the
19781 * model group definition.
19782 */
19783 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19784 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019785 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019786 * SPEC cos-all-limited (1)
19787 * SPEC cos-all-limited (1.2)
19788 * "It appears only as the value of one or both of the
19789 * following properties:"
19790 * (1.1) "the {model group} property of a model group
19791 * definition."
19792 * (1.2) "the {term} property of a particle [... of] the "
19793 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019794 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019795 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19796 /* TODO: error code */
19797 XML_SCHEMAP_COS_ALL_LIMITED,
19798 WXS_ITEM_NODE(particle), NULL,
19799 "A model group definition is referenced, but "
19800 "it contains an 'all' model group, which "
19801 "cannot be contained by model groups",
19802 NULL, NULL);
19803 /* TODO: remove the particle. */
19804 goto next_particle;
19805 }
19806 particle->children = (xmlSchemaTreeItemPtr) refItem;
19807 } else {
19808 /*
19809 * TODO: Are referenced element declarations the only
19810 * other components we expect here?
19811 */
19812 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019813 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019814next_particle:
19815 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019816 }
19817}
19818
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019819static int
19820xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19821 xmlSchemaValPtr y)
19822{
19823 xmlSchemaTypePtr tx, ty, ptx, pty;
19824 int ret;
19825
19826 while (x != NULL) {
19827 /* Same types. */
19828 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19829 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19830 ptx = xmlSchemaGetPrimitiveType(tx);
19831 pty = xmlSchemaGetPrimitiveType(ty);
19832 /*
19833 * (1) if a datatype T' is ·derived· by ·restriction· from an
19834 * atomic datatype T then the ·value space· of T' is a subset of
19835 * the ·value space· of T. */
19836 /*
19837 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19838 * from a common atomic ancestor T then the ·value space·s of T'
19839 * and T'' may overlap.
19840 */
19841 if (ptx != pty)
19842 return(0);
19843 /*
19844 * We assume computed values to be normalized, so do a fast
19845 * string comparison for string based types.
19846 */
19847 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019848 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019849 if (! xmlStrEqual(
19850 xmlSchemaValueGetAsString(x),
19851 xmlSchemaValueGetAsString(y)))
19852 return (0);
19853 } else {
19854 ret = xmlSchemaCompareValuesWhtsp(
19855 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19856 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19857 if (ret == -2)
19858 return(-1);
19859 if (ret != 0)
19860 return(0);
19861 }
19862 /*
19863 * Lists.
19864 */
19865 x = xmlSchemaValueGetNext(x);
19866 if (x != NULL) {
19867 y = xmlSchemaValueGetNext(y);
19868 if (y == NULL)
19869 return (0);
19870 } else if (xmlSchemaValueGetNext(y) != NULL)
19871 return (0);
19872 else
19873 return (1);
19874 }
19875 return (0);
19876}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019877
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019878/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019879 * xmlSchemaResolveAttrUseReferences:
19880 * @item: an attribute use
19881 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019882 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019883 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019884 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019885static int
19886xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19887 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019888{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019889 if ((ctxt == NULL) || (ause == NULL))
19890 return(-1);
19891 if ((ause->attrDecl == NULL) ||
19892 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19893 return(0);
19894
19895 {
19896 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19897
19898 /*
19899 * TODO: Evaluate, what errors could occur if the declaration is not
19900 * found.
19901 */
19902 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19903 ref->name, ref->targetNamespace);
19904 if (ause->attrDecl == NULL) {
19905 xmlSchemaPResCompAttrErr(ctxt,
19906 XML_SCHEMAP_SRC_RESOLVE,
19907 WXS_BASIC_CAST ause, ause->node,
19908 "ref", ref->name, ref->targetNamespace,
19909 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19910 return(ctxt->err);;
19911 }
19912 }
19913 return(0);
19914}
19915
19916/**
19917 * xmlSchemaCheckAttrUsePropsCorrect:
19918 * @ctxt: a parser context
19919 * @use: an attribute use
19920 *
19921 * Schema Component Constraint:
19922 * Attribute Use Correct (au-props-correct)
19923 *
19924 */
19925static int
19926xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19927 xmlSchemaAttributeUsePtr use)
19928{
19929 if ((ctxt == NULL) || (use == NULL))
19930 return(-1);
19931 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19932 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19933 return(0);
19934
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019935 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019936 * SPEC au-props-correct (1)
19937 * "The values of the properties of an attribute use must be as
19938 * described in the property tableau in The Attribute Use Schema
19939 * Component (§3.5.1), modulo the impact of Missing
19940 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019941 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019942
19943 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19944 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19945 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19946 {
19947 xmlSchemaPCustomErr(ctxt,
19948 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19949 WXS_BASIC_CAST use, NULL,
19950 "The attribute declaration has a 'fixed' value constraint "
19951 ", thus the attribute use must also have a 'fixed' value "
19952 "constraint",
19953 NULL);
19954 return(ctxt->err);
19955 }
19956 /*
19957 * Compute and check the value constraint's value.
19958 */
19959 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19960 int ret;
19961 /*
19962 * TODO: The spec seems to be missing a check of the
19963 * value constraint of the attribute use. We will do it here.
19964 */
19965 /*
19966 * SPEC a-props-correct (3)
19967 */
19968 if (xmlSchemaIsDerivedFromBuiltInType(
19969 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19970 {
19971 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19972 XML_SCHEMAP_AU_PROPS_CORRECT,
19973 NULL, WXS_BASIC_CAST use,
19974 "Value constraints are not allowed if the type definition "
19975 "is or is derived from xs:ID",
19976 NULL, NULL);
19977 return(ctxt->err);
19978 }
19979
19980 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19981 use->node, WXS_ATTRUSE_TYPEDEF(use),
19982 use->defValue, &(use->defVal),
19983 1, 1, 0);
19984 if (ret != 0) {
19985 if (ret < 0) {
19986 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19987 "calling xmlSchemaVCheckCVCSimpleType()");
19988 return(-1);
19989 }
19990 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19991 XML_SCHEMAP_AU_PROPS_CORRECT,
19992 NULL, WXS_BASIC_CAST use,
19993 "The value of the value constraint is not valid",
19994 NULL, NULL);
19995 return(ctxt->err);
19996 }
19997 }
19998 /*
19999 * SPEC au-props-correct (2)
20000 * "If the {attribute declaration} has a fixed
20001 * {value constraint}, then if the attribute use itself has a
20002 * {value constraint}, it must also be fixed and its value must match
20003 * that of the {attribute declaration}'s {value constraint}."
20004 */
20005 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20006 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20007 {
20008 if (! xmlSchemaAreValuesEqual(use->defVal,
20009 (WXS_ATTRUSE_DECL(use))->defVal))
20010 {
20011 xmlSchemaPCustomErr(ctxt,
20012 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20013 WXS_BASIC_CAST use, NULL,
20014 "The 'fixed' value constraint of the attribute use "
20015 "must match the attribute declaration's value "
20016 "constraint '%s'",
20017 (WXS_ATTRUSE_DECL(use))->defValue);
20018 }
20019 return(ctxt->err);
20020 }
20021 return(0);
20022}
20023
20024
20025
20026
20027/**
20028 * xmlSchemaResolveAttrTypeReferences:
20029 * @item: an attribute declaration
20030 * @ctxt: a parser context
20031 *
20032 * Resolves the referenced type definition component.
20033 */
20034static int
20035xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20036 xmlSchemaParserCtxtPtr ctxt)
20037{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020038 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020039 * The simple type definition corresponding to the <simpleType> element
20040 * information item in the [children], if present, otherwise the simple
20041 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020042 * [attribute], if present, otherwise the ·simple ur-type definition·.
20043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020044 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020045 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020046 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20047 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020048 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020049 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020050 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020051
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020052 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20053 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020054 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020055 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020056 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020057 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020058 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020059 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020060 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020061 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020062 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020063
Daniel Veillard3646d642004-06-02 19:19:14 +000020064 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020065 /*
20066 * The type defaults to the xs:anySimpleType.
20067 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020068 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20069 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020070 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020071}
20072
20073/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020074 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020075 * @idc: the identity-constraint definition
20076 * @ctxt: the schema parser context
20077 * @name: the attribute name
20078 *
20079 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020080 * Schema Component Constraint:
20081 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020082 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020083static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020084xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020085 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020086{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020087 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020088 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020089 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020090 idc->ref->item = (xmlSchemaBasicItemPtr)
20091 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20092 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020093 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020094 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020095 * TODO: It is actually not an error to fail to resolve
20096 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020097 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020098 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020099 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020100 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020101 "refer", idc->ref->name,
20102 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020103 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020104 return(pctxt->err);
20105 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20106 /*
20107 * SPEC c-props-correct (1)
20108 */
20109 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20110 XML_SCHEMAP_C_PROPS_CORRECT,
20111 NULL, WXS_BASIC_CAST idc,
20112 "The keyref references a keyref",
20113 NULL, NULL);
20114 idc->ref->item = NULL;
20115 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020116 } else {
20117 if (idc->nbFields !=
20118 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20119 xmlChar *str = NULL;
20120 xmlSchemaIDCPtr refer;
20121
20122 refer = (xmlSchemaIDCPtr) idc->ref->item;
20123 /*
20124 * SPEC c-props-correct(2)
20125 * "If the {identity-constraint category} is keyref,
20126 * the cardinality of the {fields} must equal that of
20127 * the {fields} of the {referenced key}.
20128 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020129 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020130 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020131 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020132 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020133 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020134 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020135 refer->name),
20136 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020137 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020138 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020139 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020140 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020141 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020142 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020143}
20144
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020145static int
20146xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20147 xmlSchemaParserCtxtPtr pctxt)
20148{
20149 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20150 prohib->targetNamespace) == NULL) {
20151
20152 xmlSchemaPResCompAttrErr(pctxt,
20153 XML_SCHEMAP_SRC_RESOLVE,
20154 NULL, prohib->node,
20155 "ref", prohib->name, prohib->targetNamespace,
20156 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20157 return(XML_SCHEMAP_SRC_RESOLVE);
20158 }
20159 return(0);
20160}
20161
20162#define WXS_REDEFINED_TYPE(c) \
20163(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20164
20165#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20166(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20167
20168#define WXS_REDEFINED_ATTR_GROUP(c) \
20169(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20170
20171static int
20172xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20173{
20174 int err = 0;
20175 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20176 xmlSchemaBasicItemPtr prev, item;
20177 int wasRedefined;
20178
20179 if (redef == NULL)
20180 return(0);
20181
20182 do {
20183 item = redef->item;
20184 /*
20185 * First try to locate the redefined component in the
20186 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020187 * NOTE: According to this schema bug entry:
20188 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20189 * it's not clear if the referenced component needs to originate
20190 * from the <redefine>d schema _document_ or the schema; the latter
20191 * would include all imported and included sub-schemas of the
20192 * <redefine>d schema. Currenlty we latter approach is used.
20193 * SUPPLEMENT: It seems that the WG moves towards the latter
20194 * approach, so we are doing it right.
20195 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020196 */
20197 prev = xmlSchemaFindRedefCompInGraph(
20198 redef->targetBucket, item->type,
20199 redef->refName, redef->refTargetNs);
20200 if (prev == NULL) {
20201 xmlChar *str = NULL;
20202 xmlNodePtr node;
20203
20204 /*
20205 * SPEC src-redefine:
20206 * (6.2.1) "The ·actual value· of its own name attribute plus
20207 * target namespace must successfully ·resolve· to a model
20208 * group definition in I."
20209 * (7.2.1) "The ·actual value· of its own name attribute plus
20210 * target namespace must successfully ·resolve· to an attribute
20211 * group definition in I."
20212
20213 *
20214 * Note that, if we are redefining with the use of references
20215 * to components, the spec assumes the src-resolve to be used;
20216 * but this won't assure that we search only *inside* the
20217 * redefined schema.
20218 */
20219 if (redef->reference)
20220 node = WXS_ITEM_NODE(redef->reference);
20221 else
20222 node = WXS_ITEM_NODE(item);
20223 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20224 /*
20225 * TODO: error code.
20226 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20227 * reference kind.
20228 */
20229 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020230 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020231 "the redefined schema",
20232 WXS_ITEM_TYPE_NAME(item),
20233 xmlSchemaFormatQName(&str, redef->refTargetNs,
20234 redef->refName));
20235 FREE_AND_NULL(str);
20236 err = pctxt->err;
20237 redef = redef->next;
20238 continue;
20239 }
20240 /*
20241 * TODO: Obtaining and setting the redefinition state is really
20242 * clumsy.
20243 */
20244 wasRedefined = 0;
20245 switch (item->type) {
20246 case XML_SCHEMA_TYPE_COMPLEX:
20247 case XML_SCHEMA_TYPE_SIMPLE:
20248 if ((WXS_TYPE_CAST prev)->flags &
20249 XML_SCHEMAS_TYPE_REDEFINED)
20250 {
20251 wasRedefined = 1;
20252 break;
20253 }
20254 /* Mark it as redefined. */
20255 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20256 /*
20257 * Assign the redefined type to the
20258 * base type of the redefining type.
20259 * TODO: How
20260 */
20261 ((xmlSchemaTypePtr) item)->baseType =
20262 (xmlSchemaTypePtr) prev;
20263 break;
20264 case XML_SCHEMA_TYPE_GROUP:
20265 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20266 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20267 {
20268 wasRedefined = 1;
20269 break;
20270 }
20271 /* Mark it as redefined. */
20272 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20273 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20274 if (redef->reference != NULL) {
20275 /*
20276 * Overwrite the QName-reference with the
20277 * referenced model group def.
20278 */
20279 (WXS_PTC_CAST redef->reference)->children =
20280 WXS_TREE_CAST prev;
20281 }
20282 redef->target = prev;
20283 break;
20284 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20285 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20286 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20287 {
20288 wasRedefined = 1;
20289 break;
20290 }
20291 (WXS_ATTR_GROUP_CAST prev)->flags |=
20292 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20293 if (redef->reference != NULL) {
20294 /*
20295 * Assign the redefined attribute group to the
20296 * QName-reference component.
20297 * This is the easy case, since we will just
20298 * expand the redefined group.
20299 */
20300 (WXS_QNAME_CAST redef->reference)->item = prev;
20301 redef->target = NULL;
20302 } else {
20303 /*
20304 * This is the complicated case: we need
20305 * to apply src-redefine (7.2.2) at a later
20306 * stage, i.e. when attribute group references
20307 * have beed expanded and simple types have
20308 * beed fixed.
20309 */
20310 redef->target = prev;
20311 }
20312 break;
20313 default:
20314 PERROR_INT("xmlSchemaResolveRedefReferences",
20315 "Unexpected redefined component type");
20316 return(-1);
20317 }
20318 if (wasRedefined) {
20319 xmlChar *str = NULL;
20320 xmlNodePtr node;
20321
20322 if (redef->reference)
20323 node = WXS_ITEM_NODE(redef->reference);
20324 else
20325 node = WXS_ITEM_NODE(redef->item);
20326
20327 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20328 /* TODO: error code. */
20329 XML_SCHEMAP_SRC_REDEFINE,
20330 node, NULL,
20331 "The referenced %s was already redefined. Multiple "
20332 "redefinition of the same component is not supported",
20333 xmlSchemaGetComponentDesignation(&str, prev),
20334 NULL);
20335 FREE_AND_NULL(str)
20336 err = pctxt->err;
20337 redef = redef->next;
20338 continue;
20339 }
20340 redef = redef->next;
20341 } while (redef != NULL);
20342
20343 return(err);
20344}
20345
20346static int
20347xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20348{
20349 int err = 0;
20350 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20351 xmlSchemaBasicItemPtr item;
20352
20353 if (redef == NULL)
20354 return(0);
20355
20356 do {
20357 if (redef->target == NULL) {
20358 redef = redef->next;
20359 continue;
20360 }
20361 item = redef->item;
20362
20363 switch (item->type) {
20364 case XML_SCHEMA_TYPE_SIMPLE:
20365 case XML_SCHEMA_TYPE_COMPLEX:
20366 /*
20367 * Since the spec wants the {name} of the redefined
20368 * type to be 'absent', we'll NULL it.
20369 */
20370 (WXS_TYPE_CAST redef->target)->name = NULL;
20371
20372 /*
20373 * TODO: Seems like there's nothing more to do. The normal
20374 * inheritance mechanism is used. But not 100% sure.
20375 */
20376 break;
20377 case XML_SCHEMA_TYPE_GROUP:
20378 /*
20379 * URGENT TODO:
20380 * SPEC src-redefine:
20381 * (6.2.2) "The {model group} of the model group definition
20382 * which corresponds to it per XML Representation of Model
20383 * Group Definition Schema Components (§3.7.2) must be a
20384 * ·valid restriction· of the {model group} of that model
20385 * group definition in I, as defined in Particle Valid
20386 * (Restriction) (§3.9.6)."
20387 */
20388 break;
20389 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20390 /*
20391 * SPEC src-redefine:
20392 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20393 * the attribute group definition which corresponds to it
20394 * per XML Representation of Attribute Group Definition Schema
20395 * Components (§3.6.2) must be ·valid restrictions· of the
20396 * {attribute uses} and {attribute wildcard} of that attribute
20397 * group definition in I, as defined in clause 2, clause 3 and
20398 * clause 4 of Derivation Valid (Restriction, Complex)
20399 * (§3.4.6) (where references to the base type definition are
20400 * understood as references to the attribute group definition
20401 * in I)."
20402 */
20403 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20404 XML_SCHEMA_ACTION_REDEFINE,
20405 item, redef->target,
20406 (WXS_ATTR_GROUP_CAST item)->attrUses,
20407 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20408 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20409 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20410 if (err == -1)
20411 return(-1);
20412 break;
20413 default:
20414 break;
20415 }
20416 redef = redef->next;
20417 } while (redef != NULL);
20418 return(0);
20419}
20420
20421
20422static int
20423xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20424 xmlSchemaBucketPtr bucket)
20425{
20426 xmlSchemaBasicItemPtr item;
20427 int err;
20428 xmlHashTablePtr *table;
20429 const xmlChar *name;
20430 int i;
20431
20432#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20433 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20434 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20435 else \
20436 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20437
20438 /*
20439 * Add global components to the schema's hash tables.
20440 * This is the place where duplicate components will be
20441 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020442 * TODO: I think normally we should support imports of the
20443 * same namespace from multiple locations. We don't do currently,
20444 * but if we do then according to:
20445 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20446 * we would need, if imported directly, to import redefined
20447 * components as well to be able to catch clashing components.
20448 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020449 */
20450 if (bucket == NULL)
20451 return(-1);
20452 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20453 return(0);
20454 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20455
20456 for (i = 0; i < bucket->globals->nbItems; i++) {
20457 item = bucket->globals->items[i];
20458 table = NULL;
20459 switch (item->type) {
20460 case XML_SCHEMA_TYPE_COMPLEX:
20461 case XML_SCHEMA_TYPE_SIMPLE:
20462 if (WXS_REDEFINED_TYPE(item))
20463 continue;
20464 name = (WXS_TYPE_CAST item)->name;
20465 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20466 break;
20467 case XML_SCHEMA_TYPE_ELEMENT:
20468 name = (WXS_ELEM_CAST item)->name;
20469 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20470 break;
20471 case XML_SCHEMA_TYPE_ATTRIBUTE:
20472 name = (WXS_ATTR_CAST item)->name;
20473 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20474 break;
20475 case XML_SCHEMA_TYPE_GROUP:
20476 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20477 continue;
20478 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20479 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20480 break;
20481 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20482 if (WXS_REDEFINED_ATTR_GROUP(item))
20483 continue;
20484 name = (WXS_ATTR_GROUP_CAST item)->name;
20485 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20486 break;
20487 case XML_SCHEMA_TYPE_IDC_KEY:
20488 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20489 case XML_SCHEMA_TYPE_IDC_KEYREF:
20490 name = (WXS_IDC_CAST item)->name;
20491 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20492 break;
20493 case XML_SCHEMA_TYPE_NOTATION:
20494 name = ((xmlSchemaNotationPtr) item)->name;
20495 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20496 break;
20497 default:
20498 PERROR_INT("xmlSchemaAddComponents",
20499 "Unexpected global component type");
20500 continue;
20501 }
20502 if (*table == NULL) {
20503 *table = xmlHashCreateDict(10, pctxt->dict);
20504 if (*table == NULL) {
20505 PERROR_INT("xmlSchemaAddComponents",
20506 "failed to create a component hash table");
20507 return(-1);
20508 }
20509 }
20510 err = xmlHashAddEntry(*table, name, item);
20511 if (err != 0) {
20512 xmlChar *str = NULL;
20513
20514 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20515 XML_SCHEMAP_REDEFINED_TYPE,
20516 WXS_ITEM_NODE(item),
20517 WXS_BASIC_CAST item,
20518 "A global %s '%s' does already exist",
20519 WXS_ITEM_TYPE_NAME(item),
20520 xmlSchemaGetComponentQName(&str, item));
20521 FREE_AND_NULL(str);
20522 }
20523 }
20524 /*
20525 * Process imported/included schemas.
20526 */
20527 if (bucket->relations != NULL) {
20528 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20529 do {
20530 if ((rel->bucket != NULL) &&
20531 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20532 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20533 return(-1);
20534 }
20535 rel = rel->next;
20536 } while (rel != NULL);
20537 }
20538 return(0);
20539}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020540
20541static int
20542xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20543{
20544 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20545 xmlSchemaTreeItemPtr item, *items;
20546 int nbItems, i;
20547
20548#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20549
20550 if ((con->pending == NULL) ||
20551 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020552 return(0);
20553
20554 /* TODO:
20555 * SPEC (src-redefine):
20556 * (6.2) "If it has no such self-reference, then all of the
20557 * following must be true:"
20558
20559 * (6.2.2) The {model group} of the model group definition which
20560 * corresponds to it per XML Representation of Model Group
20561 * Definition Schema Components (§3.7.2) must be a ·valid
20562 * restriction· of the {model group} of that model group definition
20563 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20564 */
20565 xmlSchemaCheckSRCRedefineFirst(pctxt);
20566
20567 /*
20568 * Add global components to the schemata's hash tables.
20569 */
20570 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020571
20572 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020573 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20574 nbItems = con->pending->nbItems;
20575 /*
20576 * Now that we have parsed *all* the schema document(s) and converted
20577 * them to schema components, we can resolve references, apply component
20578 * constraints, create the FSA from the content model, etc.
20579 */
20580 /*
20581 * Resolve references of..
20582 *
20583 * 1. element declarations:
20584 * - the type definition
20585 * - the substitution group affiliation
20586 * 2. simple/complex types:
20587 * - the base type definition
20588 * - the memberTypes of union types
20589 * - the itemType of list types
20590 * 3. attributes declarations and attribute uses:
20591 * - the type definition
20592 * - if an attribute use, then the attribute declaration
20593 * 4. attribute group references:
20594 * - the attribute group definition
20595 * 5. particles:
20596 * - the term of the particle (e.g. a model group)
20597 * 6. IDC key-references:
20598 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020599 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020600 */
20601 for (i = 0; i < nbItems; i++) {
20602 item = items[i];
20603 switch (item->type) {
20604 case XML_SCHEMA_TYPE_ELEMENT:
20605 xmlSchemaResolveElementReferences(
20606 (xmlSchemaElementPtr) item, pctxt);
20607 FIXHFAILURE;
20608 break;
20609 case XML_SCHEMA_TYPE_COMPLEX:
20610 case XML_SCHEMA_TYPE_SIMPLE:
20611 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020612 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020613 FIXHFAILURE;
20614 break;
20615 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020616 xmlSchemaResolveAttrTypeReferences(
20617 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020618 FIXHFAILURE;
20619 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020620 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20621 xmlSchemaResolveAttrUseReferences(
20622 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020623 FIXHFAILURE;
20624 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020625 case XML_SCHEMA_EXTRA_QNAMEREF:
20626 if ((WXS_QNAME_CAST item)->itemType ==
20627 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20628 {
20629 xmlSchemaResolveAttrGroupReferences(
20630 WXS_QNAME_CAST item, pctxt);
20631 }
20632 FIXHFAILURE;
20633 break;
20634 case XML_SCHEMA_TYPE_SEQUENCE:
20635 case XML_SCHEMA_TYPE_CHOICE:
20636 case XML_SCHEMA_TYPE_ALL:
20637 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20638 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020639 FIXHFAILURE;
20640 break;
20641 case XML_SCHEMA_TYPE_IDC_KEY:
20642 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20643 case XML_SCHEMA_TYPE_IDC_KEYREF:
20644 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020645 (xmlSchemaIDCPtr) item, pctxt);
20646 FIXHFAILURE;
20647 break;
20648 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20649 /*
20650 * Handle attribue prohibition which had a
20651 * "ref" attribute.
20652 */
20653 xmlSchemaResolveAttrUseProhibReferences(
20654 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020655 FIXHFAILURE;
20656 break;
20657 default:
20658 break;
20659 }
20660 }
20661 if (pctxt->nberrors != 0)
20662 goto exit_error;
20663
20664 /*
20665 * Now that all references are resolved we
20666 * can check for circularity of...
20667 * 1. the base axis of type definitions
20668 * 2. nested model group definitions
20669 * 3. nested attribute group definitions
20670 * TODO: check for circual substitution groups.
20671 */
20672 for (i = 0; i < nbItems; i++) {
20673 item = items[i];
20674 /*
20675 * Let's better stop on the first error here.
20676 */
20677 switch (item->type) {
20678 case XML_SCHEMA_TYPE_COMPLEX:
20679 case XML_SCHEMA_TYPE_SIMPLE:
20680 xmlSchemaCheckTypeDefCircular(
20681 (xmlSchemaTypePtr) item, pctxt);
20682 FIXHFAILURE;
20683 if (pctxt->nberrors != 0)
20684 goto exit_error;
20685 break;
20686 case XML_SCHEMA_TYPE_GROUP:
20687 xmlSchemaCheckGroupDefCircular(
20688 (xmlSchemaModelGroupDefPtr) item, pctxt);
20689 FIXHFAILURE;
20690 if (pctxt->nberrors != 0)
20691 goto exit_error;
20692 break;
20693 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20694 xmlSchemaCheckAttrGroupCircular(
20695 (xmlSchemaAttributeGroupPtr) item, pctxt);
20696 FIXHFAILURE;
20697 if (pctxt->nberrors != 0)
20698 goto exit_error;
20699 break;
20700 default:
20701 break;
20702 }
20703 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020704 if (pctxt->nberrors != 0)
20705 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020706 /*
20707 * Model group definition references:
20708 * Such a reference is reflected by a particle at the component
20709 * level. Until now the 'term' of such particles pointed
20710 * to the model group definition; this was done, in order to
20711 * ease circularity checks. Now we need to set the 'term' of
20712 * such particles to the model group of the model group definition.
20713 */
20714 for (i = 0; i < nbItems; i++) {
20715 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020716 switch (item->type) {
20717 case XML_SCHEMA_TYPE_SEQUENCE:
20718 case XML_SCHEMA_TYPE_CHOICE:
20719 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20720 WXS_MODEL_GROUP_CAST item);
20721 break;
20722 default:
20723 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020724 }
20725 }
20726 if (pctxt->nberrors != 0)
20727 goto exit_error;
20728 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020729 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020730 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020731 for (i = 0; i < nbItems; i++) {
20732 item = items[i];
20733 switch (item->type) {
20734 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20735 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20736 WXS_ATTR_GROUP_HAS_REFS(item))
20737 {
20738 xmlSchemaAttributeGroupExpandRefs(pctxt,
20739 WXS_ATTR_GROUP_CAST item);
20740 FIXHFAILURE;
20741 }
20742 break;
20743 default:
20744 break;
20745 }
20746 }
20747 if (pctxt->nberrors != 0)
20748 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020749 /*
20750 * First compute the variety of simple types. This is needed as
20751 * a seperate step, since otherwise we won't be able to detect
20752 * circular union types in all cases.
20753 */
20754 for (i = 0; i < nbItems; i++) {
20755 item = items[i];
20756 switch (item->type) {
20757 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020758 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020759 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20760 (xmlSchemaTypePtr) item);
20761 FIXHFAILURE;
20762 }
20763 break;
20764 default:
20765 break;
20766 }
20767 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020768 if (pctxt->nberrors != 0)
20769 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020770 /*
20771 * Detect circular union types. Note that this needs the variety to
20772 * be already computed.
20773 */
20774 for (i = 0; i < nbItems; i++) {
20775 item = items[i];
20776 switch (item->type) {
20777 case XML_SCHEMA_TYPE_SIMPLE:
20778 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20779 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20780 (xmlSchemaTypePtr) item);
20781 FIXHFAILURE;
20782 }
20783 break;
20784 default:
20785 break;
20786 }
20787 }
20788 if (pctxt->nberrors != 0)
20789 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020790
20791 /*
20792 * Do the complete type fixup for simple types.
20793 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020794 for (i = 0; i < nbItems; i++) {
20795 item = items[i];
20796 switch (item->type) {
20797 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020798 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20799 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20800 FIXHFAILURE;
20801 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020802 break;
20803 default:
20804 break;
20805 }
20806 }
20807 if (pctxt->nberrors != 0)
20808 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020809 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020810 * At this point we need all simple types to be builded and checked.
20811 */
20812 /*
20813 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020814 */
20815 for (i = 0; i < nbItems; i++) {
20816 item = items[i];
20817 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020818 case XML_SCHEMA_TYPE_ATTRIBUTE:
20819 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20820 FIXHFAILURE;
20821 break;
20822 default:
20823 break;
20824 }
20825 }
20826 if (pctxt->nberrors != 0)
20827 goto exit_error;
20828 /*
20829 * Apply constraints for attribute uses.
20830 */
20831 for (i = 0; i < nbItems; i++) {
20832 item = items[i];
20833 switch (item->type) {
20834 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20835 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20836 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20837 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020838 FIXHFAILURE;
20839 }
20840 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020841 default:
20842 break;
20843 }
20844 }
20845 if (pctxt->nberrors != 0)
20846 goto exit_error;
20847
20848 /*
20849 * Apply constraints for attribute group definitions.
20850 */
20851 for (i = 0; i < nbItems; i++) {
20852 item = items[i];
20853 switch (item->type) {
20854 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20855 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20856 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20857 {
20858 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20859 FIXHFAILURE;
20860 }
20861 break;
20862 default:
20863 break;
20864 }
20865 }
20866 if (pctxt->nberrors != 0)
20867 goto exit_error;
20868
20869 /*
20870 * Apply constraints for redefinitions.
20871 */
20872 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20873 xmlSchemaCheckSRCRedefineSecond(pctxt);
20874 if (pctxt->nberrors != 0)
20875 goto exit_error;
20876
20877 /*
20878 * Fixup complex types.
20879 */
20880 for (i = 0; i < nbItems; i++) {
20881 item = con->pending->items[i];
20882 switch (item->type) {
20883 case XML_SCHEMA_TYPE_COMPLEX:
20884 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20885 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20886 FIXHFAILURE;
20887 }
20888 break;
20889 default:
20890 break;
20891 }
20892 }
20893 if (pctxt->nberrors != 0)
20894 goto exit_error;
20895
20896 /*
20897 * The list could have changed, since xmlSchemaFixupComplexType()
20898 * will create particles and model groups in some cases.
20899 */
20900 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20901 nbItems = con->pending->nbItems;
20902
20903 /*
20904 * At this point all complex types need to be builded and checked.
20905 */
20906 /*
20907 * Apply some constraints for element declarations.
20908 */
20909 for (i = 0; i < nbItems; i++) {
20910 item = items[i];
20911 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020912 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020913
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020914 if ((((xmlSchemaElementPtr) item)->flags &
20915 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20916 xmlSchemaCheckElementDeclComponent(
20917 (xmlSchemaElementPtr) item, pctxt);
20918 FIXHFAILURE;
20919 }
20920 break;
20921 default:
20922 break;
20923 }
20924 }
20925 if (pctxt->nberrors != 0)
20926 goto exit_error;
20927 /*
20928 * Finally we can build the automaton from the content model of
20929 * complex types.
20930 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020931
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020932 for (i = 0; i < nbItems; i++) {
20933 item = items[i];
20934 switch (item->type) {
20935 case XML_SCHEMA_TYPE_COMPLEX:
20936 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020937 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020938 break;
20939 default:
20940 break;
20941 }
20942 }
20943 if (pctxt->nberrors != 0)
20944 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020945 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020946 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020947 */
20948 con->pending->nbItems = 0;
20949 return(0);
20950exit_error:
20951 con->pending->nbItems = 0;
20952 return(pctxt->err);
20953exit_failure:
20954 con->pending->nbItems = 0;
20955 return(-1);
20956}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020957/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020958 * xmlSchemaParse:
20959 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020960 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020961 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020962 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020963 *
20964 * Returns the internal XML Schema structure built from the resource or
20965 * NULL in case of error
20966 */
20967xmlSchemaPtr
20968xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20969{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020970 xmlSchemaPtr schema = NULL;
20971 xmlSchemaBucketPtr bucket = NULL;
20972 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020973
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020974 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020975 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020976 * the API; i.e. not automatically by the validated instance document.
20977 */
20978
Daniel Veillard4255d502002-04-16 15:50:10 +000020979 xmlSchemaInitTypes();
20980
Daniel Veillard6045c902002-10-09 21:13:59 +000020981 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020982 return (NULL);
20983
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020984 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020985 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020986 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020987 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020988
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020989 /* Create the *main* schema. */
20990 schema = xmlSchemaNewSchema(ctxt);
20991 if (schema == NULL)
20992 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020993 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020994 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020995 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020996 if (ctxt->constructor == NULL) {
20997 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
20998 if (ctxt->constructor == NULL)
20999 return(NULL);
21000 /* Take ownership of the constructor to be able to free it. */
21001 ctxt->ownsConstructor = 1;
21002 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021003 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021004 /*
21005 * Locate and add the schema document.
21006 */
21007 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21008 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21009 NULL, NULL, &bucket);
21010 if (res == -1)
21011 goto exit_failure;
21012 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021013 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021014
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021015 if (bucket == NULL) {
21016 /* TODO: Error code, actually we failed to *locate* the schema. */
21017 if (ctxt->URL)
21018 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21019 NULL, NULL,
21020 "Failed to locate the main schema resource at '%s'",
21021 ctxt->URL, NULL);
21022 else
21023 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21024 NULL, NULL,
21025 "Failed to locate the main schema resource",
21026 NULL, NULL);
21027 goto exit;
21028 }
21029 /* Set the main schema bucket. */
21030 ctxt->constructor->bucket = bucket;
21031 ctxt->targetNamespace = bucket->targetNamespace;
21032 schema->targetNamespace = bucket->targetNamespace;
21033
21034 /* Then do the parsing for good. */
21035 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21036 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021037 if (ctxt->nberrors != 0)
21038 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021039
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021040 schema->doc = bucket->doc;
21041 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021042
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021043 ctxt->schema = schema;
21044
21045 if (xmlSchemaFixupComponents(ctxt) == -1)
21046 goto exit_failure;
21047
21048 /*
21049 * TODO: This is not nice, since we cannot distinguish from the
21050 * result if there was an internal error or not.
21051 */
21052exit:
21053 if (ctxt->nberrors != 0) {
21054 if (schema) {
21055 xmlSchemaFree(schema);
21056 schema = NULL;
21057 }
21058 if (ctxt->constructor) {
21059 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21060 ctxt->constructor = NULL;
21061 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021063 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021064 ctxt->schema = NULL;
21065 return(schema);
21066exit_failure:
21067 /*
21068 * Quite verbose, but should catch internal errors, which were
21069 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021070 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021071 if (schema) {
21072 xmlSchemaFree(schema);
21073 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021074 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021075 if (ctxt->constructor) {
21076 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21077 ctxt->constructor = NULL;
21078 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021079 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021080 PERROR_INT2("xmlSchemaParse",
21081 "An internal error occured");
21082 ctxt->schema = NULL;
21083 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021084}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021085
Daniel Veillard4255d502002-04-16 15:50:10 +000021086/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021087 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021088 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021089 * @err: the error callback
21090 * @warn: the warning callback
21091 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021092 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021093 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021094 */
21095void
21096xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021097 xmlSchemaValidityErrorFunc err,
21098 xmlSchemaValidityWarningFunc warn, void *ctx)
21099{
Daniel Veillard4255d502002-04-16 15:50:10 +000021100 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021101 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021102 ctxt->error = err;
21103 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021104 ctxt->errCtxt = ctx;
21105 if (ctxt->vctxt != NULL)
21106 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21107}
21108
21109/**
21110 * xmlSchemaSetParserStructuredErrors:
21111 * @ctxt: a schema parser context
21112 * @serror: the structured error function
21113 * @ctx: the functions context
21114 *
21115 * Set the structured error callback
21116 */
21117void
21118xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21119 xmlStructuredErrorFunc serror,
21120 void *ctx)
21121{
21122 if (ctxt == NULL)
21123 return;
21124 ctxt->serror = serror;
21125 ctxt->errCtxt = ctx;
21126 if (ctxt->vctxt != NULL)
21127 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021128}
21129
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021130/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021131 * xmlSchemaGetParserErrors:
21132 * @ctxt: a XMl-Schema parser context
21133 * @err: the error callback result
21134 * @warn: the warning callback result
21135 * @ctx: contextual data for the callbacks result
21136 *
21137 * Get the callback information used to handle errors for a parser context
21138 *
21139 * Returns -1 in case of failure, 0 otherwise
21140 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021141int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021142xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021143 xmlSchemaValidityErrorFunc * err,
21144 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021145{
21146 if (ctxt == NULL)
21147 return(-1);
21148 if (err != NULL)
21149 *err = ctxt->error;
21150 if (warn != NULL)
21151 *warn = ctxt->warning;
21152 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021153 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021154 return(0);
21155}
21156
21157/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021158 * xmlSchemaFacetTypeToString:
21159 * @type: the facet type
21160 *
21161 * Convert the xmlSchemaTypeType to a char string.
21162 *
21163 * Returns the char string representation of the facet type if the
21164 * type is a facet and an "Internal Error" string otherwise.
21165 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021166static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021167xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21168{
21169 switch (type) {
21170 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021171 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021172 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021173 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021174 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021175 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021176 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021177 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021178 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021179 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021180 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021181 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021182 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021183 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021184 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021185 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021186 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021187 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021188 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021189 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021190 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021191 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021192 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021193 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021194 default:
21195 break;
21196 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021197 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021198}
21199
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021200static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021201xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21202{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021203 /*
21204 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021205 * from xsd:string.
21206 */
21207 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021208 /*
21209 * Note that we assume a whitespace of preserve for anySimpleType.
21210 */
21211 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21212 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21213 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021214 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021215 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021216 else {
21217 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021218 * For all ·atomic· datatypes other than string (and types ·derived·
21219 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021220 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021221 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021222 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021223 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021224 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021225 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021226 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021227 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021228 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021229 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021230 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021231 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021232 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021233 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21234 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21235 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21236 return (XML_SCHEMA_WHITESPACE_REPLACE);
21237 else
21238 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021239 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021240 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021241}
21242
Daniel Veillard4255d502002-04-16 15:50:10 +000021243/************************************************************************
21244 * *
21245 * Simple type validation *
21246 * *
21247 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021248
Daniel Veillard4255d502002-04-16 15:50:10 +000021249
21250/************************************************************************
21251 * *
21252 * DOM Validation code *
21253 * *
21254 ************************************************************************/
21255
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021256/**
21257 * xmlSchemaAssembleByLocation:
21258 * @pctxt: a schema parser context
21259 * @vctxt: a schema validation context
21260 * @schema: the existing schema
21261 * @node: the node that fired the assembling
21262 * @nsName: the namespace name of the new schema
21263 * @location: the location of the schema
21264 *
21265 * Expands an existing schema by an additional schema.
21266 *
21267 * Returns 0 if the new schema is correct, a positive error code
21268 * number otherwise and -1 in case of an internal or API error.
21269 */
21270static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021271xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021272 xmlSchemaPtr schema,
21273 xmlNodePtr node,
21274 const xmlChar *nsName,
21275 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021276{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021277 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021278 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021279 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021280
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021281 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021282 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021283
21284 if (vctxt->pctxt == NULL) {
21285 VERROR_INT("xmlSchemaAssembleByLocation",
21286 "no parser context available");
21287 return(-1);
21288 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021289 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021290 if (pctxt->constructor == NULL) {
21291 PERROR_INT("xmlSchemaAssembleByLocation",
21292 "no constructor");
21293 return(-1);
21294 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021295 /*
21296 * Acquire the schema document.
21297 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021298 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21299 location, node);
21300 /*
21301 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21302 * the process will automatically change this to
21303 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21304 */
21305 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21306 location, NULL, NULL, 0, node, NULL, nsName,
21307 &bucket);
21308 if (ret != 0)
21309 return(ret);
21310 if (bucket == NULL) {
21311 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021312 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021313 return(-1);
21314 }
21315 /*
21316 * The first located schema will be handled as if all other
21317 * schemas imported by XSI were imported by this first schema.
21318 */
21319 if ((bucket != NULL) &&
21320 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21321 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21322 /*
21323 * TODO: Is this handled like an import? I.e. is it not an error
21324 * if the schema cannot be located?
21325 */
21326 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21327 return(0);
21328 /*
21329 * We will reuse the parser context for every schema imported
21330 * directly via XSI. So reset the context.
21331 */
21332 pctxt->nberrors = 0;
21333 pctxt->err = 0;
21334 pctxt->doc = bucket->doc;
21335
21336 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21337 if (ret == -1) {
21338 pctxt->doc = NULL;
21339 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021340 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021341 /* Paranoid error channelling. */
21342 if ((ret == 0) && (pctxt->nberrors != 0))
21343 ret = pctxt->err;
21344 if (pctxt->nberrors == 0) {
21345 /*
21346 * Only bother to fixup pending components, if there was
21347 * no error yet.
21348 */
21349 xmlSchemaFixupComponents(pctxt);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021350 ret = pctxt->err;
21351 /*
21352 * Not nice, but we need somehow to channel the schema parser
21353 * error to the validation context.
21354 */
21355 if ((ret != 0) && (vctxt->err == 0))
21356 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021357 vctxt->nberrors += pctxt->nberrors;
21358 } else {
21359 /* Add to validation error sum. */
21360 vctxt->nberrors += pctxt->nberrors;
21361 }
21362 pctxt->doc = NULL;
21363 return(ret);
21364exit_failure:
21365 pctxt->doc = NULL;
21366 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021367}
21368
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021369static xmlSchemaAttrInfoPtr
21370xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21371 int metaType)
21372{
21373 if (vctxt->nbAttrInfos == 0)
21374 return (NULL);
21375 {
21376 int i;
21377 xmlSchemaAttrInfoPtr iattr;
21378
21379 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21380 iattr = vctxt->attrInfos[i];
21381 if (iattr->metaType == metaType)
21382 return (iattr);
21383 }
21384
21385 }
21386 return (NULL);
21387}
21388
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021389/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021390 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021391 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021392 *
21393 * Expands an existing schema by an additional schema using
21394 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21395 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21396 * must be set to 1.
21397 *
21398 * Returns 0 if the new schema is correct, a positive error code
21399 * number otherwise and -1 in case of an internal or API error.
21400 */
21401static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021402xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021403{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021404 const xmlChar *cur, *end;
21405 const xmlChar *nsname = NULL, *location;
21406 int count = 0;
21407 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021408 xmlSchemaAttrInfoPtr iattr;
21409
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021410 /*
21411 * Parse the value; we will assume an even number of values
21412 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021413 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021414 * URGENT TODO: !! This needs to work for both
21415 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21416 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021417 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021418 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21419 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21420 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021421 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021422 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21423 if (iattr == NULL)
21424 return (0);
21425 cur = iattr->value;
21426 do {
21427 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021428 /*
21429 * Get the namespace name.
21430 */
21431 while (IS_BLANK_CH(*cur))
21432 cur++;
21433 end = cur;
21434 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21435 end++;
21436 if (end == cur)
21437 break;
21438 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021439 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021440 cur = end;
21441 }
21442 /*
21443 * Get the URI.
21444 */
21445 while (IS_BLANK_CH(*cur))
21446 cur++;
21447 end = cur;
21448 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21449 end++;
21450 if (end == cur)
21451 break;
21452 count++;
21453 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021454 cur = end;
21455 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21456 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021457 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021458 VERROR_INT("xmlSchemaAssembleByXSI",
21459 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021460 return (-1);
21461 }
21462 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021463 return (ret);
21464}
21465
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021466static const xmlChar *
21467xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21468 const xmlChar *prefix)
21469{
21470 if (vctxt->sax != NULL) {
21471 int i, j;
21472 xmlSchemaNodeInfoPtr inode;
21473
21474 for (i = vctxt->depth; i >= 0; i--) {
21475 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21476 inode = vctxt->elemInfos[i];
21477 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21478 if (((prefix == NULL) &&
21479 (inode->nsBindings[j] == NULL)) ||
21480 ((prefix != NULL) && xmlStrEqual(prefix,
21481 inode->nsBindings[j]))) {
21482
21483 /*
21484 * Note that the namespace bindings are already
21485 * in a string dict.
21486 */
21487 return (inode->nsBindings[j+1]);
21488 }
21489 }
21490 }
21491 }
21492 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021493#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021494 } else if (vctxt->reader != NULL) {
21495 xmlChar *nsName;
21496
21497 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21498 if (nsName != NULL) {
21499 const xmlChar *ret;
21500
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021501 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21502 xmlFree(nsName);
21503 return (ret);
21504 } else
21505 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021506#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021507 } else {
21508 xmlNsPtr ns;
21509
21510 if ((vctxt->inode->node == NULL) ||
21511 (vctxt->inode->node->doc == NULL)) {
21512 VERROR_INT("xmlSchemaLookupNamespace",
21513 "no node or node's doc avaliable");
21514 return (NULL);
21515 }
21516 ns = xmlSearchNs(vctxt->inode->node->doc,
21517 vctxt->inode->node, prefix);
21518 if (ns != NULL)
21519 return (ns->href);
21520 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021521 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021522}
21523
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021524/*
21525* This one works on the schema of the validation context.
21526*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021527static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021528xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21529 xmlSchemaPtr schema,
21530 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021531 const xmlChar *value,
21532 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021533 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021534{
21535 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021536
21537 if (vctxt && (vctxt->schema == NULL)) {
21538 VERROR_INT("xmlSchemaValidateNotation",
21539 "a schema is needed on the validation context");
21540 return (-1);
21541 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021542 ret = xmlValidateQName(value, 1);
21543 if (ret != 0)
21544 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021545 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021546 xmlChar *localName = NULL;
21547 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021549 localName = xmlSplitQName2(value, &prefix);
21550 if (prefix != NULL) {
21551 const xmlChar *nsName = NULL;
21552
21553 if (vctxt != NULL)
21554 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21555 else if (node != NULL) {
21556 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21557 if (ns != NULL)
21558 nsName = ns->href;
21559 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021560 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021561 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021562 return (1);
21563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021564 if (nsName == NULL) {
21565 xmlFree(prefix);
21566 xmlFree(localName);
21567 return (1);
21568 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021569 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021570 if (valNeeded && (val != NULL)) {
21571 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21572 BAD_CAST xmlStrdup(nsName));
21573 if (*val == NULL)
21574 ret = -1;
21575 }
21576 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021577 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021578 xmlFree(prefix);
21579 xmlFree(localName);
21580 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021581 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021582 if (valNeeded && (val != NULL)) {
21583 (*val) = xmlSchemaNewNOTATIONValue(
21584 BAD_CAST xmlStrdup(value), NULL);
21585 if (*val == NULL)
21586 ret = -1;
21587 }
21588 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021589 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021590 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021592 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021593}
21594
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021595static int
21596xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21597 const xmlChar* lname,
21598 const xmlChar* nsname)
21599{
21600 int i;
21601
21602 lname = xmlDictLookup(vctxt->dict, lname, -1);
21603 if (lname == NULL)
21604 return(-1);
21605 if (nsname != NULL) {
21606 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21607 if (nsname == NULL)
21608 return(-1);
21609 }
21610 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21611 if ((vctxt->nodeQNames->items [i] == lname) &&
21612 (vctxt->nodeQNames->items[i +1] == nsname))
21613 /* Already there */
21614 return(i);
21615 }
21616 /* Add new entry. */
21617 i = vctxt->nodeQNames->nbItems;
21618 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21619 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21620 return(i);
21621}
21622
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021623/************************************************************************
21624 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021625 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021626 * *
21627 ************************************************************************/
21628
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021629/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021630 * xmlSchemaAugmentIDC:
21631 * @idcDef: the IDC definition
21632 *
21633 * Creates an augmented IDC definition item.
21634 *
21635 * Returns the item, or NULL on internal errors.
21636 */
21637static void
21638xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21639 xmlSchemaValidCtxtPtr vctxt)
21640{
21641 xmlSchemaIDCAugPtr aidc;
21642
21643 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21644 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021645 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021646 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21647 NULL);
21648 return;
21649 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021650 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021651 aidc->def = idcDef;
21652 aidc->next = NULL;
21653 if (vctxt->aidcs == NULL)
21654 vctxt->aidcs = aidc;
21655 else {
21656 aidc->next = vctxt->aidcs;
21657 vctxt->aidcs = aidc;
21658 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021659 /*
21660 * Save if we have keyrefs at all.
21661 */
21662 if ((vctxt->hasKeyrefs == 0) &&
21663 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21664 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021665}
21666
21667/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021668 * xmlSchemaIDCNewBinding:
21669 * @idcDef: the IDC definition of this binding
21670 *
21671 * Creates a new IDC binding.
21672 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021673 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021674 */
21675static xmlSchemaPSVIIDCBindingPtr
21676xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21677{
21678 xmlSchemaPSVIIDCBindingPtr ret;
21679
21680 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21681 sizeof(xmlSchemaPSVIIDCBinding));
21682 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021683 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021684 "allocating a PSVI IDC binding item", NULL);
21685 return (NULL);
21686 }
21687 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21688 ret->definition = idcDef;
21689 return (ret);
21690}
21691
21692/**
21693 * xmlSchemaIDCStoreNodeTableItem:
21694 * @vctxt: the WXS validation context
21695 * @item: the IDC node table item
21696 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021697 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021698 * They are stored to avoid copying them if IDC node-tables are merged
21699 * with corresponding parent IDC node-tables (bubbling).
21700 *
21701 * Returns 0 if succeeded, -1 on internal errors.
21702 */
21703static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021704xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021705 xmlSchemaPSVIIDCNodePtr item)
21706{
21707 /*
21708 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021709 */
21710 if (vctxt->idcNodes == NULL) {
21711 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021712 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21713 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021714 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021715 "allocating the IDC node table item list", NULL);
21716 return (-1);
21717 }
21718 vctxt->sizeIdcNodes = 20;
21719 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21720 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021721 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21722 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021723 sizeof(xmlSchemaPSVIIDCNodePtr));
21724 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021725 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021726 "re-allocating the IDC node table item list", NULL);
21727 return (-1);
21728 }
21729 }
21730 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021731
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021732 return (0);
21733}
21734
21735/**
21736 * xmlSchemaIDCStoreKey:
21737 * @vctxt: the WXS validation context
21738 * @item: the IDC key
21739 *
21740 * The validation context is used to store an IDC key.
21741 *
21742 * Returns 0 if succeeded, -1 on internal errors.
21743 */
21744static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021745xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021746 xmlSchemaPSVIIDCKeyPtr key)
21747{
21748 /*
21749 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021750 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021751 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021752 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021753 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21754 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021755 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021756 "allocating the IDC key storage list", NULL);
21757 return (-1);
21758 }
21759 vctxt->sizeIdcKeys = 40;
21760 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21761 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021762 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21763 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021764 sizeof(xmlSchemaPSVIIDCKeyPtr));
21765 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021766 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021767 "re-allocating the IDC key storage list", NULL);
21768 return (-1);
21769 }
21770 }
21771 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021772
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021773 return (0);
21774}
21775
21776/**
21777 * xmlSchemaIDCAppendNodeTableItem:
21778 * @bind: the IDC binding
21779 * @ntItem: the node-table item
21780 *
21781 * Appends the IDC node-table item to the binding.
21782 *
21783 * Returns 0 on success and -1 on internal errors.
21784 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021785static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021786xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21787 xmlSchemaPSVIIDCNodePtr ntItem)
21788{
21789 if (bind->nodeTable == NULL) {
21790 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021791 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021792 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21793 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021794 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021795 "allocating an array of IDC node-table items", NULL);
21796 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021797 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021798 } else if (bind->sizeNodes <= bind->nbNodes) {
21799 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021800 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21801 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021802 sizeof(xmlSchemaPSVIIDCNodePtr));
21803 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021804 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021805 "re-allocating an array of IDC node-table items", NULL);
21806 return(-1);
21807 }
21808 }
21809 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021810 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021811}
21812
21813/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021814 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021815 * @vctxt: the WXS validation context
21816 * @matcher: the IDC matcher
21817 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021818 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021819 * of the given matcher. If none found, a new one is created
21820 * and added to the IDC table.
21821 *
21822 * Returns an IDC binding or NULL on internal errors.
21823 */
21824static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021825xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021826 xmlSchemaIDCMatcherPtr matcher)
21827{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021828 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021829
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021830 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021831
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021832 if (ielem->idcTable == NULL) {
21833 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21834 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021835 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021836 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021837 } else {
21838 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021839
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021840 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021841 do {
21842 if (bind->definition == matcher->aidc->def)
21843 return(bind);
21844 if (bind->next == NULL) {
21845 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21846 if (bind->next == NULL)
21847 return (NULL);
21848 return(bind->next);
21849 }
21850 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021851 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021852 }
21853 return (NULL);
21854}
21855
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021856static xmlSchemaItemListPtr
21857xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21858 xmlSchemaIDCMatcherPtr matcher)
21859{
21860 if (matcher->targets == NULL)
21861 matcher->targets = xmlSchemaItemListCreate();
21862 return(matcher->targets);
21863}
21864
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021865/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021866 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021867 * @key: the IDC key
21868 *
21869 * Frees an IDC key together with its compiled value.
21870 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021871static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021872xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21873{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021874 if (key->val != NULL)
21875 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021876 xmlFree(key);
21877}
21878
21879/**
21880 * xmlSchemaIDCFreeBinding:
21881 *
21882 * Frees an IDC binding. Note that the node table-items
21883 * are not freed.
21884 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021885static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021886xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21887{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021888 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021889 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021890 if (bind->dupls != NULL)
21891 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021892 xmlFree(bind);
21893}
21894
21895/**
21896 * xmlSchemaIDCFreeIDCTable:
21897 * @bind: the first IDC binding in the list
21898 *
21899 * Frees an IDC table, i.e. all the IDC bindings in the list.
21900 */
21901static void
21902xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21903{
21904 xmlSchemaPSVIIDCBindingPtr prev;
21905
21906 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021907 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021908 bind = bind->next;
21909 xmlSchemaIDCFreeBinding(prev);
21910 }
21911}
21912
21913/**
21914 * xmlSchemaIDCFreeMatcherList:
21915 * @matcher: the first IDC matcher in the list
21916 *
21917 * Frees a list of IDC matchers.
21918 */
21919static void
21920xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21921{
21922 xmlSchemaIDCMatcherPtr next;
21923
21924 while (matcher != NULL) {
21925 next = matcher->next;
21926 if (matcher->keySeqs != NULL) {
21927 int i;
21928 for (i = 0; i < matcher->sizeKeySeqs; i++)
21929 if (matcher->keySeqs[i] != NULL)
21930 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021931 xmlFree(matcher->keySeqs);
21932 }
21933 if (matcher->targets != NULL) {
21934 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21935 int i;
21936 xmlSchemaPSVIIDCNodePtr idcNode;
21937 /*
21938 * Node-table items for keyrefs are not stored globally
21939 * to the validation context, since they are not bubbled.
21940 * We need to free them here.
21941 */
21942 for (i = 0; i < matcher->targets->nbItems; i++) {
21943 idcNode =
21944 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21945 xmlFree(idcNode->keys);
21946 xmlFree(idcNode);
21947 }
21948 }
21949 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021950 }
21951 xmlFree(matcher);
21952 matcher = next;
21953 }
21954}
21955
21956/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021957 * xmlSchemaIDCAddStateObject:
21958 * @vctxt: the WXS validation context
21959 * @matcher: the IDC matcher
21960 * @sel: the XPath information
21961 * @parent: the parent "selector" state object if any
21962 * @type: "selector" or "field"
21963 *
21964 * Creates/reuses and activates state objects for the given
21965 * XPath information; if the XPath expression consists of unions,
21966 * multiple state objects are created for every unioned expression.
21967 *
21968 * Returns 0 on success and -1 on internal errors.
21969 */
21970static int
21971xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21972 xmlSchemaIDCMatcherPtr matcher,
21973 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021974 int type)
21975{
21976 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021977
21978 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021979 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021980 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021981 if (vctxt->xpathStatePool != NULL) {
21982 sto = vctxt->xpathStatePool;
21983 vctxt->xpathStatePool = sto->next;
21984 sto->next = NULL;
21985 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021986 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021987 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021988 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021989 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21990 if (sto == NULL) {
21991 xmlSchemaVErrMemory(NULL,
21992 "allocating an IDC state object", NULL);
21993 return (-1);
21994 }
21995 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21996 }
21997 /*
21998 * Add to global list.
21999 */
22000 if (vctxt->xpathStates != NULL)
22001 sto->next = vctxt->xpathStates;
22002 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022003
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022004 /*
22005 * Free the old xpath validation context.
22006 */
22007 if (sto->xpathCtxt != NULL)
22008 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22009
22010 /*
22011 * Create a new XPath (pattern) validation context.
22012 */
22013 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22014 (xmlPatternPtr) sel->xpathComp);
22015 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022016 VERROR_INT("xmlSchemaIDCAddStateObject",
22017 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022018 return (-1);
22019 }
22020 sto->type = type;
22021 sto->depth = vctxt->depth;
22022 sto->matcher = matcher;
22023 sto->sel = sel;
22024 sto->nbHistory = 0;
22025
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022026#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022027 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22028 sto->sel->xpath);
22029#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022030 return (0);
22031}
22032
22033/**
22034 * xmlSchemaXPathEvaluate:
22035 * @vctxt: the WXS validation context
22036 * @nodeType: the nodeType of the current node
22037 *
22038 * Evaluates all active XPath state objects.
22039 *
22040 * Returns the number of IC "field" state objects which resolved to
22041 * this node, 0 if none resolved and -1 on internal errors.
22042 */
22043static int
22044xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022045 xmlElementType nodeType)
22046{
22047 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022048 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022049
22050 if (vctxt->xpathStates == NULL)
22051 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022052
22053 if (nodeType == XML_ATTRIBUTE_NODE)
22054 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022055#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022056 {
22057 xmlChar *str = NULL;
22058 xmlGenericError(xmlGenericErrorContext,
22059 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022060 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22061 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022062 FREE_AND_NULL(str)
22063 }
22064#endif
22065 /*
22066 * Process all active XPath state objects.
22067 */
22068 first = vctxt->xpathStates;
22069 sto = first;
22070 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022071#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022072 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022073 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22074 sto->matcher->aidc->def->name, sto->sel->xpath);
22075 else
22076 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22077 sto->matcher->aidc->def->name, sto->sel->xpath);
22078#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022079 if (nodeType == XML_ELEMENT_NODE)
22080 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022081 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022082 else
22083 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022084 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022085
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022086 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022087 VERROR_INT("xmlSchemaXPathEvaluate",
22088 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022089 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022090 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022091 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022092 goto next_sto;
22093 /*
22094 * Full match.
22095 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022096#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022097 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022098 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022099#endif
22100 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022101 * Register a match in the state object history.
22102 */
22103 if (sto->history == NULL) {
22104 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22105 if (sto->history == NULL) {
22106 xmlSchemaVErrMemory(NULL,
22107 "allocating the state object history", NULL);
22108 return(-1);
22109 }
22110 sto->sizeHistory = 10;
22111 } else if (sto->sizeHistory <= sto->nbHistory) {
22112 sto->sizeHistory *= 2;
22113 sto->history = (int *) xmlRealloc(sto->history,
22114 sto->sizeHistory * sizeof(int));
22115 if (sto->history == NULL) {
22116 xmlSchemaVErrMemory(NULL,
22117 "re-allocating the state object history", NULL);
22118 return(-1);
22119 }
22120 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022121 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022122
22123#ifdef DEBUG_IDC
22124 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22125 vctxt->depth);
22126#endif
22127
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022128 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22129 xmlSchemaIDCSelectPtr sel;
22130 /*
22131 * Activate state objects for the IDC fields of
22132 * the IDC selector.
22133 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022134#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022135 xmlGenericError(xmlGenericErrorContext, "IDC: "
22136 "activating field states\n");
22137#endif
22138 sel = sto->matcher->aidc->def->fields;
22139 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022140 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22141 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22142 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022143 sel = sel->next;
22144 }
22145 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22146 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022147 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022148 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022149#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022150 xmlGenericError(xmlGenericErrorContext,
22151 "IDC: key found\n");
22152#endif
22153 /*
22154 * Notify that the character value of this node is
22155 * needed.
22156 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022157 if (resolved == 0) {
22158 if ((vctxt->inode->flags &
22159 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22160 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22161 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022162 resolved++;
22163 }
22164next_sto:
22165 if (sto->next == NULL) {
22166 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022167 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022168 */
22169 head = first;
22170 sto = vctxt->xpathStates;
22171 } else
22172 sto = sto->next;
22173 }
22174 return (resolved);
22175}
22176
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022177static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022178xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022179 xmlChar **buf,
22180 xmlSchemaPSVIIDCKeyPtr *seq,
22181 int count)
22182{
22183 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022184 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022185
22186 *buf = xmlStrdup(BAD_CAST "[");
22187 for (i = 0; i < count; i++) {
22188 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022189 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22190 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22191 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022192 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022193 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022194 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022195 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22196 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022197 *buf = xmlStrcat(*buf, BAD_CAST "???");
22198 }
22199 if (i < count -1)
22200 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22201 else
22202 *buf = xmlStrcat(*buf, BAD_CAST "'");
22203 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022204 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022205 value = NULL;
22206 }
22207 }
22208 *buf = xmlStrcat(*buf, BAD_CAST "]");
22209
22210 return (BAD_CAST *buf);
22211}
22212
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022213/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022214 * xmlSchemaXPathPop:
22215 * @vctxt: the WXS validation context
22216 *
22217 * Pops all XPath states.
22218 *
22219 * Returns 0 on success and -1 on internal errors.
22220 */
22221static int
22222xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22223{
22224 xmlSchemaIDCStateObjPtr sto;
22225 int res;
22226
22227 if (vctxt->xpathStates == NULL)
22228 return(0);
22229 sto = vctxt->xpathStates;
22230 do {
22231 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22232 if (res == -1)
22233 return (-1);
22234 sto = sto->next;
22235 } while (sto != NULL);
22236 return(0);
22237}
22238
22239/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022240 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022241 * @vctxt: the WXS validation context
22242 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022243 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022244 *
22245 * Processes and pops the history items of the IDC state objects.
22246 * IDC key-sequences are validated/created on IDC bindings.
22247 *
22248 * Returns 0 on success and -1 on internal errors.
22249 */
22250static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022251xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022252 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022253{
22254 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022255 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022256 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022257 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022258
22259 if (vctxt->xpathStates == NULL)
22260 return (0);
22261 sto = vctxt->xpathStates;
22262
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022263#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022264 {
22265 xmlChar *str = NULL;
22266 xmlGenericError(xmlGenericErrorContext,
22267 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022268 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22269 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022270 FREE_AND_NULL(str)
22271 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022272#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022273 /*
22274 * Evaluate the state objects.
22275 */
22276 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022277 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22278 if (res == -1) {
22279 VERROR_INT("xmlSchemaXPathProcessHistory",
22280 "calling xmlStreamPop()");
22281 return (-1);
22282 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022283#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022284 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22285 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022286#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022287 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022288 goto deregister_check;
22289
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022290 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022291
22292 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022293 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022294 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022295 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022296 sto = sto->next;
22297 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022298 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022299 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022300 /*
22301 * NOTE: According to
22302 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22303 * ... the simple-content of complex types is also allowed.
22304 */
22305
22306 if (WXS_IS_COMPLEX(type)) {
22307 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22308 /*
22309 * Sanity check for complex types with simple content.
22310 */
22311 simpleType = type->contentTypeDef;
22312 if (simpleType == NULL) {
22313 VERROR_INT("xmlSchemaXPathProcessHistory",
22314 "field resolves to a CT with simple content "
22315 "but the CT is missing the ST definition");
22316 return (-1);
22317 }
22318 } else
22319 simpleType = NULL;
22320 } else
22321 simpleType = type;
22322 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022323 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022324
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022325 /*
22326 * Not qualified if the field resolves to a node of non
22327 * simple type.
22328 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022329 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022330 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022331 WXS_BASIC_CAST sto->matcher->aidc->def,
22332 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022333 "non-simple type",
22334 sto->sel->xpath,
22335 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22336 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022337 sto->nbHistory--;
22338 goto deregister_check;
22339 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022340
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022341 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022342 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022343 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022344 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022345 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022346 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022347 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022348 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022349 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022350 sto->nbHistory--;
22351 goto deregister_check;
22352 } else {
22353 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22354 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022355 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022356
22357 /*
22358 * The key will be anchored on the matcher's list of
22359 * key-sequences. The position in this list is determined
22360 * by the target node's depth relative to the matcher's
22361 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022362 *
22363 * Element Depth Pos List-entries
22364 * <scope> 0 NULL
22365 * <bar> 1 NULL
22366 * <target/> 2 2 target
22367 * <bar>
22368 * </scope>
22369 *
22370 * The size of the list is only dependant on the depth of
22371 * the tree.
22372 * An entry will be NULLed in selector_leave, i.e. when
22373 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022374 */
22375 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022376 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022377
22378 /*
22379 * Create/grow the array of key-sequences.
22380 */
22381 if (matcher->keySeqs == NULL) {
22382 if (pos > 9)
22383 matcher->sizeKeySeqs = pos * 2;
22384 else
22385 matcher->sizeKeySeqs = 10;
22386 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22387 xmlMalloc(matcher->sizeKeySeqs *
22388 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22389 if (matcher->keySeqs == NULL) {
22390 xmlSchemaVErrMemory(NULL,
22391 "allocating an array of key-sequences",
22392 NULL);
22393 return(-1);
22394 }
22395 memset(matcher->keySeqs, 0,
22396 matcher->sizeKeySeqs *
22397 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22398 } else if (pos >= matcher->sizeKeySeqs) {
22399 int i = matcher->sizeKeySeqs;
22400
22401 matcher->sizeKeySeqs *= 2;
22402 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22403 xmlRealloc(matcher->keySeqs,
22404 matcher->sizeKeySeqs *
22405 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022406 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022407 xmlSchemaVErrMemory(NULL,
22408 "reallocating an array of key-sequences",
22409 NULL);
22410 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022411 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022412 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022413 * The array needs to be NULLed.
22414 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022415 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022416 for (; i < matcher->sizeKeySeqs; i++)
22417 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022418 }
22419
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022420 /*
22421 * Get/create the key-sequence.
22422 */
22423 keySeq = matcher->keySeqs[pos];
22424 if (keySeq == NULL) {
22425 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022426 } else if (keySeq[idx] != NULL) {
22427 xmlChar *str = NULL;
22428 /*
22429 * cvc-identity-constraint:
22430 * 3 For each node in the ·target node set· all
22431 * of the {fields}, with that node as the context
22432 * node, evaluate to either an empty node-set or
22433 * a node-set with exactly one member, which must
22434 * have a simple type.
22435 *
22436 * The key was already set; report an error.
22437 */
22438 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22439 XML_SCHEMAV_CVC_IDC, NULL,
22440 WXS_BASIC_CAST matcher->aidc->def,
22441 "The XPath '%s' of a field of %s evaluates to a "
22442 "node-set with more than one member",
22443 sto->sel->xpath,
22444 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22445 FREE_AND_NULL(str);
22446 sto->nbHistory--;
22447 goto deregister_check;
22448 } else
22449 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022450
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022451create_sequence:
22452 /*
22453 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022454 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022455 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22456 matcher->aidc->def->nbFields *
22457 sizeof(xmlSchemaPSVIIDCKeyPtr));
22458 if (keySeq == NULL) {
22459 xmlSchemaVErrMemory(NULL,
22460 "allocating an IDC key-sequence", NULL);
22461 return(-1);
22462 }
22463 memset(keySeq, 0, matcher->aidc->def->nbFields *
22464 sizeof(xmlSchemaPSVIIDCKeyPtr));
22465 matcher->keySeqs[pos] = keySeq;
22466create_key:
22467 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022468 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022469 */
22470 if (key == NULL) {
22471 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22472 sizeof(xmlSchemaPSVIIDCKey));
22473 if (key == NULL) {
22474 xmlSchemaVErrMemory(NULL,
22475 "allocating a IDC key", NULL);
22476 xmlFree(keySeq);
22477 matcher->keySeqs[pos] = NULL;
22478 return(-1);
22479 }
22480 /*
22481 * Consume the compiled value.
22482 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022483 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022484 key->val = vctxt->inode->val;
22485 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022486 /*
22487 * Store the key in a global list.
22488 */
22489 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22490 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022491 return (-1);
22492 }
22493 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022494 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022495 }
22496 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022497
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022498 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022499 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022500 xmlSchemaPSVIIDCNodePtr ntItem;
22501 xmlSchemaIDCMatcherPtr matcher;
22502 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022503 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022504 int pos, i, j, nbKeys;
22505 /*
22506 * Here we have the following scenario:
22507 * An IDC 'selector' state object resolved to a target node,
22508 * during the time this target node was in the
22509 * ancestor-or-self axis, the 'field' state object(s) looked
22510 * out for matching nodes to create a key-sequence for this
22511 * target node. Now we are back to this target node and need
22512 * to put the key-sequence, together with the target node
22513 * itself, into the node-table of the corresponding IDC
22514 * binding.
22515 */
22516 matcher = sto->matcher;
22517 idc = matcher->aidc->def;
22518 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022519 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022520 /*
22521 * Check if the matcher has any key-sequences at all, plus
22522 * if it has a key-sequence for the current target node.
22523 */
22524 if ((matcher->keySeqs == NULL) ||
22525 (matcher->sizeKeySeqs <= pos)) {
22526 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22527 goto selector_key_error;
22528 else
22529 goto selector_leave;
22530 }
22531
22532 keySeq = &(matcher->keySeqs[pos]);
22533 if (*keySeq == NULL) {
22534 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22535 goto selector_key_error;
22536 else
22537 goto selector_leave;
22538 }
22539
22540 for (i = 0; i < nbKeys; i++) {
22541 if ((*keySeq)[i] == NULL) {
22542 /*
22543 * Not qualified, if not all fields did resolve.
22544 */
22545 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22546 /*
22547 * All fields of a "key" IDC must resolve.
22548 */
22549 goto selector_key_error;
22550 }
22551 goto selector_leave;
22552 }
22553 }
22554 /*
22555 * All fields did resolve.
22556 */
22557
22558 /*
22559 * 4.1 If the {identity-constraint category} is unique(/key),
22560 * then no two members of the ·qualified node set· have
22561 * ·key-sequences· whose members are pairwise equal, as
22562 * defined by Equal in [XML Schemas: Datatypes].
22563 *
22564 * Get the IDC binding from the matcher and check for
22565 * duplicate key-sequences.
22566 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022567#if 0
22568 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22569#endif
22570 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022571 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022572 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022573 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022574
22575 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022576 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022577 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022578 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022579 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022580 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022581 bkeySeq =
22582 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022583 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022584 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022585 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022586 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022587 if (res == -1) {
22588 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022589 } else if (res == 0) {
22590 /*
22591 * One of the keys differs, so the key-sequence
22592 * won't be equal; get out.
22593 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022594 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022595 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022596 }
22597 if (res == 1) {
22598 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022599 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022600 */
22601 break;
22602 }
22603 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022604 } while (i < targets->nbItems);
22605 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022606 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022607 /*
22608 * TODO: Try to report the key-sequence.
22609 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022610 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022611 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022612 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022613 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022614 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022615 (*keySeq), nbKeys),
22616 xmlSchemaGetIDCDesignation(&strB, idc));
22617 FREE_AND_NULL(str);
22618 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022619 goto selector_leave;
22620 }
22621 }
22622 /*
22623 * Add a node-table item to the IDC binding.
22624 */
22625 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22626 sizeof(xmlSchemaPSVIIDCNode));
22627 if (ntItem == NULL) {
22628 xmlSchemaVErrMemory(NULL,
22629 "allocating an IDC node-table item", NULL);
22630 xmlFree(*keySeq);
22631 *keySeq = NULL;
22632 return(-1);
22633 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022634 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022635
22636 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022637 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022638 */
22639 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22640 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22641 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022642 xmlFree(*keySeq);
22643 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022644 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022645 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022646 ntItem->nodeQNameID = -1;
22647 } else {
22648 /*
22649 * Save a cached QName for this node on the IDC node, to be
22650 * able to report it, even if the node is not saved.
22651 */
22652 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22653 vctxt->inode->localName, vctxt->inode->nsName);
22654 if (ntItem->nodeQNameID == -1) {
22655 xmlFree(ntItem);
22656 xmlFree(*keySeq);
22657 *keySeq = NULL;
22658 return (-1);
22659 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022660 }
22661 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022662 * Init the node-table item: Save the node, position and
22663 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022664 */
22665 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022666 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022667 ntItem->keys = *keySeq;
22668 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022669#if 0
22670 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22671#endif
22672 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022673 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22674 /*
22675 * Free the item, since keyref items won't be
22676 * put on a global list.
22677 */
22678 xmlFree(ntItem->keys);
22679 xmlFree(ntItem);
22680 }
22681 return (-1);
22682 }
22683
22684 goto selector_leave;
22685selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022686 {
22687 xmlChar *str = NULL;
22688 /*
22689 * 4.2.1 (KEY) The ·target node set· and the
22690 * ·qualified node set· are equal, that is, every
22691 * member of the ·target node set· is also a member
22692 * of the ·qualified node set· and vice versa.
22693 */
22694 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22695 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022696 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022697 "Not all fields of %s evaluate to a node",
22698 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22699 FREE_AND_NULL(str);
22700 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022701selector_leave:
22702 /*
22703 * Free the key-sequence if not added to the IDC table.
22704 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022705 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022706 xmlFree(*keySeq);
22707 *keySeq = NULL;
22708 }
22709 } /* if selector */
22710
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022711 sto->nbHistory--;
22712
22713deregister_check:
22714 /*
22715 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022716 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022717 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022718#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022719 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22720 sto->sel->xpath);
22721#endif
22722 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022723 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022724 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022725 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022726 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022727 nextsto = sto->next;
22728 /*
22729 * Unlink from the list of active XPath state objects.
22730 */
22731 vctxt->xpathStates = sto->next;
22732 sto->next = vctxt->xpathStatePool;
22733 /*
22734 * Link it to the pool of reusable state objects.
22735 */
22736 vctxt->xpathStatePool = sto;
22737 sto = nextsto;
22738 } else
22739 sto = sto->next;
22740 } /* while (sto != NULL) */
22741 return (0);
22742}
22743
22744/**
22745 * xmlSchemaIDCRegisterMatchers:
22746 * @vctxt: the WXS validation context
22747 * @elemDecl: the element declaration
22748 *
22749 * Creates helper objects to evaluate IDC selectors/fields
22750 * successively.
22751 *
22752 * Returns 0 if OK and -1 on internal errors.
22753 */
22754static int
22755xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22756 xmlSchemaElementPtr elemDecl)
22757{
22758 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22759 xmlSchemaIDCPtr idc, refIdc;
22760 xmlSchemaIDCAugPtr aidc;
22761
22762 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22763 if (idc == NULL)
22764 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022765
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022766#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022767 {
22768 xmlChar *str = NULL;
22769 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022770 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022771 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22772 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022773 FREE_AND_NULL(str)
22774 }
22775#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022776 if (vctxt->inode->idcMatchers != NULL) {
22777 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22778 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022779 return (-1);
22780 }
22781 do {
22782 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22783 /*
22784 * Since IDCs bubbles are expensive we need to know the
22785 * depth at which the bubbles should stop; this will be
22786 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022787 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022788 * be -1, indicating that no bubbles are needed.
22789 */
22790 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22791 if (refIdc != NULL) {
22792 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022793 * Remember that we have keyrefs on this node.
22794 */
22795 vctxt->inode->hasKeyrefs = 1;
22796 /*
22797 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022798 */
22799 aidc = vctxt->aidcs;
22800 while (aidc != NULL) {
22801 if (aidc->def == refIdc)
22802 break;
22803 aidc = aidc->next;
22804 }
22805 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022806 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022807 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022808 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022809 return (-1);
22810 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022811 if ((aidc->keyrefDepth == -1) ||
22812 (vctxt->depth < aidc->keyrefDepth))
22813 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022814 }
22815 }
22816 /*
22817 * Lookup the augmented IDC item for the IDC definition.
22818 */
22819 aidc = vctxt->aidcs;
22820 while (aidc != NULL) {
22821 if (aidc->def == idc)
22822 break;
22823 aidc = aidc->next;
22824 }
22825 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022826 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22827 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022828 return (-1);
22829 }
22830 /*
22831 * Create an IDC matcher for every IDC definition.
22832 */
22833 matcher = (xmlSchemaIDCMatcherPtr)
22834 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22835 if (matcher == NULL) {
22836 xmlSchemaVErrMemory(vctxt,
22837 "allocating an IDC matcher", NULL);
22838 return (-1);
22839 }
22840 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22841 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022842 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022843 else
22844 last->next = matcher;
22845 last = matcher;
22846
22847 matcher->type = IDC_MATCHER;
22848 matcher->depth = vctxt->depth;
22849 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022850 matcher->idcType = aidc->def->type;
22851#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022852 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22853#endif
22854 /*
22855 * Init the automaton state object.
22856 */
22857 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022858 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022859 return (-1);
22860
22861 idc = idc->next;
22862 } while (idc != NULL);
22863 return (0);
22864}
22865
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022866static int
22867xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22868 xmlSchemaNodeInfoPtr ielem)
22869{
22870 xmlSchemaPSVIIDCBindingPtr bind;
22871 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22872 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22873 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22874
22875 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22876 /* vctxt->createIDCNodeTables */
22877 while (matcher != NULL) {
22878 /*
22879 * Skip keyref IDCs and empty IDC target-lists.
22880 */
22881 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22882 WXS_ILIST_IS_EMPTY(matcher->targets))
22883 {
22884 matcher = matcher->next;
22885 continue;
22886 }
22887 /*
22888 * If we _want_ the IDC node-table to be created in any case
22889 * then do so. Otherwise create them only if keyrefs need them.
22890 */
22891 if ((! vctxt->createIDCNodeTables) &&
22892 ((matcher->aidc->keyrefDepth == -1) ||
22893 (matcher->aidc->keyrefDepth > vctxt->depth)))
22894 {
22895 matcher = matcher->next;
22896 continue;
22897 }
22898 /*
22899 * Get/create the IDC binding on this element for the IDC definition.
22900 */
22901 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22902
22903 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22904 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22905 nbDupls = bind->dupls->nbItems;
22906 } else {
22907 dupls = NULL;
22908 nbDupls = 0;
22909 }
22910 if (bind->nodeTable != NULL) {
22911 nbNodeTable = bind->nbNodes;
22912 } else {
22913 nbNodeTable = 0;
22914 }
22915
22916 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22917 /*
22918 * Transfer all IDC target-nodes to the IDC node-table.
22919 */
22920 bind->nodeTable =
22921 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22922 bind->sizeNodes = matcher->targets->sizeItems;
22923 bind->nbNodes = matcher->targets->nbItems;
22924
22925 matcher->targets->items = NULL;
22926 matcher->targets->sizeItems = 0;
22927 matcher->targets->nbItems = 0;
22928 } else {
22929 /*
22930 * Compare the key-sequences and add to the IDC node-table.
22931 */
22932 nbTargets = matcher->targets->nbItems;
22933 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22934 nbFields = matcher->aidc->def->nbFields;
22935 i = 0;
22936 do {
22937 keys = targets[i]->keys;
22938 if (nbDupls) {
22939 /*
22940 * Search in already found duplicates first.
22941 */
22942 j = 0;
22943 do {
22944 if (nbFields == 1) {
22945 res = xmlSchemaAreValuesEqual(keys[0]->val,
22946 dupls[j]->keys[0]->val);
22947 if (res == -1)
22948 goto internal_error;
22949 if (res == 1) {
22950 /*
22951 * Equal key-sequence.
22952 */
22953 goto next_target;
22954 }
22955 } else {
22956 res = 0;
22957 ntkeys = dupls[j]->keys;
22958 for (k = 0; k < nbFields; k++) {
22959 res = xmlSchemaAreValuesEqual(keys[k]->val,
22960 ntkeys[k]->val);
22961 if (res == -1)
22962 goto internal_error;
22963 if (res == 0) {
22964 /*
22965 * One of the keys differs.
22966 */
22967 break;
22968 }
22969 }
22970 if (res == 1) {
22971 /*
22972 * Equal key-sequence found.
22973 */
22974 goto next_target;
22975 }
22976 }
22977 j++;
22978 } while (j < nbDupls);
22979 }
22980 if (nbNodeTable) {
22981 j = 0;
22982 do {
22983 if (nbFields == 1) {
22984 res = xmlSchemaAreValuesEqual(keys[0]->val,
22985 bind->nodeTable[j]->keys[0]->val);
22986 if (res == -1)
22987 goto internal_error;
22988 if (res == 0) {
22989 /*
22990 * The key-sequence differs.
22991 */
22992 goto next_node_table_entry;
22993 }
22994 } else {
22995 res = 0;
22996 ntkeys = bind->nodeTable[j]->keys;
22997 for (k = 0; k < nbFields; k++) {
22998 res = xmlSchemaAreValuesEqual(keys[k]->val,
22999 ntkeys[k]->val);
23000 if (res == -1)
23001 goto internal_error;
23002 if (res == 0) {
23003 /*
23004 * One of the keys differs.
23005 */
23006 goto next_node_table_entry;
23007 }
23008 }
23009 }
23010 /*
23011 * Add the duplicate to the list of duplicates.
23012 */
23013 if (bind->dupls == NULL) {
23014 bind->dupls = xmlSchemaItemListCreate();
23015 if (bind->dupls == NULL)
23016 goto internal_error;
23017 }
23018 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23019 goto internal_error;
23020 /*
23021 * Remove the duplicate entry from the IDC node-table.
23022 */
23023 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23024 bind->nbNodes--;
23025
23026 goto next_target;
23027
23028next_node_table_entry:
23029 j++;
23030 } while (j < nbNodeTable);
23031 }
23032 /*
23033 * If everything is fine, then add the IDC target-node to
23034 * the IDC node-table.
23035 */
23036 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23037 goto internal_error;
23038
23039next_target:
23040 i++;
23041 } while (i < nbTargets);
23042 }
23043 matcher = matcher->next;
23044 }
23045 return(0);
23046
23047internal_error:
23048 return(-1);
23049}
23050
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023051/**
23052 * xmlSchemaBubbleIDCNodeTables:
23053 * @depth: the current tree depth
23054 *
23055 * Merges IDC bindings of an element at @depth into the corresponding IDC
23056 * bindings of its parent element. If a duplicate note-table entry is found,
23057 * both, the parent node-table entry and child entry are discarded from the
23058 * node-table of the parent.
23059 *
23060 * Returns 0 if OK and -1 on internal errors.
23061 */
23062static int
23063xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23064{
23065 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023066 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23067 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023068 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023069 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023070
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023071 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023072 if (bind == NULL) {
23073 /* Fine, no table, no bubbles. */
23074 return (0);
23075 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023076
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023077 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23078 /*
23079 * Walk all bindings; create new or add to existing bindings.
23080 * Remove duplicate key-sequences.
23081 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023082 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023083
23084 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23085 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023086 /*
23087 * Check if the key/unique IDC table needs to be bubbled.
23088 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023089 if (! vctxt->createIDCNodeTables) {
23090 aidc = vctxt->aidcs;
23091 do {
23092 if (aidc->def == bind->definition) {
23093 if ((aidc->keyrefDepth == -1) ||
23094 (aidc->keyrefDepth >= vctxt->depth)) {
23095 goto next_binding;
23096 }
23097 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023098 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023099 aidc = aidc->next;
23100 } while (aidc != NULL);
23101 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023102
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023103 if (parTable != NULL)
23104 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023105 /*
23106 * Search a matching parent binding for the
23107 * IDC definition.
23108 */
23109 while (parBind != NULL) {
23110 if (parBind->definition == bind->definition)
23111 break;
23112 parBind = parBind->next;
23113 }
23114
23115 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023116 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023117 * Compare every node-table entry of the child node,
23118 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023119 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023120 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023121
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023122 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23123 oldDupls = parBind->dupls->nbItems;
23124 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23125 } else {
23126 dupls = NULL;
23127 oldDupls = 0;
23128 }
23129
23130 parNodes = parBind->nodeTable;
23131 nbFields = bind->definition->nbFields;
23132
23133 for (i = 0; i < bind->nbNodes; i++) {
23134 node = bind->nodeTable[i];
23135 if (node == NULL)
23136 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023137 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023138 * ...with every key-sequence of the parent node, already
23139 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023140 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023141 if (oldDupls) {
23142 j = 0;
23143 while (j < oldDupls) {
23144 if (nbFields == 1) {
23145 ret = xmlSchemaAreValuesEqual(
23146 node->keys[0]->val,
23147 dupls[j]->keys[0]->val);
23148 if (ret == -1)
23149 goto internal_error;
23150 if (ret == 0) {
23151 j++;
23152 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023153 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023154 } else {
23155 parNode = dupls[j];
23156 for (k = 0; k < nbFields; k++) {
23157 ret = xmlSchemaAreValuesEqual(
23158 node->keys[k]->val,
23159 parNode->keys[k]->val);
23160 if (ret == -1)
23161 goto internal_error;
23162 if (ret == 0)
23163 break;
23164 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023165 }
23166 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023167 /* Duplicate found. */
23168 break;
23169 j++;
23170 }
23171 if (j != oldDupls) {
23172 /* Duplicate found. Skip this entry. */
23173 continue;
23174 }
23175 }
23176 /*
23177 * ... and with every key-sequence of the parent node.
23178 */
23179 if (oldNum) {
23180 j = 0;
23181 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023182 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023183 if (nbFields == 1) {
23184 ret = xmlSchemaAreValuesEqual(
23185 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023186 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023187 if (ret == -1)
23188 goto internal_error;
23189 if (ret == 0) {
23190 j++;
23191 continue;
23192 }
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023193 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023194 for (k = 0; k < nbFields; k++) {
23195 ret = xmlSchemaAreValuesEqual(
23196 node->keys[k]->val,
23197 parNode->keys[k]->val);
23198 if (ret == -1)
23199 goto internal_error;
23200 if (ret == 0)
23201 break;
23202 }
23203 }
23204 if (ret == 1)
23205 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023206 break;
23207 j++;
23208 }
23209 if (j != oldNum) {
23210 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023211 * Handle duplicates. Move the duplicate in
23212 * the parent's node-table to the list of
23213 * duplicates.
23214 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023215 oldNum--;
23216 parBind->nbNodes--;
23217 /*
23218 * Move last old item to pos of duplicate.
23219 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023220 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023221
23222 if (parBind->nbNodes != oldNum) {
23223 /*
23224 * If new items exist, move last new item to
23225 * last of old items.
23226 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023227 parNodes[oldNum] =
23228 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023229 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023230 if (parBind->dupls == NULL) {
23231 parBind->dupls = xmlSchemaItemListCreate();
23232 if (parBind->dupls == NULL)
23233 goto internal_error;
23234 }
23235 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023236 } else {
23237 /*
23238 * Add the node-table entry (node and key-sequence) of
23239 * the child node to the node table of the parent node.
23240 */
23241 if (parBind->nodeTable == NULL) {
23242 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023243 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023244 if (parBind->nodeTable == NULL) {
23245 xmlSchemaVErrMemory(NULL,
23246 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023247 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023248 }
23249 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023250 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023251 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023252 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23253 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23254 sizeof(xmlSchemaPSVIIDCNodePtr));
23255 if (parBind->nodeTable == NULL) {
23256 xmlSchemaVErrMemory(NULL,
23257 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023258 goto internal_error;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023259 }
23260 }
23261 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023262 /*
23263 * Append the new node-table entry to the 'new node-table
23264 * entries' section.
23265 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023266 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023267 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023268
23269 }
23270
23271 }
23272 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023273 /*
23274 * No binding for the IDC was found: create a new one and
23275 * copy all node-tables.
23276 */
23277 parBind = xmlSchemaIDCNewBinding(bind->definition);
23278 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023279 goto internal_error;
23280
23281 /*
23282 * TODO: Hmm, how to optimize the initial number of
23283 * allocated entries?
23284 */
23285 if (bind->nbNodes != 0) {
23286 /*
23287 * Add all IDC node-table entries.
23288 */
23289 if (! vctxt->psviExposeIDCNodeTables) {
23290 /*
23291 * Just move the entries.
23292 * NOTE: this is quite save here, since
23293 * all the keyref lookups have already been
23294 * performed.
23295 */
23296 parBind->nodeTable = bind->nodeTable;
23297 bind->nodeTable = NULL;
23298 parBind->sizeNodes = bind->sizeNodes;
23299 bind->sizeNodes = 0;
23300 parBind->nbNodes = bind->nbNodes;
23301 bind->nbNodes = 0;
23302 } else {
23303 /*
23304 * Copy the entries.
23305 */
23306 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23307 xmlMalloc(bind->nbNodes *
23308 sizeof(xmlSchemaPSVIIDCNodePtr));
23309 if (parBind->nodeTable == NULL) {
23310 xmlSchemaVErrMemory(NULL,
23311 "allocating an array of IDC node-table "
23312 "items", NULL);
23313 xmlSchemaIDCFreeBinding(parBind);
23314 goto internal_error;
23315 }
23316 parBind->sizeNodes = bind->nbNodes;
23317 parBind->nbNodes = bind->nbNodes;
23318 memcpy(parBind->nodeTable, bind->nodeTable,
23319 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23320 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023321 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023322 if (bind->dupls) {
23323 /*
23324 * Move the duplicates.
23325 */
23326 if (parBind->dupls != NULL)
23327 xmlSchemaItemListFree(parBind->dupls);
23328 parBind->dupls = bind->dupls;
23329 bind->dupls = NULL;
23330 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023331 if (*parTable == NULL)
23332 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023333 else {
23334 parBind->next = *parTable;
23335 *parTable = parBind;
23336 }
23337 }
23338
23339next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023340 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023341 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023342 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023343
23344internal_error:
23345 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023346}
23347
23348/**
23349 * xmlSchemaCheckCVCIDCKeyRef:
23350 * @vctxt: the WXS validation context
23351 * @elemDecl: the element declaration
23352 *
23353 * Check the cvc-idc-keyref constraints.
23354 */
23355static int
23356xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23357{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023358 xmlSchemaIDCMatcherPtr matcher;
23359 xmlSchemaPSVIIDCBindingPtr bind;
23360
23361 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023362 /*
23363 * Find a keyref.
23364 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023365 while (matcher != NULL) {
23366 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23367 matcher->targets &&
23368 matcher->targets->nbItems)
23369 {
23370 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023371 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023372 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023373
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023374 nbFields = matcher->aidc->def->nbFields;
23375
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023376 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023377 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023378 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023379 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023380 while (bind != NULL) {
23381 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023382 bind->definition)
23383 break;
23384 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023385 }
23386 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023387 /*
23388 * Search for a matching key-sequences.
23389 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023390 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023391 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023392 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023393 if (bind != NULL) {
23394 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023395 for (j = 0; j < bind->nbNodes; j++) {
23396 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023397 for (k = 0; k < nbFields; k++) {
23398 res = xmlSchemaAreValuesEqual(keys[k]->val,
23399 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023400 if (res == 0)
23401 break;
23402 else if (res == -1) {
23403 return (-1);
23404 }
23405 }
23406 if (res == 1) {
23407 /*
23408 * Match found.
23409 */
23410 break;
23411 }
23412 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023413 if ((res == 0) && hasDupls) {
23414 /*
23415 * Search in duplicates
23416 */
23417 for (j = 0; j < bind->dupls->nbItems; j++) {
23418 keys = ((xmlSchemaPSVIIDCNodePtr)
23419 bind->dupls->items[j])->keys;
23420 for (k = 0; k < nbFields; k++) {
23421 res = xmlSchemaAreValuesEqual(keys[k]->val,
23422 refKeys[k]->val);
23423 if (res == 0)
23424 break;
23425 else if (res == -1) {
23426 return (-1);
23427 }
23428 }
23429 if (res == 1) {
23430 /*
23431 * Match in duplicates found.
23432 */
23433 xmlChar *str = NULL, *strB = NULL;
23434 xmlSchemaKeyrefErr(vctxt,
23435 XML_SCHEMAV_CVC_IDC, refNode,
23436 (xmlSchemaTypePtr) matcher->aidc->def,
23437 "More than one match found for "
23438 "key-sequence %s of keyref '%s'",
23439 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23440 refNode->keys, nbFields),
23441 xmlSchemaGetComponentQName(&strB,
23442 matcher->aidc->def));
23443 FREE_AND_NULL(str);
23444 FREE_AND_NULL(strB);
23445 break;
23446 }
23447 }
23448 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023449 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023450
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023451 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023452 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023453 xmlSchemaKeyrefErr(vctxt,
23454 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023455 (xmlSchemaTypePtr) matcher->aidc->def,
23456 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023457 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023458 refNode->keys, nbFields),
23459 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023460 FREE_AND_NULL(str);
23461 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023462 }
23463 }
23464 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023465 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023466 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023467 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023468 return (0);
23469}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023470
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023471/************************************************************************
23472 * *
23473 * XML Reader validation code *
23474 * *
23475 ************************************************************************/
23476
23477static xmlSchemaAttrInfoPtr
23478xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023479{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023480 xmlSchemaAttrInfoPtr iattr;
23481 /*
23482 * Grow/create list of attribute infos.
23483 */
23484 if (vctxt->attrInfos == NULL) {
23485 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23486 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23487 vctxt->sizeAttrInfos = 1;
23488 if (vctxt->attrInfos == NULL) {
23489 xmlSchemaVErrMemory(vctxt,
23490 "allocating attribute info list", NULL);
23491 return (NULL);
23492 }
23493 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23494 vctxt->sizeAttrInfos++;
23495 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23496 xmlRealloc(vctxt->attrInfos,
23497 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23498 if (vctxt->attrInfos == NULL) {
23499 xmlSchemaVErrMemory(vctxt,
23500 "re-allocating attribute info list", NULL);
23501 return (NULL);
23502 }
23503 } else {
23504 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23505 if (iattr->localName != NULL) {
23506 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23507 "attr info not cleared");
23508 return (NULL);
23509 }
23510 iattr->nodeType = XML_ATTRIBUTE_NODE;
23511 return (iattr);
23512 }
23513 /*
23514 * Create an attribute info.
23515 */
23516 iattr = (xmlSchemaAttrInfoPtr)
23517 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23518 if (iattr == NULL) {
23519 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23520 return (NULL);
23521 }
23522 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23523 iattr->nodeType = XML_ATTRIBUTE_NODE;
23524 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23525
23526 return (iattr);
23527}
23528
23529static int
23530xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23531 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023532 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023533 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023534 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023535 int ownedNames,
23536 xmlChar *value,
23537 int ownedValue)
23538{
23539 xmlSchemaAttrInfoPtr attr;
23540
23541 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23542 if (attr == NULL) {
23543 VERROR_INT("xmlSchemaPushAttribute",
23544 "calling xmlSchemaGetFreshAttrInfo()");
23545 return (-1);
23546 }
23547 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023548 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023549 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23550 attr->localName = localName;
23551 attr->nsName = nsName;
23552 if (ownedNames)
23553 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23554 /*
23555 * Evaluate if it's an XSI attribute.
23556 */
23557 if (nsName != NULL) {
23558 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23559 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23560 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23561 }
23562 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23563 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23564 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23565 }
23566 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23567 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23568 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23569 }
23570 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23571 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23572 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23573 }
23574 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23575 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23576 }
23577 }
23578 attr->value = value;
23579 if (ownedValue)
23580 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23581 if (attr->metaType != 0)
23582 attr->state = XML_SCHEMAS_ATTR_META;
23583 return (0);
23584}
23585
23586static void
23587xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23588{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023589 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023590 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023591 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23592 FREE_AND_NULL(ielem->localName);
23593 FREE_AND_NULL(ielem->nsName);
23594 } else {
23595 ielem->localName = NULL;
23596 ielem->nsName = NULL;
23597 }
23598 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23599 FREE_AND_NULL(ielem->value);
23600 } else {
23601 ielem->value = NULL;
23602 }
23603 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023604 /*
23605 * PSVI TODO: Be careful not to free it when the value is
23606 * exposed via PSVI.
23607 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023608 xmlSchemaFreeValue(ielem->val);
23609 ielem->val = NULL;
23610 }
23611 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023612 /*
23613 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023615 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23616 ielem->idcMatchers = NULL;
23617 }
23618 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023619 /*
23620 * OPTIMIZE TODO: Use a pool of IDC tables??.
23621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023622 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23623 ielem->idcTable = NULL;
23624 }
23625 if (ielem->regexCtxt != NULL) {
23626 xmlRegFreeExecCtxt(ielem->regexCtxt);
23627 ielem->regexCtxt = NULL;
23628 }
23629 if (ielem->nsBindings != NULL) {
23630 xmlFree((xmlChar **)ielem->nsBindings);
23631 ielem->nsBindings = NULL;
23632 ielem->nbNsBindings = 0;
23633 ielem->sizeNsBindings = 0;
23634 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023635}
23636
23637/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023638 * xmlSchemaGetFreshElemInfo:
23639 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023640 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023641 * Creates/reuses and initializes the element info item for
23642 * the currect tree depth.
23643 *
23644 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023646static xmlSchemaNodeInfoPtr
23647xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023648{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023649 xmlSchemaNodeInfoPtr info = NULL;
23650
23651 if (vctxt->depth > vctxt->sizeElemInfos) {
23652 VERROR_INT("xmlSchemaGetFreshElemInfo",
23653 "inconsistent depth encountered");
23654 return (NULL);
23655 }
23656 if (vctxt->elemInfos == NULL) {
23657 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23658 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23659 if (vctxt->elemInfos == NULL) {
23660 xmlSchemaVErrMemory(vctxt,
23661 "allocating the element info array", NULL);
23662 return (NULL);
23663 }
23664 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23665 vctxt->sizeElemInfos = 10;
23666 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23667 int i = vctxt->sizeElemInfos;
23668
23669 vctxt->sizeElemInfos *= 2;
23670 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23671 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23672 sizeof(xmlSchemaNodeInfoPtr));
23673 if (vctxt->elemInfos == NULL) {
23674 xmlSchemaVErrMemory(vctxt,
23675 "re-allocating the element info array", NULL);
23676 return (NULL);
23677 }
23678 /*
23679 * We need the new memory to be NULLed.
23680 * TODO: Use memset instead?
23681 */
23682 for (; i < vctxt->sizeElemInfos; i++)
23683 vctxt->elemInfos[i] = NULL;
23684 } else
23685 info = vctxt->elemInfos[vctxt->depth];
23686
23687 if (info == NULL) {
23688 info = (xmlSchemaNodeInfoPtr)
23689 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23690 if (info == NULL) {
23691 xmlSchemaVErrMemory(vctxt,
23692 "allocating an element info", NULL);
23693 return (NULL);
23694 }
23695 vctxt->elemInfos[vctxt->depth] = info;
23696 } else {
23697 if (info->localName != NULL) {
23698 VERROR_INT("xmlSchemaGetFreshElemInfo",
23699 "elem info has not been cleared");
23700 return (NULL);
23701 }
23702 }
23703 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23704 info->nodeType = XML_ELEMENT_NODE;
23705 info->depth = vctxt->depth;
23706
23707 return (info);
23708}
23709
23710#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23711#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23712#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23713
23714static int
23715xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23716 xmlNodePtr node,
23717 xmlSchemaTypePtr type,
23718 xmlSchemaValType valType,
23719 const xmlChar * value,
23720 xmlSchemaValPtr val,
23721 unsigned long length,
23722 int fireErrors)
23723{
23724 int ret, error = 0;
23725
23726 xmlSchemaTypePtr tmpType;
23727 xmlSchemaFacetLinkPtr facetLink;
23728 xmlSchemaFacetPtr facet;
23729 unsigned long len = 0;
23730 xmlSchemaWhitespaceValueType ws;
23731
23732 /*
23733 * In Libxml2, derived built-in types have currently no explicit facets.
23734 */
23735 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023736 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023737
23738 /*
23739 * NOTE: Do not jump away, if the facetSet of the given type is
23740 * empty: until now, "pattern" and "enumeration" facets of the
23741 * *base types* need to be checked as well.
23742 */
23743 if (type->facetSet == NULL)
23744 goto pattern_and_enum;
23745
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023746 if (! WXS_IS_ATOMIC(type)) {
23747 if (WXS_IS_LIST(type))
23748 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023749 else
23750 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023751 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023752 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023753 * Whitespace handling is only of importance for string-based
23754 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023755 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023756 tmpType = xmlSchemaGetPrimitiveType(type);
23757 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023758 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023759 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23760 } else
23761 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23762 /*
23763 * If the value was not computed (for string or
23764 * anySimpleType based types), then use the provided
23765 * type.
23766 */
23767 if (val == NULL)
23768 valType = valType;
23769 else
23770 valType = xmlSchemaGetValType(val);
23771
23772 ret = 0;
23773 for (facetLink = type->facetSet; facetLink != NULL;
23774 facetLink = facetLink->next) {
23775 /*
23776 * Skip the pattern "whiteSpace": it is used to
23777 * format the character content beforehand.
23778 */
23779 switch (facetLink->facet->type) {
23780 case XML_SCHEMA_FACET_WHITESPACE:
23781 case XML_SCHEMA_FACET_PATTERN:
23782 case XML_SCHEMA_FACET_ENUMERATION:
23783 continue;
23784 case XML_SCHEMA_FACET_LENGTH:
23785 case XML_SCHEMA_FACET_MINLENGTH:
23786 case XML_SCHEMA_FACET_MAXLENGTH:
23787 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23788 valType, value, val, &len, ws);
23789 break;
23790 default:
23791 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23792 valType, value, val, ws);
23793 break;
23794 }
23795 if (ret < 0) {
23796 AERROR_INT("xmlSchemaValidateFacets",
23797 "validating against a atomic type facet");
23798 return (-1);
23799 } else if (ret > 0) {
23800 if (fireErrors)
23801 xmlSchemaFacetErr(actxt, ret, node,
23802 value, len, type, facetLink->facet, NULL, NULL, NULL);
23803 else
23804 return (ret);
23805 if (error == 0)
23806 error = ret;
23807 }
23808 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023809 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023810
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023811WXS_IS_LIST:
23812 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023813 goto pattern_and_enum;
23814 /*
23815 * "length", "minLength" and "maxLength" of list types.
23816 */
23817 ret = 0;
23818 for (facetLink = type->facetSet; facetLink != NULL;
23819 facetLink = facetLink->next) {
23820
23821 switch (facetLink->facet->type) {
23822 case XML_SCHEMA_FACET_LENGTH:
23823 case XML_SCHEMA_FACET_MINLENGTH:
23824 case XML_SCHEMA_FACET_MAXLENGTH:
23825 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23826 value, length, NULL);
23827 break;
23828 default:
23829 continue;
23830 }
23831 if (ret < 0) {
23832 AERROR_INT("xmlSchemaValidateFacets",
23833 "validating against a list type facet");
23834 return (-1);
23835 } else if (ret > 0) {
23836 if (fireErrors)
23837 xmlSchemaFacetErr(actxt, ret, node,
23838 value, length, type, facetLink->facet, NULL, NULL, NULL);
23839 else
23840 return (ret);
23841 if (error == 0)
23842 error = ret;
23843 }
23844 ret = 0;
23845 }
23846
23847pattern_and_enum:
23848 if (error >= 0) {
23849 int found = 0;
23850 /*
23851 * Process enumerations. Facet values are in the value space
23852 * of the defining type's base type. This seems to be a bug in the
23853 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23854 * Only the first set of enumerations in the ancestor-or-self axis
23855 * is used for validation.
23856 */
23857 ret = 0;
23858 tmpType = type;
23859 do {
23860 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23861 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23862 continue;
23863 found = 1;
23864 ret = xmlSchemaAreValuesEqual(facet->val, val);
23865 if (ret == 1)
23866 break;
23867 else if (ret < 0) {
23868 AERROR_INT("xmlSchemaValidateFacets",
23869 "validating against an enumeration facet");
23870 return (-1);
23871 }
23872 }
23873 if (ret != 0)
23874 break;
23875 tmpType = tmpType->baseType;
23876 } while ((tmpType != NULL) &&
23877 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23878 if (found && (ret == 0)) {
23879 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23880 if (fireErrors) {
23881 xmlSchemaFacetErr(actxt, ret, node,
23882 value, 0, type, NULL, NULL, NULL, NULL);
23883 } else
23884 return (ret);
23885 if (error == 0)
23886 error = ret;
23887 }
23888 }
23889
23890 if (error >= 0) {
23891 int found;
23892 /*
23893 * Process patters. Pattern facets are ORed at type level
23894 * and ANDed if derived. Walk the base type axis.
23895 */
23896 tmpType = type;
23897 facet = NULL;
23898 do {
23899 found = 0;
23900 for (facetLink = tmpType->facetSet; facetLink != NULL;
23901 facetLink = facetLink->next) {
23902 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23903 continue;
23904 found = 1;
23905 /*
23906 * NOTE that for patterns, @value needs to be the
23907 * normalized vaule.
23908 */
23909 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23910 if (ret == 1)
23911 break;
23912 else if (ret < 0) {
23913 AERROR_INT("xmlSchemaValidateFacets",
23914 "validating against a pattern facet");
23915 return (-1);
23916 } else {
23917 /*
23918 * Save the last non-validating facet.
23919 */
23920 facet = facetLink->facet;
23921 }
23922 }
23923 if (found && (ret != 1)) {
23924 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23925 if (fireErrors) {
23926 xmlSchemaFacetErr(actxt, ret, node,
23927 value, 0, type, facet, NULL, NULL, NULL);
23928 } else
23929 return (ret);
23930 if (error == 0)
23931 error = ret;
23932 break;
23933 }
23934 tmpType = tmpType->baseType;
23935 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23936 }
23937
23938 return (error);
23939}
23940
23941static xmlChar *
23942xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23943 const xmlChar *value)
23944{
23945 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23946 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23947 return (xmlSchemaCollapseString(value));
23948 case XML_SCHEMA_WHITESPACE_REPLACE:
23949 return (xmlSchemaWhiteSpaceReplace(value));
23950 default:
23951 return (NULL);
23952 }
23953}
23954
23955static int
23956xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23957 const xmlChar *value,
23958 xmlSchemaValPtr *val,
23959 int valNeeded)
23960{
23961 int ret;
23962 const xmlChar *nsName;
23963 xmlChar *local, *prefix = NULL;
23964
23965 ret = xmlValidateQName(value, 1);
23966 if (ret != 0) {
23967 if (ret == -1) {
23968 VERROR_INT("xmlSchemaValidateQName",
23969 "calling xmlValidateQName()");
23970 return (-1);
23971 }
23972 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23973 }
23974 /*
23975 * NOTE: xmlSplitQName2 will always return a duplicated
23976 * strings.
23977 */
23978 local = xmlSplitQName2(value, &prefix);
23979 if (local == NULL)
23980 local = xmlStrdup(value);
23981 /*
23982 * OPTIMIZE TODO: Use flags for:
23983 * - is there any namespace binding?
23984 * - is there a default namespace?
23985 */
23986 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23987
23988 if (prefix != NULL) {
23989 xmlFree(prefix);
23990 /*
23991 * A namespace must be found if the prefix is
23992 * NOT NULL.
23993 */
23994 if (nsName == NULL) {
23995 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023996 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023997 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023998 "The QName value '%s' has no "
23999 "corresponding namespace declaration in "
24000 "scope", value, NULL);
24001 if (local != NULL)
24002 xmlFree(local);
24003 return (ret);
24004 }
24005 }
24006 if (valNeeded && val) {
24007 if (nsName != NULL)
24008 *val = xmlSchemaNewQNameValue(
24009 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24010 else
24011 *val = xmlSchemaNewQNameValue(NULL,
24012 BAD_CAST local);
24013 } else
24014 xmlFree(local);
24015 return (0);
24016}
24017
24018/*
24019* cvc-simple-type
24020*/
24021static int
24022xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24023 xmlNodePtr node,
24024 xmlSchemaTypePtr type,
24025 const xmlChar *value,
24026 xmlSchemaValPtr *retVal,
24027 int fireErrors,
24028 int normalize,
24029 int isNormalized)
24030{
24031 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24032 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024033 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024034 xmlChar *normValue = NULL;
24035
24036#define NORMALIZE(atype) \
24037 if ((! isNormalized) && \
24038 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24039 normValue = xmlSchemaNormalizeValue(atype, value); \
24040 if (normValue != NULL) \
24041 value = normValue; \
24042 isNormalized = 1; \
24043 }
24044
24045 if ((retVal != NULL) && (*retVal != NULL)) {
24046 xmlSchemaFreeValue(*retVal);
24047 *retVal = NULL;
24048 }
24049 /*
24050 * 3.14.4 Simple Type Definition Validation Rules
24051 * Validation Rule: String Valid
24052 */
24053 /*
24054 * 1 It is schema-valid with respect to that definition as defined
24055 * by Datatype Valid in [XML Schemas: Datatypes].
24056 */
24057 /*
24058 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24059 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24060 * the string must be a ·declared entity name·.
24061 */
24062 /*
24063 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24064 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24065 * then every whitespace-delimited substring of the string must be a ·declared
24066 * entity name·.
24067 */
24068 /*
24069 * 2.3 otherwise no further condition applies.
24070 */
24071 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24072 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024073 if (value == NULL)
24074 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024075 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024076 xmlSchemaTypePtr biType; /* The built-in type. */
24077 /*
24078 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24079 * a literal in the ·lexical space· of {base type definition}"
24080 */
24081 /*
24082 * Whitespace-normalize.
24083 */
24084 NORMALIZE(type);
24085 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24086 /*
24087 * Get the built-in type.
24088 */
24089 biType = type->baseType;
24090 while ((biType != NULL) &&
24091 (biType->type != XML_SCHEMA_TYPE_BASIC))
24092 biType = biType->baseType;
24093
24094 if (biType == NULL) {
24095 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24096 "could not get the built-in type");
24097 goto internal_error;
24098 }
24099 } else
24100 biType = type;
24101 /*
24102 * NOTATIONs need to be processed here, since they need
24103 * to lookup in the hashtable of NOTATION declarations of the schema.
24104 */
24105 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24106 switch (biType->builtInType) {
24107 case XML_SCHEMAS_NOTATION:
24108 ret = xmlSchemaValidateNotation(
24109 (xmlSchemaValidCtxtPtr) actxt,
24110 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24111 NULL, value, &val, valNeeded);
24112 break;
24113 case XML_SCHEMAS_QNAME:
24114 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24115 value, &val, valNeeded);
24116 break;
24117 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024118 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024119 if (valNeeded)
24120 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24121 value, &val, NULL);
24122 else
24123 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24124 value, NULL, NULL);
24125 break;
24126 }
24127 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24128 switch (biType->builtInType) {
24129 case XML_SCHEMAS_NOTATION:
24130 ret = xmlSchemaValidateNotation(NULL,
24131 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24132 value, &val, valNeeded);
24133 break;
24134 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024135 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024136 if (valNeeded)
24137 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24138 value, &val, node);
24139 else
24140 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24141 value, NULL, node);
24142 break;
24143 }
24144 } else {
24145 /*
24146 * Validation via a public API is not implemented yet.
24147 */
24148 TODO
24149 goto internal_error;
24150 }
24151 if (ret != 0) {
24152 if (ret < 0) {
24153 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24154 "validating against a built-in type");
24155 goto internal_error;
24156 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024157 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024158 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24159 else
24160 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24161 }
24162 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24163 /*
24164 * Check facets.
24165 */
24166 ret = xmlSchemaValidateFacets(actxt, node, type,
24167 (xmlSchemaValType) biType->builtInType, value, val,
24168 0, fireErrors);
24169 if (ret != 0) {
24170 if (ret < 0) {
24171 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24172 "validating facets of atomic simple type");
24173 goto internal_error;
24174 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024175 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024176 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24177 else
24178 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24179 }
24180 }
24181 if (fireErrors && (ret > 0))
24182 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024183 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024184
24185 xmlSchemaTypePtr itemType;
24186 const xmlChar *cur, *end;
24187 xmlChar *tmpValue = NULL;
24188 unsigned long len = 0;
24189 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24190 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24191 * of white space separated tokens, each of which ·match·es a literal
24192 * in the ·lexical space· of {item type definition}
24193 */
24194 /*
24195 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24196 * the list type has an enum or pattern facet.
24197 */
24198 NORMALIZE(type);
24199 /*
24200 * VAL TODO: Optimize validation of empty values.
24201 * VAL TODO: We do not have computed values for lists.
24202 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024203 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024204 cur = value;
24205 do {
24206 while (IS_BLANK_CH(*cur))
24207 cur++;
24208 end = cur;
24209 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24210 end++;
24211 if (end == cur)
24212 break;
24213 tmpValue = xmlStrndup(cur, end - cur);
24214 len++;
24215
24216 if (valNeeded)
24217 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24218 tmpValue, &curVal, fireErrors, 0, 1);
24219 else
24220 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24221 tmpValue, NULL, fireErrors, 0, 1);
24222 FREE_AND_NULL(tmpValue);
24223 if (curVal != NULL) {
24224 /*
24225 * Add to list of computed values.
24226 */
24227 if (val == NULL)
24228 val = curVal;
24229 else
24230 xmlSchemaValueAppend(prevVal, curVal);
24231 prevVal = curVal;
24232 curVal = NULL;
24233 }
24234 if (ret != 0) {
24235 if (ret < 0) {
24236 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24237 "validating an item of list simple type");
24238 goto internal_error;
24239 }
24240 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24241 break;
24242 }
24243 cur = end;
24244 } while (*cur != 0);
24245 FREE_AND_NULL(tmpValue);
24246 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24247 /*
24248 * Apply facets (pattern, enumeration).
24249 */
24250 ret = xmlSchemaValidateFacets(actxt, node, type,
24251 XML_SCHEMAS_UNKNOWN, value, val,
24252 len, fireErrors);
24253 if (ret != 0) {
24254 if (ret < 0) {
24255 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24256 "validating facets of list simple type");
24257 goto internal_error;
24258 }
24259 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24260 }
24261 }
24262 if (fireErrors && (ret > 0)) {
24263 /*
24264 * Report the normalized value.
24265 */
24266 normalize = 1;
24267 NORMALIZE(type);
24268 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24269 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024270 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024271 xmlSchemaTypeLinkPtr memberLink;
24272 /*
24273 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24274 * not apply directly; however, the normalization behavior of ·union·
24275 * types is controlled by the value of whiteSpace on that one of the
24276 * ·memberTypes· against which the ·union· is successfully validated.
24277 *
24278 * This means that the value is normalized by the first validating
24279 * member type, then the facets of the union type are applied. This
24280 * needs changing of the value!
24281 */
24282
24283 /*
24284 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24285 * literal in the ·lexical space· of at least one member of
24286 * {member type definitions}
24287 */
24288 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24289 if (memberLink == NULL) {
24290 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24291 "union simple type has no member types");
24292 goto internal_error;
24293 }
24294 /*
24295 * Always normalize union type values, since we currently
24296 * cannot store the whitespace information with the value
24297 * itself; otherwise a later value-comparison would be
24298 * not possible.
24299 */
24300 while (memberLink != NULL) {
24301 if (valNeeded)
24302 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24303 memberLink->type, value, &val, 0, 1, 0);
24304 else
24305 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24306 memberLink->type, value, NULL, 0, 1, 0);
24307 if (ret <= 0)
24308 break;
24309 memberLink = memberLink->next;
24310 }
24311 if (ret != 0) {
24312 if (ret < 0) {
24313 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24314 "validating members of union simple type");
24315 goto internal_error;
24316 }
24317 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24318 }
24319 /*
24320 * Apply facets (pattern, enumeration).
24321 */
24322 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24323 /*
24324 * The normalization behavior of ·union· types is controlled by
24325 * the value of whiteSpace on that one of the ·memberTypes·
24326 * against which the ·union· is successfully validated.
24327 */
24328 NORMALIZE(memberLink->type);
24329 ret = xmlSchemaValidateFacets(actxt, node, type,
24330 XML_SCHEMAS_UNKNOWN, value, val,
24331 0, fireErrors);
24332 if (ret != 0) {
24333 if (ret < 0) {
24334 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24335 "validating facets of union simple type");
24336 goto internal_error;
24337 }
24338 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24339 }
24340 }
24341 if (fireErrors && (ret > 0))
24342 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24343 }
24344
24345 if (normValue != NULL)
24346 xmlFree(normValue);
24347 if (ret == 0) {
24348 if (retVal != NULL)
24349 *retVal = val;
24350 else if (val != NULL)
24351 xmlSchemaFreeValue(val);
24352 } else if (val != NULL)
24353 xmlSchemaFreeValue(val);
24354 return (ret);
24355internal_error:
24356 if (normValue != NULL)
24357 xmlFree(normValue);
24358 if (val != NULL)
24359 xmlSchemaFreeValue(val);
24360 return (-1);
24361}
24362
24363static int
24364xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24365 const xmlChar *value,
24366 const xmlChar **nsName,
24367 const xmlChar **localName)
24368{
24369 int ret = 0;
24370
24371 if ((nsName == NULL) || (localName == NULL))
24372 return (-1);
24373 *nsName = NULL;
24374 *localName = NULL;
24375
24376 ret = xmlValidateQName(value, 1);
24377 if (ret == -1)
24378 return (-1);
24379 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024380 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024381 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24382 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24383 return (1);
24384 }
24385 {
24386 xmlChar *local = NULL;
24387 xmlChar *prefix;
24388
24389 /*
24390 * NOTE: xmlSplitQName2 will return a duplicated
24391 * string.
24392 */
24393 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024394 if (local == NULL)
24395 *localName = xmlDictLookup(vctxt->dict, value, -1);
24396 else {
24397 *localName = xmlDictLookup(vctxt->dict, local, -1);
24398 xmlFree(local);
24399 }
24400
24401 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24402
24403 if (prefix != NULL) {
24404 xmlFree(prefix);
24405 /*
24406 * A namespace must be found if the prefix is NOT NULL.
24407 */
24408 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024409 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024410 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024411 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024412 "The QName value '%s' has no "
24413 "corresponding namespace declaration in scope",
24414 value, NULL);
24415 return (2);
24416 }
24417 }
24418 }
24419 return (0);
24420}
24421
24422static int
24423xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24424 xmlSchemaAttrInfoPtr iattr,
24425 xmlSchemaTypePtr *localType,
24426 xmlSchemaElementPtr elemDecl)
24427{
24428 int ret = 0;
24429 /*
24430 * cvc-elt (3.3.4) : (4)
24431 * AND
24432 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24433 * (1.2.1.2.1) - (1.2.1.2.4)
24434 * Handle 'xsi:type'.
24435 */
24436 if (localType == NULL)
24437 return (-1);
24438 *localType = NULL;
24439 if (iattr == NULL)
24440 return (0);
24441 else {
24442 const xmlChar *nsName = NULL, *local = NULL;
24443 /*
24444 * TODO: We should report a *warning* that the type was overriden
24445 * by the instance.
24446 */
24447 ACTIVATE_ATTRIBUTE(iattr);
24448 /*
24449 * (cvc-elt) (3.3.4) : (4.1)
24450 * (cvc-assess-elt) (1.2.1.2.2)
24451 */
24452 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24453 &nsName, &local);
24454 if (ret != 0) {
24455 if (ret < 0) {
24456 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24457 "calling xmlSchemaQNameExpand() to validate the "
24458 "attribute 'xsi:type'");
24459 goto internal_error;
24460 }
24461 goto exit;
24462 }
24463 /*
24464 * (cvc-elt) (3.3.4) : (4.2)
24465 * (cvc-assess-elt) (1.2.1.2.3)
24466 */
24467 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24468 if (*localType == NULL) {
24469 xmlChar *str = NULL;
24470
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024471 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024472 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024473 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024474 "The QName value '%s' of the xsi:type attribute does not "
24475 "resolve to a type definition",
24476 xmlSchemaFormatQName(&str, nsName, local), NULL);
24477 FREE_AND_NULL(str);
24478 ret = vctxt->err;
24479 goto exit;
24480 }
24481 if (elemDecl != NULL) {
24482 int set = 0;
24483
24484 /*
24485 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24486 * "The ·local type definition· must be validly
24487 * derived from the {type definition} given the union of
24488 * the {disallowed substitutions} and the {type definition}'s
24489 * {prohibited substitutions}, as defined in
24490 * Type Derivation OK (Complex) (§3.4.6)
24491 * (if it is a complex type definition),
24492 * or given {disallowed substitutions} as defined in Type
24493 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24494 * definition)."
24495 *
24496 * {disallowed substitutions}: the "block" on the element decl.
24497 * {prohibited substitutions}: the "block" on the type def.
24498 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024499 /*
24500 * OPTIMIZE TODO: We could map types already evaluated
24501 * to be validly derived from other types to avoid checking
24502 * this over and over for the same types.
24503 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024504 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24505 (elemDecl->subtypes->flags &
24506 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24507 set |= SUBSET_EXTENSION;
24508
24509 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24510 (elemDecl->subtypes->flags &
24511 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24512 set |= SUBSET_RESTRICTION;
24513
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024514 /*
24515 * REMOVED and CHANGED since this produced a parser context
24516 * which adds to the string dict of the schema. So this would
24517 * change the schema and we don't want this. We don't need
24518 * the parser context anymore.
24519 *
24520 * if ((vctxt->pctxt == NULL) &&
24521 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24522 * return (-1);
24523 */
24524
24525 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024526 elemDecl->subtypes, set) != 0) {
24527 xmlChar *str = NULL;
24528
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024529 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024530 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24531 "The type definition '%s', specified by xsi:type, is "
24532 "blocked or not validly derived from the type definition "
24533 "of the element declaration",
24534 xmlSchemaFormatQName(&str,
24535 (*localType)->targetNamespace,
24536 (*localType)->name),
24537 NULL);
24538 FREE_AND_NULL(str);
24539 ret = vctxt->err;
24540 *localType = NULL;
24541 }
24542 }
24543 }
24544exit:
24545 ACTIVATE_ELEM;
24546 return (ret);
24547internal_error:
24548 ACTIVATE_ELEM;
24549 return (-1);
24550}
24551
24552static int
24553xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24554{
24555 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024556 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024557
24558 /*
24559 * cvc-elt (3.3.4) : 1
24560 */
24561 if (elemDecl == NULL) {
24562 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24563 "No matching declaration available");
24564 return (vctxt->err);
24565 }
24566 /*
24567 * cvc-elt (3.3.4) : 2
24568 */
24569 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24570 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24571 "The element declaration is abstract");
24572 return (vctxt->err);
24573 }
24574 if (actualType == NULL) {
24575 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24576 "The type definition is absent");
24577 return (XML_SCHEMAV_CVC_TYPE_1);
24578 }
24579 if (vctxt->nbAttrInfos != 0) {
24580 int ret;
24581 xmlSchemaAttrInfoPtr iattr;
24582 /*
24583 * cvc-elt (3.3.4) : 3
24584 * Handle 'xsi:nil'.
24585 */
24586 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24587 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24588 if (iattr) {
24589 ACTIVATE_ATTRIBUTE(iattr);
24590 /*
24591 * Validate the value.
24592 */
24593 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024594 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024595 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24596 iattr->value, &(iattr->val), 1, 0, 0);
24597 ACTIVATE_ELEM;
24598 if (ret < 0) {
24599 VERROR_INT("xmlSchemaValidateElemDecl",
24600 "calling xmlSchemaVCheckCVCSimpleType() to "
24601 "validate the attribute 'xsi:nil'");
24602 return (-1);
24603 }
24604 if (ret == 0) {
24605 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24606 /*
24607 * cvc-elt (3.3.4) : 3.1
24608 */
24609 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24610 "The element is not 'nillable'");
24611 /* Does not return an error on purpose. */
24612 } else {
24613 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24614 /*
24615 * cvc-elt (3.3.4) : 3.2.2
24616 */
24617 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24618 (elemDecl->value != NULL)) {
24619 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24620 "The element cannot be 'nilled' because "
24621 "there is a fixed value constraint defined "
24622 "for it");
24623 /* Does not return an error on purpose. */
24624 } else
24625 vctxt->inode->flags |=
24626 XML_SCHEMA_ELEM_INFO_NILLED;
24627 }
24628 }
24629 }
24630 }
24631 /*
24632 * cvc-elt (3.3.4) : 4
24633 * Handle 'xsi:type'.
24634 */
24635 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24636 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24637 if (iattr) {
24638 xmlSchemaTypePtr localType = NULL;
24639
24640 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24641 elemDecl);
24642 if (ret != 0) {
24643 if (ret == -1) {
24644 VERROR_INT("xmlSchemaValidateElemDecl",
24645 "calling xmlSchemaProcessXSIType() to "
24646 "process the attribute 'xsi:type'");
24647 return (-1);
24648 }
24649 /* Does not return an error on purpose. */
24650 }
24651 if (localType != NULL) {
24652 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24653 actualType = localType;
24654 }
24655 }
24656 }
24657 /*
24658 * IDC: Register identity-constraint XPath matchers.
24659 */
24660 if ((elemDecl->idcs != NULL) &&
24661 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24662 return (-1);
24663 /*
24664 * No actual type definition.
24665 */
24666 if (actualType == NULL) {
24667 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24668 "The type definition is absent");
24669 return (XML_SCHEMAV_CVC_TYPE_1);
24670 }
24671 /*
24672 * Remember the actual type definition.
24673 */
24674 vctxt->inode->typeDef = actualType;
24675
24676 return (0);
24677}
24678
24679static int
24680xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24681{
24682 xmlSchemaAttrInfoPtr iattr;
24683 int ret = 0, i;
24684
24685 /*
24686 * SPEC cvc-type (3.1.1)
24687 * "The attributes of must be empty, excepting those whose namespace
24688 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24689 * whose local name is one of type, nil, schemaLocation or
24690 * noNamespaceSchemaLocation."
24691 */
24692 if (vctxt->nbAttrInfos == 0)
24693 return (0);
24694 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24695 iattr = vctxt->attrInfos[i];
24696 if (! iattr->metaType) {
24697 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024698 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024699 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24700 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24701 }
24702 }
24703 ACTIVATE_ELEM
24704 return (ret);
24705}
24706
24707/*
24708* Cleanup currently used attribute infos.
24709*/
24710static void
24711xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24712{
24713 int i;
24714 xmlSchemaAttrInfoPtr attr;
24715
24716 if (vctxt->nbAttrInfos == 0)
24717 return;
24718 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24719 attr = vctxt->attrInfos[i];
24720 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24721 if (attr->localName != NULL)
24722 xmlFree((xmlChar *) attr->localName);
24723 if (attr->nsName != NULL)
24724 xmlFree((xmlChar *) attr->nsName);
24725 }
24726 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24727 if (attr->value != NULL)
24728 xmlFree((xmlChar *) attr->value);
24729 }
24730 if (attr->val != NULL) {
24731 xmlSchemaFreeValue(attr->val);
24732 attr->val = NULL;
24733 }
24734 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24735 }
24736 vctxt->nbAttrInfos = 0;
24737}
24738
24739/*
24740* 3.4.4 Complex Type Definition Validation Rules
24741* Element Locally Valid (Complex Type) (cvc-complex-type)
24742* 3.2.4 Attribute Declaration Validation Rules
24743* Validation Rule: Attribute Locally Valid (cvc-attribute)
24744* Attribute Locally Valid (Use) (cvc-au)
24745*
24746* Only "assessed" attribute information items will be visible to
24747* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24748*/
24749static int
24750xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24751{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024752 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24753 xmlSchemaItemListPtr attrUseList;
24754 xmlSchemaAttributeUsePtr attrUse = NULL;
24755 xmlSchemaAttributePtr attrDecl = NULL;
24756 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24757 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024758 int xpathRes = 0, res, wildIDs = 0, fixed;
24759
24760 /*
24761 * SPEC (cvc-attribute)
24762 * (1) "The declaration must not be ·absent· (see Missing
24763 * Sub-components (§5.3) for how this can fail to be
24764 * the case)."
24765 * (2) "Its {type definition} must not be absent."
24766 *
24767 * NOTE (1) + (2): This is not handled here, since we currently do not
24768 * allow validation against schemas which have missing sub-components.
24769 *
24770 * SPEC (cvc-complex-type)
24771 * (3) "For each attribute information item in the element information
24772 * item's [attributes] excepting those whose [namespace name] is
24773 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24774 * [local name] is one of type, nil, schemaLocation or
24775 * noNamespaceSchemaLocation, the appropriate case among the following
24776 * must be true:
24777 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024778 */
24779 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24780 /*
24781 * @nbAttrs is the number of attributes present in the instance.
24782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024783 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024784 if (attrUseList != NULL)
24785 nbUses = attrUseList->nbItems;
24786 else
24787 nbUses = 0;
24788 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024789 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024790 attrUse = attrUseList->items[i];
24791 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24792 for (j = 0; j < nbAttrs; j++) {
24793 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024794 /*
24795 * SPEC (cvc-complex-type) (3)
24796 * Skip meta attributes.
24797 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024798 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024799 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024800 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024801 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024802 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024803 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024804 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 continue;
24806 found = 1;
24807 /*
24808 * SPEC (cvc-complex-type)
24809 * (3.1) "If there is among the {attribute uses} an attribute
24810 * use with an {attribute declaration} whose {name} matches
24811 * the attribute information item's [local name] and whose
24812 * {target namespace} is identical to the attribute information
24813 * item's [namespace name] (where an ·absent· {target namespace}
24814 * is taken to be identical to a [namespace name] with no value),
24815 * then the attribute information must be ·valid· with respect
24816 * to that attribute use as per Attribute Locally Valid (Use)
24817 * (§3.5.4). In this case the {attribute declaration} of that
24818 * attribute use is the ·context-determined declaration· for the
24819 * attribute information item with respect to Schema-Validity
24820 * Assessment (Attribute) (§3.2.4) and
24821 * Assessment Outcome (Attribute) (§3.2.5).
24822 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024823 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24824 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024825 /*
24826 * Context-determined declaration.
24827 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024828 iattr->decl = attrDecl;
24829 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024830 break;
24831 }
24832
24833 if (found)
24834 continue;
24835
24836 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24837 /*
24838 * Handle non-existent, required attributes.
24839 *
24840 * SPEC (cvc-complex-type)
24841 * (4) "The {attribute declaration} of each attribute use in
24842 * the {attribute uses} whose {required} is true matches one
24843 * of the attribute information items in the element information
24844 * item's [attributes] as per clause 3.1 above."
24845 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024846 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24847 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024848 VERROR_INT(
24849 "xmlSchemaVAttributesComplex",
24850 "calling xmlSchemaGetFreshAttrInfo()");
24851 return (-1);
24852 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024853 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24854 tmpiattr->use = attrUse;
24855 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024856 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24857 ((attrUse->defValue != NULL) ||
24858 (attrDecl->defValue != NULL))) {
24859 /*
24860 * Handle non-existent, optional, default/fixed attributes.
24861 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024862 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24863 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024864 VERROR_INT(
24865 "xmlSchemaVAttributesComplex",
24866 "calling xmlSchemaGetFreshAttrInfo()");
24867 return (-1);
24868 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024869 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24870 tmpiattr->use = attrUse;
24871 tmpiattr->decl = attrDecl;
24872 tmpiattr->typeDef = attrDecl->subtypes;
24873 tmpiattr->localName = attrDecl->name;
24874 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024875 }
24876 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024877
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024878 if (vctxt->nbAttrInfos == 0)
24879 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024880 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024881 /*
24882 * Validate against the wildcard.
24883 */
24884 if (type->attributeWildcard != NULL) {
24885 /*
24886 * SPEC (cvc-complex-type)
24887 * (3.2.1) "There must be an {attribute wildcard}."
24888 */
24889 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024890 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024891 /*
24892 * SPEC (cvc-complex-type) (3)
24893 * Skip meta attributes.
24894 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024895 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024896 continue;
24897 /*
24898 * SPEC (cvc-complex-type)
24899 * (3.2.2) "The attribute information item must be ·valid· with
24900 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24901 *
24902 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24903 * "... its [namespace name] must be ·valid· with respect to
24904 * the wildcard constraint, as defined in Wildcard allows
24905 * Namespace Name (§3.10.4)."
24906 */
24907 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024908 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024909 /*
24910 * Handle processContents.
24911 *
24912 * SPEC (cvc-wildcard):
24913 * processContents | context-determined declaration:
24914 * "strict" "mustFind"
24915 * "lax" "none"
24916 * "skip" "skip"
24917 */
24918 if (type->attributeWildcard->processContents ==
24919 XML_SCHEMAS_ANY_SKIP) {
24920 /*
24921 * context-determined declaration = "skip"
24922 *
24923 * SPEC PSVI Assessment Outcome (Attribute)
24924 * [validity] = "notKnown"
24925 * [validation attempted] = "none"
24926 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024927 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024928 continue;
24929 }
24930 /*
24931 * Find an attribute declaration.
24932 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024933 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24934 iattr->localName, iattr->nsName);
24935 if (iattr->decl != NULL) {
24936 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024937 /*
24938 * SPEC (cvc-complex-type)
24939 * (5) "Let [Definition:] the wild IDs be the set of
24940 * all attribute information item to which clause 3.2
24941 * applied and whose ·validation· resulted in a
24942 * ·context-determined declaration· of mustFind or no
24943 * ·context-determined declaration· at all, and whose
24944 * [local name] and [namespace name] resolve (as
24945 * defined by QName resolution (Instance) (§3.15.4)) to
24946 * an attribute declaration whose {type definition} is
24947 * or is derived from ID. Then all of the following
24948 * must be true:"
24949 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024950 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024951 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024952 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024953 /*
24954 * SPEC (5.1) "There must be no more than one
24955 * item in ·wild IDs·."
24956 */
24957 if (wildIDs != 0) {
24958 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024959 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024960 TODO
24961 continue;
24962 }
24963 wildIDs++;
24964 /*
24965 * SPEC (cvc-complex-type)
24966 * (5.2) "If ·wild IDs· is non-empty, there must not
24967 * be any attribute uses among the {attribute uses}
24968 * whose {attribute declaration}'s {type definition}
24969 * is or is derived from ID."
24970 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024971 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024972 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024973 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024974 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024975 /* URGENT VAL TODO: implement */
24976 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024977 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024978 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024979 }
24980 }
24981 }
24982 } else if (type->attributeWildcard->processContents ==
24983 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024984 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024985 /*
24986 * SPEC PSVI Assessment Outcome (Attribute)
24987 * [validity] = "notKnown"
24988 * [validation attempted] = "none"
24989 */
24990 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024991 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024992 }
24993 }
24994 }
24995 }
24996
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024997 if (vctxt->nbAttrInfos == 0)
24998 return (0);
24999
25000 /*
25001 * Validate values, create default attributes, evaluate IDCs.
25002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025003 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025004 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025005 /*
25006 * VAL TODO: Note that we won't try to resolve IDCs to
25007 * "lax" and "skip" validated attributes. Check what to
25008 * do in this case.
25009 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025010 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25011 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025012 continue;
25013 /*
25014 * VAL TODO: What to do if the type definition is missing?
25015 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025016 if (iattr->typeDef == NULL) {
25017 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025018 continue;
25019 }
25020
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025021 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025022 fixed = 0;
25023 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025024
25025 if (vctxt->xpathStates != NULL) {
25026 /*
25027 * Evaluate IDCs.
25028 */
25029 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25030 XML_ATTRIBUTE_NODE);
25031 if (xpathRes == -1) {
25032 VERROR_INT("xmlSchemaVAttributesComplex",
25033 "calling xmlSchemaXPathEvaluate()");
25034 goto internal_error;
25035 }
25036 }
25037
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025038 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025039 /*
25040 * Default/fixed attributes.
25041 */
25042 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025043 if (iattr->use->defValue != NULL) {
25044 iattr->value = (xmlChar *) iattr->use->defValue;
25045 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025046 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025047 iattr->value = (xmlChar *) iattr->decl->defValue;
25048 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025049 }
25050 /*
25051 * IDCs will consume the precomputed default value,
25052 * so we need to clone it.
25053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025054 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025055 VERROR_INT("xmlSchemaVAttributesComplex",
25056 "default/fixed value on an attribute use was "
25057 "not precomputed");
25058 goto internal_error;
25059 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025060 iattr->val = xmlSchemaCopyValue(iattr->val);
25061 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025062 VERROR_INT("xmlSchemaVAttributesComplex",
25063 "calling xmlSchemaCopyValue()");
25064 goto internal_error;
25065 }
25066 }
25067 /*
25068 * PSVI: Add the default attribute to the current element.
25069 * VAL TODO: Should we use the *normalized* value? This currently
25070 * uses the *initial* value.
25071 */
25072 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025073 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025074 xmlChar *normValue;
25075 const xmlChar *value;
25076
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025077 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025078 /*
25079 * Normalize the value.
25080 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025081 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25082 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025083 if (normValue != NULL)
25084 value = BAD_CAST normValue;
25085
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025086 if (iattr->nsName == NULL) {
25087 if (xmlNewProp(iattr->node->parent,
25088 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025089 VERROR_INT("xmlSchemaVAttributesComplex",
25090 "callling xmlNewProp()");
25091 if (normValue != NULL)
25092 xmlFree(normValue);
25093 goto internal_error;
25094 }
25095 } else {
25096 xmlNsPtr ns;
25097
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025098 ns = xmlSearchNsByHref(iattr->node->doc,
25099 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025100 if (ns == NULL) {
25101 xmlChar prefix[12];
25102 int counter = 0;
25103
25104 /*
25105 * Create a namespace declaration on the validation
25106 * root node if no namespace declaration is in scope.
25107 */
25108 do {
25109 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025110 ns = xmlSearchNs(iattr->node->doc,
25111 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025112 if (counter > 1000) {
25113 VERROR_INT(
25114 "xmlSchemaVAttributesComplex",
25115 "could not compute a ns prefix for a "
25116 "default/fixed attribute");
25117 if (normValue != NULL)
25118 xmlFree(normValue);
25119 goto internal_error;
25120 }
25121 } while (ns != NULL);
25122 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025123 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025124 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025125 /*
25126 * TODO:
25127 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25128 * If we have QNames: do we need to ensure there's a
25129 * prefix defined for the QName?
25130 */
25131 xmlNewNsProp(iattr->node->parent, ns,
25132 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025133 }
25134 if (normValue != NULL)
25135 xmlFree(normValue);
25136 }
25137 /*
25138 * Go directly to IDC evaluation.
25139 */
25140 goto eval_idcs;
25141 }
25142 /*
25143 * Validate the value.
25144 */
25145 if (vctxt->value != NULL) {
25146 /*
25147 * Free last computed value; just for safety reasons.
25148 */
25149 xmlSchemaFreeValue(vctxt->value);
25150 vctxt->value = NULL;
25151 }
25152 /*
25153 * Note that the attribute *use* can be unavailable, if
25154 * the attribute was a wild attribute.
25155 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025156 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25157 ((iattr->use != NULL) &&
25158 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025159 fixed = 1;
25160 else
25161 fixed = 0;
25162 /*
25163 * SPEC (cvc-attribute)
25164 * (3) "The item's ·normalized value· must be locally ·valid·
25165 * with respect to that {type definition} as per
25166 * String Valid (§3.14.4)."
25167 *
25168 * VAL TODO: Do we already have the
25169 * "normalized attribute value" here?
25170 */
25171 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025172 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025173 /*
25174 * Request a computed value.
25175 */
25176 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025177 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025178 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025179 1, 1, 0);
25180 } else {
25181 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025182 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025183 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025184 1, 0, 0);
25185 }
25186
25187 if (res != 0) {
25188 if (res == -1) {
25189 VERROR_INT("xmlSchemaVAttributesComplex",
25190 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25191 goto internal_error;
25192 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025193 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025194 /*
25195 * SPEC PSVI Assessment Outcome (Attribute)
25196 * [validity] = "invalid"
25197 */
25198 goto eval_idcs;
25199 }
25200
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025201 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025202 /*
25203 * SPEC Attribute Locally Valid (Use) (cvc-au)
25204 * "For an attribute information item to be·valid·
25205 * with respect to an attribute use its *normalized*
25206 * value· must match the *canonical* lexical
25207 * representation of the attribute use's {value
25208 * constraint}value, if it is present and fixed."
25209 *
25210 * VAL TODO: The requirement for the *canonical* value
25211 * will be removed in XML Schema 1.1.
25212 */
25213 /*
25214 * SPEC Attribute Locally Valid (cvc-attribute)
25215 * (4) "The item's *actual* value· must match the *value* of
25216 * the {value constraint}, if it is present and fixed."
25217 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025218 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025219 /* VAL TODO: A value was not precomputed. */
25220 TODO
25221 goto eval_idcs;
25222 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025223 if ((iattr->use != NULL) &&
25224 (iattr->use->defValue != NULL)) {
25225 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025226 /* VAL TODO: A default value was not precomputed. */
25227 TODO
25228 goto eval_idcs;
25229 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025230 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025231 /*
25232 if (xmlSchemaCompareValuesWhtsp(attr->val,
25233 (xmlSchemaWhitespaceValueType) ws,
25234 attr->use->defVal,
25235 (xmlSchemaWhitespaceValueType) ws) != 0) {
25236 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025237 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25238 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025239 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025240 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025241 /* VAL TODO: A default value was not precomputed. */
25242 TODO
25243 goto eval_idcs;
25244 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025245 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025246 /*
25247 if (xmlSchemaCompareValuesWhtsp(attr->val,
25248 (xmlSchemaWhitespaceValueType) ws,
25249 attrDecl->defVal,
25250 (xmlSchemaWhitespaceValueType) ws) != 0) {
25251 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025252 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25253 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025254 }
25255 /*
25256 * [validity] = "valid"
25257 */
25258 }
25259eval_idcs:
25260 /*
25261 * Evaluate IDCs.
25262 */
25263 if (xpathRes) {
25264 if (xmlSchemaXPathProcessHistory(vctxt,
25265 vctxt->depth +1) == -1) {
25266 VERROR_INT("xmlSchemaVAttributesComplex",
25267 "calling xmlSchemaXPathEvaluate()");
25268 goto internal_error;
25269 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025270 } else if (vctxt->xpathStates != NULL)
25271 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025272 }
25273
25274 /*
25275 * Report errors.
25276 */
25277 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025278 iattr = vctxt->attrInfos[i];
25279 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25280 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25281 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25282 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025283 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025284 ACTIVATE_ATTRIBUTE(iattr);
25285 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025286 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25287 xmlChar *str = NULL;
25288 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025289 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025290 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25291 "The attribute '%s' is required but missing",
25292 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025293 iattr->decl->targetNamespace,
25294 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025295 NULL);
25296 FREE_AND_NULL(str)
25297 break;
25298 }
25299 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25300 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25301 "The type definition is absent");
25302 break;
25303 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025304 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025305 XML_SCHEMAV_CVC_AU, NULL, NULL,
25306 "The value '%s' does not match the fixed "
25307 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025308 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025309 break;
25310 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25311 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25312 "No matching global attribute declaration available, but "
25313 "demanded by the strict wildcard");
25314 break;
25315 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025316 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025317 break;
25318 /*
25319 * MAYBE VAL TODO: One might report different error messages
25320 * for the following errors.
25321 */
25322 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025323 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025324 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025325 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025326 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025327 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025328 }
25329 break;
25330 default:
25331 break;
25332 }
25333 }
25334
25335 ACTIVATE_ELEM;
25336 return (0);
25337internal_error:
25338 ACTIVATE_ELEM;
25339 return (-1);
25340}
25341
25342static int
25343xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25344 int *skip)
25345{
25346 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25347 /*
25348 * The namespace of the element was already identified to be
25349 * matching the wildcard.
25350 */
25351 if ((skip == NULL) || (wild == NULL) ||
25352 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25353 VERROR_INT("xmlSchemaValidateElemWildcard",
25354 "bad arguments");
25355 return (-1);
25356 }
25357 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025358 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25359 /*
25360 * URGENT VAL TODO: Either we need to position the stream to the
25361 * next sibling, or walk the whole subtree.
25362 */
25363 *skip = 1;
25364 return (0);
25365 }
25366 {
25367 xmlSchemaElementPtr decl = NULL;
25368
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025369 decl = xmlSchemaGetElem(vctxt->schema,
25370 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025371 if (decl != NULL) {
25372 vctxt->inode->decl = decl;
25373 return (0);
25374 }
25375 }
25376 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25377 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025378 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025379 "No matching global element declaration available, but "
25380 "demanded by the strict wildcard");
25381 return (vctxt->err);
25382 }
25383 if (vctxt->nbAttrInfos != 0) {
25384 xmlSchemaAttrInfoPtr iattr;
25385 /*
25386 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25387 * (1.2.1.2.1) - (1.2.1.2.3 )
25388 *
25389 * Use the xsi:type attribute for the type definition.
25390 */
25391 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25392 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25393 if (iattr != NULL) {
25394 if (xmlSchemaProcessXSIType(vctxt, iattr,
25395 &(vctxt->inode->typeDef), NULL) == -1) {
25396 VERROR_INT("xmlSchemaValidateElemWildcard",
25397 "calling xmlSchemaProcessXSIType() to "
25398 "process the attribute 'xsi:nil'");
25399 return (-1);
25400 }
25401 /*
25402 * Don't return an error on purpose.
25403 */
25404 return (0);
25405 }
25406 }
25407 /*
25408 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25409 *
25410 * Fallback to "anyType".
25411 */
25412 vctxt->inode->typeDef =
25413 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25414 return (0);
25415}
25416
25417/*
25418* xmlSchemaCheckCOSValidDefault:
25419*
25420* This will be called if: not nilled, no content and a default/fixed
25421* value is provided.
25422*/
25423
25424static int
25425xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25426 const xmlChar *value,
25427 xmlSchemaValPtr *val)
25428{
25429 int ret = 0;
25430 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25431
25432 /*
25433 * cos-valid-default:
25434 * Schema Component Constraint: Element Default Valid (Immediate)
25435 * For a string to be a valid default with respect to a type
25436 * definition the appropriate case among the following must be true:
25437 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025438 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025439 /*
25440 * Complex type.
25441 *
25442 * SPEC (2.1) "its {content type} must be a simple type definition
25443 * or mixed."
25444 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25445 * type}'s particle must be ·emptiable· as defined by
25446 * Particle Emptiable (§3.9.6)."
25447 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025448 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25449 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25450 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025451 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25452 /* NOTE that this covers (2.2.2) as well. */
25453 VERROR(ret, NULL,
25454 "For a string to be a valid default, the type definition "
25455 "must be a simple type or a complex type with simple content "
25456 "or mixed content and a particle emptiable");
25457 return(ret);
25458 }
25459 }
25460 /*
25461 * 1 If the type definition is a simple type definition, then the string
25462 * must be ·valid· with respect to that definition as defined by String
25463 * Valid (§3.14.4).
25464 *
25465 * AND
25466 *
25467 * 2.2.1 If the {content type} is a simple type definition, then the
25468 * string must be ·valid· with respect to that simple type definition
25469 * as defined by String Valid (§3.14.4).
25470 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025471 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025472
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025473 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025474 NULL, inode->typeDef, value, val, 1, 1, 0);
25475
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025476 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025477
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025478 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025479 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25480 }
25481 if (ret < 0) {
25482 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25483 "calling xmlSchemaVCheckCVCSimpleType()");
25484 }
25485 return (ret);
25486}
25487
25488static void
25489xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25490 const xmlChar * name ATTRIBUTE_UNUSED,
25491 xmlSchemaElementPtr item,
25492 xmlSchemaNodeInfoPtr inode)
25493{
25494 inode->decl = item;
25495#ifdef DEBUG_CONTENT
25496 {
25497 xmlChar *str = NULL;
25498
25499 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25500 xmlGenericError(xmlGenericErrorContext,
25501 "AUTOMATON callback for '%s' [declaration]\n",
25502 xmlSchemaFormatQName(&str,
25503 inode->localName, inode->nsName));
25504 } else {
25505 xmlGenericError(xmlGenericErrorContext,
25506 "AUTOMATON callback for '%s' [wildcard]\n",
25507 xmlSchemaFormatQName(&str,
25508 inode->localName, inode->nsName));
25509
25510 }
25511 FREE_AND_NULL(str)
25512 }
25513#endif
25514}
25515
25516static int
25517xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025518{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025519 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25520 if (vctxt->inode == NULL) {
25521 VERROR_INT("xmlSchemaValidatorPushElem",
25522 "calling xmlSchemaGetFreshElemInfo()");
25523 return (-1);
25524 }
25525 vctxt->nbAttrInfos = 0;
25526 return (0);
25527}
25528
25529static int
25530xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25531 xmlSchemaNodeInfoPtr inode,
25532 xmlSchemaTypePtr type,
25533 const xmlChar *value)
25534{
25535 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25536 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025537 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025538 type, value, &(inode->val), 1, 1, 0));
25539 else
25540 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025541 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025542 type, value, NULL, 1, 0, 0));
25543}
25544
25545
25546
25547/*
25548* Process END of element.
25549*/
25550static int
25551xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25552{
25553 int ret = 0;
25554 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25555
25556 if (vctxt->nbAttrInfos != 0)
25557 xmlSchemaClearAttrInfos(vctxt);
25558 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25559 /*
25560 * This element was not expected;
25561 * we will not validate child elements of broken parents.
25562 * Skip validation of all content of the parent.
25563 */
25564 vctxt->skipDepth = vctxt->depth -1;
25565 goto end_elem;
25566 }
25567 if ((inode->typeDef == NULL) ||
25568 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25569 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025570 * 1. the type definition might be missing if the element was
25571 * error prone
25572 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025573 */
25574 goto end_elem;
25575 }
25576 /*
25577 * Check the content model.
25578 */
25579 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25580 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25581
25582 /*
25583 * Workaround for "anyType".
25584 */
25585 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25586 goto character_content;
25587
25588 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25589 xmlChar *values[10];
25590 int terminal, nbval = 10, nbneg;
25591
25592 if (inode->regexCtxt == NULL) {
25593 /*
25594 * Create the regex context.
25595 */
25596 inode->regexCtxt =
25597 xmlRegNewExecCtxt(inode->typeDef->contModel,
25598 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25599 vctxt);
25600 if (inode->regexCtxt == NULL) {
25601 VERROR_INT("xmlSchemaValidatorPopElem",
25602 "failed to create a regex context");
25603 goto internal_error;
25604 }
25605#ifdef DEBUG_AUTOMATA
25606 xmlGenericError(xmlGenericErrorContext,
25607 "AUTOMATON create on '%s'\n", inode->localName);
25608#endif
25609 }
25610 /*
25611 * Get hold of the still expected content, since a further
25612 * call to xmlRegExecPushString() will loose this information.
25613 */
25614 xmlRegExecNextValues(inode->regexCtxt,
25615 &nbval, &nbneg, &values[0], &terminal);
25616 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25617 if (ret <= 0) {
25618 /*
25619 * Still missing something.
25620 */
25621 ret = 1;
25622 inode->flags |=
25623 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025624 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025625 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25626 "Missing child element(s)",
25627 nbval, nbneg, values);
25628#ifdef DEBUG_AUTOMATA
25629 xmlGenericError(xmlGenericErrorContext,
25630 "AUTOMATON missing ERROR on '%s'\n",
25631 inode->localName);
25632#endif
25633 } else {
25634 /*
25635 * Content model is satisfied.
25636 */
25637 ret = 0;
25638#ifdef DEBUG_AUTOMATA
25639 xmlGenericError(xmlGenericErrorContext,
25640 "AUTOMATON succeeded on '%s'\n",
25641 inode->localName);
25642#endif
25643 }
25644
25645 }
25646 }
25647 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25648 goto end_elem;
25649
25650character_content:
25651
25652 if (vctxt->value != NULL) {
25653 xmlSchemaFreeValue(vctxt->value);
25654 vctxt->value = NULL;
25655 }
25656 /*
25657 * Check character content.
25658 */
25659 if (inode->decl == NULL) {
25660 /*
25661 * Speedup if no declaration exists.
25662 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025663 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025664 ret = xmlSchemaVCheckINodeDataType(vctxt,
25665 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025666 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025667 ret = xmlSchemaVCheckINodeDataType(vctxt,
25668 inode, inode->typeDef->contentTypeDef,
25669 inode->value);
25670 }
25671 if (ret < 0) {
25672 VERROR_INT("xmlSchemaValidatorPopElem",
25673 "calling xmlSchemaVCheckCVCSimpleType()");
25674 goto internal_error;
25675 }
25676 goto end_elem;
25677 }
25678 /*
25679 * cvc-elt (3.3.4) : 5
25680 * The appropriate case among the following must be true:
25681 */
25682 /*
25683 * cvc-elt (3.3.4) : 5.1
25684 * If the declaration has a {value constraint},
25685 * the item has neither element nor character [children] and
25686 * clause 3.2 has not applied, then all of the following must be true:
25687 */
25688 if ((inode->decl->value != NULL) &&
25689 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25690 (! INODE_NILLED(inode))) {
25691 /*
25692 * cvc-elt (3.3.4) : 5.1.1
25693 * If the ·actual type definition· is a ·local type definition·
25694 * then the canonical lexical representation of the {value constraint}
25695 * value must be a valid default for the ·actual type definition· as
25696 * defined in Element Default Valid (Immediate) (§3.3.6).
25697 */
25698 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025699 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025700 * NOTE: Although the *canonical* value is stated, it is not
25701 * relevant if canonical or not. Additionally XML Schema 1.1
25702 * will removed this requirement as well.
25703 */
25704 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25705
25706 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25707 inode->decl->value, &(inode->val));
25708 if (ret != 0) {
25709 if (ret < 0) {
25710 VERROR_INT("xmlSchemaValidatorPopElem",
25711 "calling xmlSchemaCheckCOSValidDefault()");
25712 goto internal_error;
25713 }
25714 goto end_elem;
25715 }
25716 /*
25717 * Stop here, to avoid redundant validation of the value
25718 * (see following).
25719 */
25720 goto default_psvi;
25721 }
25722 /*
25723 * cvc-elt (3.3.4) : 5.1.2
25724 * The element information item with the canonical lexical
25725 * representation of the {value constraint} value used as its
25726 * ·normalized value· must be ·valid· with respect to the
25727 * ·actual type definition· as defined by Element Locally Valid (Type)
25728 * (§3.3.4).
25729 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025730 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025731 ret = xmlSchemaVCheckINodeDataType(vctxt,
25732 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025733 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025734 ret = xmlSchemaVCheckINodeDataType(vctxt,
25735 inode, inode->typeDef->contentTypeDef,
25736 inode->decl->value);
25737 }
25738 if (ret != 0) {
25739 if (ret < 0) {
25740 VERROR_INT("xmlSchemaValidatorPopElem",
25741 "calling xmlSchemaVCheckCVCSimpleType()");
25742 goto internal_error;
25743 }
25744 goto end_elem;
25745 }
25746
25747default_psvi:
25748 /*
25749 * PSVI: Create a text node on the instance element.
25750 */
25751 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25752 (inode->node != NULL)) {
25753 xmlNodePtr textChild;
25754 xmlChar *normValue;
25755 /*
25756 * VAL TODO: Normalize the value.
25757 */
25758 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25759 inode->decl->value);
25760 if (normValue != NULL) {
25761 textChild = xmlNewText(BAD_CAST normValue);
25762 xmlFree(normValue);
25763 } else
25764 textChild = xmlNewText(inode->decl->value);
25765 if (textChild == NULL) {
25766 VERROR_INT("xmlSchemaValidatorPopElem",
25767 "calling xmlNewText()");
25768 goto internal_error;
25769 } else
25770 xmlAddChild(inode->node, textChild);
25771 }
25772
25773 } else if (! INODE_NILLED(inode)) {
25774 /*
25775 * 5.2.1 The element information item must be ·valid· with respect
25776 * to the ·actual type definition· as defined by Element Locally
25777 * Valid (Type) (§3.3.4).
25778 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025779 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025780 /*
25781 * SPEC (cvc-type) (3.1)
25782 * "If the type definition is a simple type definition, ..."
25783 * (3.1.3) "If clause 3.2 of Element Locally Valid
25784 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25785 * must be ·valid· with respect to the type definition as defined
25786 * by String Valid (§3.14.4).
25787 */
25788 ret = xmlSchemaVCheckINodeDataType(vctxt,
25789 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025790 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025791 /*
25792 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25793 * definition, then the element information item must be
25794 * ·valid· with respect to the type definition as per
25795 * Element Locally Valid (Complex Type) (§3.4.4);"
25796 *
25797 * SPEC (cvc-complex-type) (2.2)
25798 * "If the {content type} is a simple type definition, ...
25799 * the ·normalized value· of the element information item is
25800 * ·valid· with respect to that simple type definition as
25801 * defined by String Valid (§3.14.4)."
25802 */
25803 ret = xmlSchemaVCheckINodeDataType(vctxt,
25804 inode, inode->typeDef->contentTypeDef, inode->value);
25805 }
25806 if (ret != 0) {
25807 if (ret < 0) {
25808 VERROR_INT("xmlSchemaValidatorPopElem",
25809 "calling xmlSchemaVCheckCVCSimpleType()");
25810 goto internal_error;
25811 }
25812 goto end_elem;
25813 }
25814 /*
25815 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25816 * not applied, all of the following must be true:
25817 */
25818 if ((inode->decl->value != NULL) &&
25819 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25820
25821 /*
25822 * TODO: We will need a computed value, when comparison is
25823 * done on computed values.
25824 */
25825 /*
25826 * 5.2.2.1 The element information item must have no element
25827 * information item [children].
25828 */
25829 if (inode->flags &
25830 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25831 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25832 VERROR(ret, NULL,
25833 "The content must not containt element nodes since "
25834 "there is a fixed value constraint");
25835 goto end_elem;
25836 } else {
25837 /*
25838 * 5.2.2.2 The appropriate case among the following must
25839 * be true:
25840 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025841 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025842 /*
25843 * 5.2.2.2.1 If the {content type} of the ·actual type
25844 * definition· is mixed, then the *initial value* of the
25845 * item must match the canonical lexical representation
25846 * of the {value constraint} value.
25847 *
25848 * ... the *initial value* of an element information
25849 * item is the string composed of, in order, the
25850 * [character code] of each character information item in
25851 * the [children] of that element information item.
25852 */
25853 if (! xmlStrEqual(inode->value, inode->decl->value)){
25854 /*
25855 * VAL TODO: Report invalid & expected values as well.
25856 * VAL TODO: Implement the canonical stuff.
25857 */
25858 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025859 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025860 ret, NULL, NULL,
25861 "The initial value '%s' does not match the fixed "
25862 "value constraint '%s'",
25863 inode->value, inode->decl->value);
25864 goto end_elem;
25865 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025866 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025867 /*
25868 * 5.2.2.2.2 If the {content type} of the ·actual type
25869 * definition· is a simple type definition, then the
25870 * *actual value* of the item must match the canonical
25871 * lexical representation of the {value constraint} value.
25872 */
25873 /*
25874 * VAL TODO: *actual value* is the normalized value, impl.
25875 * this.
25876 * VAL TODO: Report invalid & expected values as well.
25877 * VAL TODO: Implement a comparison with the computed values.
25878 */
25879 if (! xmlStrEqual(inode->value,
25880 inode->decl->value)) {
25881 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025882 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025883 ret, NULL, NULL,
25884 "The actual value '%s' does not match the fixed "
25885 "value constraint '%s'",
25886 inode->value,
25887 inode->decl->value);
25888 goto end_elem;
25889 }
25890 }
25891 }
25892 }
25893 }
25894
25895end_elem:
25896 if (vctxt->depth < 0) {
25897 /* TODO: raise error? */
25898 return (0);
25899 }
25900 if (vctxt->depth == vctxt->skipDepth)
25901 vctxt->skipDepth = -1;
25902 /*
25903 * Evaluate the history of XPath state objects.
25904 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025905 if (inode->appliedXPath &&
25906 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025907 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025908 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025909 * MAYBE TODO:
25910 * SPEC (6) "The element information item must be ·valid· with
25911 * respect to each of the {identity-constraint definitions} as per
25912 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025913 */
25914 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025915 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25916 * need to be built in any case.
25917 * We will currently build IDC node-tables and bubble them only if
25918 * keyrefs do exist.
25919 */
25920
25921 /*
25922 * Add the current IDC target-nodes to the IDC node-tables.
25923 */
25924 if ((inode->idcMatchers != NULL) &&
25925 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25926 {
25927 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25928 goto internal_error;
25929 }
25930 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025931 * Validate IDC keyrefs.
25932 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025933 if (vctxt->inode->hasKeyrefs)
25934 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25935 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025936 /*
25937 * Merge/free the IDC table.
25938 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025939 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025940#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025941 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025942 inode->nsName,
25943 inode->localName,
25944 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025945#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025946 if ((vctxt->depth > 0) &&
25947 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25948 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025949 /*
25950 * Merge the IDC node table with the table of the parent node.
25951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025952 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25953 goto internal_error;
25954 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025955 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025956 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025957 * Clear the current ielem.
25958 * VAL TODO: Don't free the PSVI IDC tables if they are
25959 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025960 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025961 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025962 /*
25963 * Skip further processing if we are on the validation root.
25964 */
25965 if (vctxt->depth == 0) {
25966 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025967 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025968 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025969 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025970 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025971 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025972 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025973 if (vctxt->aidcs != NULL) {
25974 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25975 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025976 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025977 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025978 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025979 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025980 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025981 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025982 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025983 }
25984 aidc = aidc->next;
25985 } while (aidc != NULL);
25986 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025987 vctxt->depth--;
25988 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025989 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025990 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025991 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25992 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025993 return (ret);
25994
25995internal_error:
25996 vctxt->err = -1;
25997 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025998}
25999
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026000/*
26001* 3.4.4 Complex Type Definition Validation Rules
26002* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26003*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026004static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026005xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026006{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026007 xmlSchemaNodeInfoPtr pielem;
26008 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026009 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026010
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026011 if (vctxt->depth <= 0) {
26012 VERROR_INT("xmlSchemaValidateChildElem",
26013 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026014 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026015 }
26016 pielem = vctxt->elemInfos[vctxt->depth -1];
26017 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26018 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026019 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026020 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026021 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026022 if (INODE_NILLED(pielem)) {
26023 /*
26024 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26025 */
26026 ACTIVATE_PARENT_ELEM;
26027 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26028 VERROR(ret, NULL,
26029 "Neither character nor element content is allowed, "
26030 "because the element was 'nilled'");
26031 ACTIVATE_ELEM;
26032 goto unexpected_elem;
26033 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026034
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026035 ptype = pielem->typeDef;
26036
26037 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26038 /*
26039 * Workaround for "anyType": we have currently no content model
26040 * assigned for "anyType", so handle it explicitely.
26041 * "anyType" has an unbounded, lax "any" wildcard.
26042 */
26043 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26044 vctxt->inode->localName,
26045 vctxt->inode->nsName);
26046
26047 if (vctxt->inode->decl == NULL) {
26048 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026049 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026050 * Process "xsi:type".
26051 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026052 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026053 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26054 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26055 if (iattr != NULL) {
26056 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26057 &(vctxt->inode->typeDef), NULL);
26058 if (ret != 0) {
26059 if (ret == -1) {
26060 VERROR_INT("xmlSchemaValidateChildElem",
26061 "calling xmlSchemaProcessXSIType() to "
26062 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026063 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026064 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026065 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026067 } else {
26068 /*
26069 * Fallback to "anyType".
26070 *
26071 * SPEC (cvc-assess-elt)
26072 * "If the item cannot be ·strictly assessed·, [...]
26073 * an element information item's schema validity may be laxly
26074 * assessed if its ·context-determined declaration· is not
26075 * skip by ·validating· with respect to the ·ur-type
26076 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26077 */
26078 vctxt->inode->typeDef =
26079 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026080 }
26081 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026082 return (0);
26083 }
26084
26085 switch (ptype->contentType) {
26086 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026087 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026088 * SPEC (2.1) "If the {content type} is empty, then the
26089 * element information item has no character or element
26090 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026091 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026092 ACTIVATE_PARENT_ELEM
26093 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26094 VERROR(ret, NULL,
26095 "Element content is not allowed, "
26096 "because the content type is empty");
26097 ACTIVATE_ELEM
26098 goto unexpected_elem;
26099 break;
26100
26101 case XML_SCHEMA_CONTENT_MIXED:
26102 case XML_SCHEMA_CONTENT_ELEMENTS: {
26103 xmlRegExecCtxtPtr regexCtxt;
26104 xmlChar *values[10];
26105 int terminal, nbval = 10, nbneg;
26106
26107 /* VAL TODO: Optimized "anyType" validation.*/
26108
26109 if (ptype->contModel == NULL) {
26110 VERROR_INT("xmlSchemaValidateChildElem",
26111 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026112 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026113 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026114 /*
26115 * Safety belf for evaluation if the cont. model was already
26116 * examined to be invalid.
26117 */
26118 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26119 VERROR_INT("xmlSchemaValidateChildElem",
26120 "validating elem, but elem content is already invalid");
26121 return (-1);
26122 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026123
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026124 regexCtxt = pielem->regexCtxt;
26125 if (regexCtxt == NULL) {
26126 /*
26127 * Create the regex context.
26128 */
26129 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26130 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26131 vctxt);
26132 if (regexCtxt == NULL) {
26133 VERROR_INT("xmlSchemaValidateChildElem",
26134 "failed to create a regex context");
26135 return (-1);
26136 }
26137 pielem->regexCtxt = regexCtxt;
26138#ifdef DEBUG_AUTOMATA
26139 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26140 pielem->localName);
26141#endif
26142 }
26143
26144 /*
26145 * SPEC (2.4) "If the {content type} is element-only or mixed,
26146 * then the sequence of the element information item's
26147 * element information item [children], if any, taken in
26148 * order, is ·valid· with respect to the {content type}'s
26149 * particle, as defined in Element Sequence Locally Valid
26150 * (Particle) (§3.9.4)."
26151 */
26152 ret = xmlRegExecPushString2(regexCtxt,
26153 vctxt->inode->localName,
26154 vctxt->inode->nsName,
26155 vctxt->inode);
26156#ifdef DEBUG_AUTOMATA
26157 if (ret < 0)
26158 xmlGenericError(xmlGenericErrorContext,
26159 "AUTOMATON push ERROR for '%s' on '%s'\n",
26160 vctxt->inode->localName, pielem->localName);
26161 else
26162 xmlGenericError(xmlGenericErrorContext,
26163 "AUTOMATON push OK for '%s' on '%s'\n",
26164 vctxt->inode->localName, pielem->localName);
26165#endif
26166 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26167 VERROR_INT("xmlSchemaValidateChildElem",
26168 "calling xmlRegExecPushString2()");
26169 return (-1);
26170 }
26171 if (ret < 0) {
26172 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26173 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026174 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026175 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26176 "This element is not expected",
26177 nbval, nbneg, values);
26178 ret = vctxt->err;
26179 goto unexpected_elem;
26180 } else
26181 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026182 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026183 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026184 case XML_SCHEMA_CONTENT_SIMPLE:
26185 case XML_SCHEMA_CONTENT_BASIC:
26186 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026187 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026188 /*
26189 * SPEC (cvc-complex-type) (2.2)
26190 * "If the {content type} is a simple type definition, then
26191 * the element information item has no element information
26192 * item [children], ..."
26193 */
26194 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26195 VERROR(ret, NULL, "Element content is not allowed, "
26196 "because the content type is a simple type definition");
26197 } else {
26198 /*
26199 * SPEC (cvc-type) (3.1.2) "The element information item must
26200 * have no element information item [children]."
26201 */
26202 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26203 VERROR(ret, NULL, "Element content is not allowed, "
26204 "because the type definition is simple");
26205 }
26206 ACTIVATE_ELEM
26207 ret = vctxt->err;
26208 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026209 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026210
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026211 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026212 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026213 }
26214 return (ret);
26215unexpected_elem:
26216 /*
26217 * Pop this element and set the skipDepth to skip
26218 * all further content of the parent element.
26219 */
26220 vctxt->skipDepth = vctxt->depth;
26221 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26222 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26223 return (ret);
26224}
26225
26226#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26227#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26228#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26229
26230static int
26231xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26232 int nodeType, const xmlChar *value, int len,
26233 int mode, int *consumed)
26234{
26235 /*
26236 * Unfortunately we have to duplicate the text sometimes.
26237 * OPTIMIZE: Maybe we could skip it, if:
26238 * 1. content type is simple
26239 * 2. whitespace is "collapse"
26240 * 3. it consists of whitespace only
26241 *
26242 * Process character content.
26243 */
26244 if (consumed != NULL)
26245 *consumed = 0;
26246 if (INODE_NILLED(vctxt->inode)) {
26247 /*
26248 * SPEC cvc-elt (3.3.4 - 3.2.1)
26249 * "The element information item must have no character or
26250 * element information item [children]."
26251 */
26252 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26253 "Neither character nor element content is allowed "
26254 "because the element is 'nilled'");
26255 return (vctxt->err);
26256 }
26257 /*
26258 * SPEC (2.1) "If the {content type} is empty, then the
26259 * element information item has no character or element
26260 * information item [children]."
26261 */
26262 if (vctxt->inode->typeDef->contentType ==
26263 XML_SCHEMA_CONTENT_EMPTY) {
26264 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26265 "Character content is not allowed, "
26266 "because the content type is empty");
26267 return (vctxt->err);
26268 }
26269
26270 if (vctxt->inode->typeDef->contentType ==
26271 XML_SCHEMA_CONTENT_ELEMENTS) {
26272 if ((nodeType != XML_TEXT_NODE) ||
26273 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26274 /*
26275 * SPEC cvc-complex-type (2.3)
26276 * "If the {content type} is element-only, then the
26277 * element information item has no character information
26278 * item [children] other than those whose [character
26279 * code] is defined as a white space in [XML 1.0 (Second
26280 * Edition)]."
26281 */
26282 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26283 "Character content other than whitespace is not allowed "
26284 "because the content type is 'element-only'");
26285 return (vctxt->err);
26286 }
26287 return (0);
26288 }
26289
26290 if ((value == NULL) || (value[0] == 0))
26291 return (0);
26292 /*
26293 * Save the value.
26294 * NOTE that even if the content type is *mixed*, we need the
26295 * *initial value* for default/fixed value constraints.
26296 */
26297 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26298 ((vctxt->inode->decl == NULL) ||
26299 (vctxt->inode->decl->value == NULL)))
26300 return (0);
26301
26302 if (vctxt->inode->value == NULL) {
26303 /*
26304 * Set the value.
26305 */
26306 switch (mode) {
26307 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26308 /*
26309 * When working on a tree.
26310 */
26311 vctxt->inode->value = value;
26312 break;
26313 case XML_SCHEMA_PUSH_TEXT_CREATED:
26314 /*
26315 * When working with the reader.
26316 * The value will be freed by the element info.
26317 */
26318 vctxt->inode->value = value;
26319 if (consumed != NULL)
26320 *consumed = 1;
26321 vctxt->inode->flags |=
26322 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26323 break;
26324 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26325 /*
26326 * When working with SAX.
26327 * The value will be freed by the element info.
26328 */
26329 if (len != -1)
26330 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26331 else
26332 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26333 vctxt->inode->flags |=
26334 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26335 break;
26336 default:
26337 break;
26338 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026339 } else {
26340 if (len < 0)
26341 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026342 /*
26343 * Concat the value.
26344 */
26345 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026346 vctxt->inode->value = BAD_CAST xmlStrncat(
26347 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026348 } else {
26349 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026350 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026351 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26352 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026353 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026354
26355 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026356}
26357
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026358static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026359xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026360{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026361 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026362
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026363 if ((vctxt->skipDepth != -1) &&
26364 (vctxt->depth >= vctxt->skipDepth)) {
26365 VERROR_INT("xmlSchemaValidateElem",
26366 "in skip-state");
26367 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026369 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026370 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026371 * We will stop validation if there was an error during
26372 * dynamic schema construction.
26373 * Note that we simply set @skipDepth to 0, this could
26374 * mean that a streaming document via SAX would be
26375 * still read to the end but it won't be validated any more.
26376 * TODO: If we are sure how to stop the validation at once
26377 * for all input scenarios, then this should be changed to
26378 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026379 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026380 ret = xmlSchemaAssembleByXSI(vctxt);
26381 if (ret != 0) {
26382 if (ret == -1)
26383 goto internal_error;
26384 vctxt->skipDepth = 0;
26385 return(ret);
26386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026387 }
26388 if (vctxt->depth > 0) {
26389 /*
26390 * Validate this element against the content model
26391 * of the parent.
26392 */
26393 ret = xmlSchemaValidateChildElem(vctxt);
26394 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026395 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026396 VERROR_INT("xmlSchemaValidateElem",
26397 "calling xmlSchemaStreamValidateChildElement()");
26398 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026399 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026400 goto exit;
26401 }
26402 if (vctxt->depth == vctxt->skipDepth)
26403 goto exit;
26404 if ((vctxt->inode->decl == NULL) &&
26405 (vctxt->inode->typeDef == NULL)) {
26406 VERROR_INT("xmlSchemaValidateElem",
26407 "the child element was valid but neither the "
26408 "declaration nor the type was set");
26409 goto internal_error;
26410 }
26411 } else {
26412 /*
26413 * Get the declaration of the validation root.
26414 */
26415 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26416 vctxt->inode->localName,
26417 vctxt->inode->nsName);
26418 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026419 ret = XML_SCHEMAV_CVC_ELT_1;
26420 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026421 "No matching global declaration available "
26422 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026423 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026424 }
26425 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026426
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026427 if (vctxt->inode->decl == NULL)
26428 goto type_validation;
26429
26430 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26431 int skip;
26432 /*
26433 * Wildcards.
26434 */
26435 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26436 if (ret != 0) {
26437 if (ret < 0) {
26438 VERROR_INT("xmlSchemaValidateElem",
26439 "calling xmlSchemaValidateElemWildcard()");
26440 goto internal_error;
26441 }
26442 goto exit;
26443 }
26444 if (skip) {
26445 vctxt->skipDepth = vctxt->depth;
26446 goto exit;
26447 }
26448 /*
26449 * The declaration might be set by the wildcard validation,
26450 * when the processContents is "lax" or "strict".
26451 */
26452 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26453 /*
26454 * Clear the "decl" field to not confuse further processing.
26455 */
26456 vctxt->inode->decl = NULL;
26457 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026458 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026459 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026460 /*
26461 * Validate against the declaration.
26462 */
26463 ret = xmlSchemaValidateElemDecl(vctxt);
26464 if (ret != 0) {
26465 if (ret < 0) {
26466 VERROR_INT("xmlSchemaValidateElem",
26467 "calling xmlSchemaValidateElemDecl()");
26468 goto internal_error;
26469 }
26470 goto exit;
26471 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026472 /*
26473 * Validate against the type definition.
26474 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026475type_validation:
26476
26477 if (vctxt->inode->typeDef == NULL) {
26478 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26479 ret = XML_SCHEMAV_CVC_TYPE_1;
26480 VERROR(ret, NULL,
26481 "The type definition is absent");
26482 goto exit;
26483 }
26484 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26485 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26486 ret = XML_SCHEMAV_CVC_TYPE_2;
26487 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026488 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026489 goto exit;
26490 }
26491 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026492 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026493 * during validation against the declaration. This must be done
26494 * _before_ attribute validation.
26495 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026496 if (vctxt->xpathStates != NULL) {
26497 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026498 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026499 if (ret == -1) {
26500 VERROR_INT("xmlSchemaValidateElem",
26501 "calling xmlSchemaXPathEvaluate()");
26502 goto internal_error;
26503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026504 }
26505 /*
26506 * Validate attributes.
26507 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026508 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026509 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026510 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026511
26512 ret = xmlSchemaVAttributesComplex(vctxt);
26513 }
26514 } else if (vctxt->nbAttrInfos != 0) {
26515
26516 ret = xmlSchemaVAttributesSimple(vctxt);
26517 }
26518 /*
26519 * Clear registered attributes.
26520 */
26521 if (vctxt->nbAttrInfos != 0)
26522 xmlSchemaClearAttrInfos(vctxt);
26523 if (ret == -1) {
26524 VERROR_INT("xmlSchemaValidateElem",
26525 "calling attributes validation");
26526 goto internal_error;
26527 }
26528 /*
26529 * Don't return an error if attributes are invalid on purpose.
26530 */
26531 ret = 0;
26532
26533exit:
26534 if (ret != 0)
26535 vctxt->skipDepth = vctxt->depth;
26536 return (ret);
26537internal_error:
26538 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026539}
26540
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026541#ifdef XML_SCHEMA_READER_ENABLED
26542static int
26543xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026544{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026545 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26546 int depth, nodeType, ret = 0, consumed;
26547 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026549 vctxt->depth = -1;
26550 ret = xmlTextReaderRead(vctxt->reader);
26551 /*
26552 * Move to the document element.
26553 */
26554 while (ret == 1) {
26555 nodeType = xmlTextReaderNodeType(vctxt->reader);
26556 if (nodeType == XML_ELEMENT_NODE)
26557 goto root_found;
26558 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026559 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026560 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026561
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026562root_found:
26563
26564 do {
26565 depth = xmlTextReaderDepth(vctxt->reader);
26566 nodeType = xmlTextReaderNodeType(vctxt->reader);
26567
26568 if (nodeType == XML_ELEMENT_NODE) {
26569
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026570 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026571 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26572 VERROR_INT("xmlSchemaVReaderWalk",
26573 "calling xmlSchemaValidatorPushElem()");
26574 goto internal_error;
26575 }
26576 ielem = vctxt->inode;
26577 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26578 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26579 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26580 /*
26581 * Is the element empty?
26582 */
26583 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26584 if (ret == -1) {
26585 VERROR_INT("xmlSchemaVReaderWalk",
26586 "calling xmlTextReaderIsEmptyElement()");
26587 goto internal_error;
26588 }
26589 if (ret) {
26590 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26591 }
26592 /*
26593 * Register attributes.
26594 */
26595 vctxt->nbAttrInfos = 0;
26596 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26597 if (ret == -1) {
26598 VERROR_INT("xmlSchemaVReaderWalk",
26599 "calling xmlTextReaderMoveToFirstAttribute()");
26600 goto internal_error;
26601 }
26602 if (ret == 1) {
26603 do {
26604 /*
26605 * VAL TODO: How do we know that the reader works on a
26606 * node tree, to be able to pass a node here?
26607 */
26608 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26609 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26610 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26611 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26612
26613 VERROR_INT("xmlSchemaVReaderWalk",
26614 "calling xmlSchemaValidatorPushAttribute()");
26615 goto internal_error;
26616 }
26617 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26618 if (ret == -1) {
26619 VERROR_INT("xmlSchemaVReaderWalk",
26620 "calling xmlTextReaderMoveToFirstAttribute()");
26621 goto internal_error;
26622 }
26623 } while (ret == 1);
26624 /*
26625 * Back to element position.
26626 */
26627 ret = xmlTextReaderMoveToElement(vctxt->reader);
26628 if (ret == -1) {
26629 VERROR_INT("xmlSchemaVReaderWalk",
26630 "calling xmlTextReaderMoveToElement()");
26631 goto internal_error;
26632 }
26633 }
26634 /*
26635 * Validate the element.
26636 */
26637 ret= xmlSchemaValidateElem(vctxt);
26638 if (ret != 0) {
26639 if (ret == -1) {
26640 VERROR_INT("xmlSchemaVReaderWalk",
26641 "calling xmlSchemaValidateElem()");
26642 goto internal_error;
26643 }
26644 goto exit;
26645 }
26646 if (vctxt->depth == vctxt->skipDepth) {
26647 int curDepth;
26648 /*
26649 * Skip all content.
26650 */
26651 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26652 ret = xmlTextReaderRead(vctxt->reader);
26653 curDepth = xmlTextReaderDepth(vctxt->reader);
26654 while ((ret == 1) && (curDepth != depth)) {
26655 ret = xmlTextReaderRead(vctxt->reader);
26656 curDepth = xmlTextReaderDepth(vctxt->reader);
26657 }
26658 if (ret < 0) {
26659 /*
26660 * VAL TODO: A reader error occured; what to do here?
26661 */
26662 ret = 1;
26663 goto exit;
26664 }
26665 }
26666 goto leave_elem;
26667 }
26668 /*
26669 * READER VAL TODO: Is an END_ELEM really never called
26670 * if the elem is empty?
26671 */
26672 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26673 goto leave_elem;
26674 } else if (nodeType == END_ELEM) {
26675 /*
26676 * Process END of element.
26677 */
26678leave_elem:
26679 ret = xmlSchemaValidatorPopElem(vctxt);
26680 if (ret != 0) {
26681 if (ret < 0) {
26682 VERROR_INT("xmlSchemaVReaderWalk",
26683 "calling xmlSchemaValidatorPopElem()");
26684 goto internal_error;
26685 }
26686 goto exit;
26687 }
26688 if (vctxt->depth >= 0)
26689 ielem = vctxt->inode;
26690 else
26691 ielem = NULL;
26692 } else if ((nodeType == XML_TEXT_NODE) ||
26693 (nodeType == XML_CDATA_SECTION_NODE) ||
26694 (nodeType == WHTSP) ||
26695 (nodeType == SIGN_WHTSP)) {
26696 /*
26697 * Process character content.
26698 */
26699 xmlChar *value;
26700
26701 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26702 nodeType = XML_TEXT_NODE;
26703
26704 value = xmlTextReaderValue(vctxt->reader);
26705 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26706 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26707 if (! consumed)
26708 xmlFree(value);
26709 if (ret == -1) {
26710 VERROR_INT("xmlSchemaVReaderWalk",
26711 "calling xmlSchemaVPushText()");
26712 goto internal_error;
26713 }
26714 } else if ((nodeType == XML_ENTITY_NODE) ||
26715 (nodeType == XML_ENTITY_REF_NODE)) {
26716 /*
26717 * VAL TODO: What to do with entities?
26718 */
26719 TODO
26720 }
26721 /*
26722 * Read next node.
26723 */
26724 ret = xmlTextReaderRead(vctxt->reader);
26725 } while (ret == 1);
26726
26727exit:
26728 return (ret);
26729internal_error:
26730 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026731}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026732#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026733
26734/************************************************************************
26735 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026736 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026737 * *
26738 ************************************************************************/
26739
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026740/*
26741* Process text content.
26742*/
26743static void
26744xmlSchemaSAXHandleText(void *ctx,
26745 const xmlChar * ch,
26746 int len)
26747{
26748 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26749
26750 if (vctxt->depth < 0)
26751 return;
26752 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26753 return;
26754 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26755 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26756 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26757 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26758 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26759 "calling xmlSchemaVPushText()");
26760 vctxt->err = -1;
26761 xmlStopParser(vctxt->parserCtxt);
26762 }
26763}
26764
26765/*
26766* Process CDATA content.
26767*/
26768static void
26769xmlSchemaSAXHandleCDataSection(void *ctx,
26770 const xmlChar * ch,
26771 int len)
26772{
26773 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26774
26775 if (vctxt->depth < 0)
26776 return;
26777 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26778 return;
26779 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26780 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26781 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26782 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26783 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26784 "calling xmlSchemaVPushText()");
26785 vctxt->err = -1;
26786 xmlStopParser(vctxt->parserCtxt);
26787 }
26788}
26789
26790static void
26791xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26792 const xmlChar * name ATTRIBUTE_UNUSED)
26793{
26794 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26795
26796 if (vctxt->depth < 0)
26797 return;
26798 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26799 return;
26800 /* SAX VAL TODO: What to do here? */
26801 TODO
26802}
26803
26804static void
26805xmlSchemaSAXHandleStartElementNs(void *ctx,
26806 const xmlChar * localname,
26807 const xmlChar * prefix ATTRIBUTE_UNUSED,
26808 const xmlChar * URI,
26809 int nb_namespaces,
26810 const xmlChar ** namespaces,
26811 int nb_attributes,
26812 int nb_defaulted ATTRIBUTE_UNUSED,
26813 const xmlChar ** attributes)
26814{
26815 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26816 int ret;
26817 xmlSchemaNodeInfoPtr ielem;
26818 int i, j;
26819
26820 /*
26821 * SAX VAL TODO: What to do with nb_defaulted?
26822 */
26823 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026824 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026825 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026826 vctxt->depth++;
26827 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026828 return;
26829 /*
26830 * Push the element.
26831 */
26832 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26833 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26834 "calling xmlSchemaValidatorPushElem()");
26835 goto internal_error;
26836 }
26837 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026838 /*
26839 * TODO: Is this OK?
26840 */
26841 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026842 ielem->localName = localname;
26843 ielem->nsName = URI;
26844 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26845 /*
26846 * Register namespaces on the elem info.
26847 */
26848 if (nb_namespaces != 0) {
26849 /*
26850 * Although the parser builds its own namespace list,
26851 * we have no access to it, so we'll use an own one.
26852 */
26853 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26854 /*
26855 * Store prefix and namespace name.
26856 */
26857 if (ielem->nsBindings == NULL) {
26858 ielem->nsBindings =
26859 (const xmlChar **) xmlMalloc(10 *
26860 sizeof(const xmlChar *));
26861 if (ielem->nsBindings == NULL) {
26862 xmlSchemaVErrMemory(vctxt,
26863 "allocating namespace bindings for SAX validation",
26864 NULL);
26865 goto internal_error;
26866 }
26867 ielem->nbNsBindings = 0;
26868 ielem->sizeNsBindings = 5;
26869 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26870 ielem->sizeNsBindings *= 2;
26871 ielem->nsBindings =
26872 (const xmlChar **) xmlRealloc(
26873 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026874 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026875 if (ielem->nsBindings == NULL) {
26876 xmlSchemaVErrMemory(vctxt,
26877 "re-allocating namespace bindings for SAX validation",
26878 NULL);
26879 goto internal_error;
26880 }
26881 }
26882
26883 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26884 if (namespaces[j+1][0] == 0) {
26885 /*
26886 * Handle xmlns="".
26887 */
26888 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26889 } else
26890 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26891 namespaces[j+1];
26892 ielem->nbNsBindings++;
26893 }
26894 }
26895 /*
26896 * Register attributes.
26897 * SAX VAL TODO: We are not adding namespace declaration
26898 * attributes yet.
26899 */
26900 if (nb_attributes != 0) {
26901 xmlChar *value;
26902
26903 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26904 /*
26905 * Duplicate the value.
26906 */
26907 value = xmlStrndup(attributes[j+3],
26908 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026909 /*
26910 * TODO: Set the node line.
26911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026912 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026913 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026914 value, 1);
26915 if (ret == -1) {
26916 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26917 "calling xmlSchemaValidatorPushAttribute()");
26918 goto internal_error;
26919 }
26920 }
26921 }
26922 /*
26923 * Validate the element.
26924 */
26925 ret = xmlSchemaValidateElem(vctxt);
26926 if (ret != 0) {
26927 if (ret == -1) {
26928 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26929 "calling xmlSchemaValidateElem()");
26930 goto internal_error;
26931 }
26932 goto exit;
26933 }
26934
26935exit:
26936 return;
26937internal_error:
26938 vctxt->err = -1;
26939 xmlStopParser(vctxt->parserCtxt);
26940 return;
26941}
26942
26943static void
26944xmlSchemaSAXHandleEndElementNs(void *ctx,
26945 const xmlChar * localname ATTRIBUTE_UNUSED,
26946 const xmlChar * prefix ATTRIBUTE_UNUSED,
26947 const xmlChar * URI ATTRIBUTE_UNUSED)
26948{
26949 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26950 int res;
26951
26952 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026953 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026954 */
26955 if (vctxt->skipDepth != -1) {
26956 if (vctxt->depth > vctxt->skipDepth) {
26957 vctxt->depth--;
26958 return;
26959 } else
26960 vctxt->skipDepth = -1;
26961 }
26962 /*
26963 * SAX VAL TODO: Just a temporary check.
26964 */
26965 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26966 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26967 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26968 "elem pop mismatch");
26969 }
26970 res = xmlSchemaValidatorPopElem(vctxt);
26971 if (res != 0) {
26972 if (res < 0) {
26973 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26974 "calling xmlSchemaValidatorPopElem()");
26975 goto internal_error;
26976 }
26977 goto exit;
26978 }
26979exit:
26980 return;
26981internal_error:
26982 vctxt->err = -1;
26983 xmlStopParser(vctxt->parserCtxt);
26984 return;
26985}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026986
Daniel Veillard4255d502002-04-16 15:50:10 +000026987/************************************************************************
26988 * *
26989 * Validation interfaces *
26990 * *
26991 ************************************************************************/
26992
26993/**
26994 * xmlSchemaNewValidCtxt:
26995 * @schema: a precompiled XML Schemas
26996 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026997 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026998 *
26999 * Returns the validation context or NULL in case of error
27000 */
27001xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027002xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27003{
Daniel Veillard4255d502002-04-16 15:50:10 +000027004 xmlSchemaValidCtxtPtr ret;
27005
27006 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27007 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027008 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027009 return (NULL);
27010 }
27011 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027012 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027013 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027014 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027015 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027016 return (ret);
27017}
27018
27019/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027020 * xmlSchemaClearValidCtxt:
27021 * @ctxt: the schema validation context
27022 *
27023 * Free the resources associated to the schema validation context;
27024 * leaves some fields alive intended for reuse of the context.
27025 */
27026static void
27027xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27028{
27029 if (vctxt == NULL)
27030 return;
27031
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027032 /*
27033 * TODO: Should we clear the flags?
27034 * Might be problematic if one reuses the context
27035 * and assumes that the options remain the same.
27036 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027037 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027038 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027039 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027040#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027041 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027042#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027043 vctxt->hasKeyrefs = 0;
27044
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027045 if (vctxt->value != NULL) {
27046 xmlSchemaFreeValue(vctxt->value);
27047 vctxt->value = NULL;
27048 }
27049 /*
27050 * Augmented IDC information.
27051 */
27052 if (vctxt->aidcs != NULL) {
27053 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27054 do {
27055 next = cur->next;
27056 xmlFree(cur);
27057 cur = next;
27058 } while (cur != NULL);
27059 vctxt->aidcs = NULL;
27060 }
27061 if (vctxt->idcNodes != NULL) {
27062 int i;
27063 xmlSchemaPSVIIDCNodePtr item;
27064
27065 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027066 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027067 xmlFree(item->keys);
27068 xmlFree(item);
27069 }
27070 xmlFree(vctxt->idcNodes);
27071 vctxt->idcNodes = NULL;
27072 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027073 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027074 * Note that we won't delete the XPath state pool here.
27075 */
27076 if (vctxt->xpathStates != NULL) {
27077 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27078 vctxt->xpathStates = NULL;
27079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027080 /*
27081 * Attribute info.
27082 */
27083 if (vctxt->nbAttrInfos != 0) {
27084 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027085 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027086 /*
27087 * Element info.
27088 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027089 if (vctxt->elemInfos != NULL) {
27090 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027091 xmlSchemaNodeInfoPtr ei;
27092
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027093 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027094 ei = vctxt->elemInfos[i];
27095 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027096 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027097 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027098 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027099 }
27100 xmlSchemaItemListClear(vctxt->nodeQNames);
27101 /* Recreate the dict. */
27102 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027103 /*
27104 * TODO: Is is save to recreate it? Do we have a scenario
27105 * where the user provides the dict?
27106 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027107 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027108}
27109
27110/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027111 * xmlSchemaFreeValidCtxt:
27112 * @ctxt: the schema validation context
27113 *
27114 * Free the resources associated to the schema validation context
27115 */
27116void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027117xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27118{
Daniel Veillard4255d502002-04-16 15:50:10 +000027119 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027120 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027121 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027122 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027123 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027124 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027125 if (ctxt->idcNodes != NULL) {
27126 int i;
27127 xmlSchemaPSVIIDCNodePtr item;
27128
27129 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027130 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027131 xmlFree(item->keys);
27132 xmlFree(item);
27133 }
27134 xmlFree(ctxt->idcNodes);
27135 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027136 if (ctxt->idcKeys != NULL) {
27137 int i;
27138 for (i = 0; i < ctxt->nbIdcKeys; i++)
27139 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27140 xmlFree(ctxt->idcKeys);
27141 }
27142
27143 if (ctxt->xpathStates != NULL)
27144 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27145 if (ctxt->xpathStatePool != NULL)
27146 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27147
27148 /*
27149 * Augmented IDC information.
27150 */
27151 if (ctxt->aidcs != NULL) {
27152 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27153 do {
27154 next = cur->next;
27155 xmlFree(cur);
27156 cur = next;
27157 } while (cur != NULL);
27158 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027159 if (ctxt->attrInfos != NULL) {
27160 int i;
27161 xmlSchemaAttrInfoPtr attr;
27162
27163 /* Just a paranoid call to the cleanup. */
27164 if (ctxt->nbAttrInfos != 0)
27165 xmlSchemaClearAttrInfos(ctxt);
27166 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27167 attr = ctxt->attrInfos[i];
27168 xmlFree(attr);
27169 }
27170 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027171 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027172 if (ctxt->elemInfos != NULL) {
27173 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027174 xmlSchemaNodeInfoPtr ei;
27175
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027176 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027177 ei = ctxt->elemInfos[i];
27178 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027179 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027180 xmlSchemaClearElemInfo(ei);
27181 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027182 }
27183 xmlFree(ctxt->elemInfos);
27184 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027185 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027186 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027187 if (ctxt->dict != NULL)
27188 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027189 xmlFree(ctxt);
27190}
27191
27192/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027193 * xmlSchemaIsValid:
27194 * @ctxt: the schema validation context
27195 *
27196 * Check if any error was detected during validation.
27197 *
27198 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27199 * of internal error.
27200 */
27201int
27202xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27203{
27204 if (ctxt == NULL)
27205 return(-1);
27206 return(ctxt->err == 0);
27207}
27208
27209/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027210 * xmlSchemaSetValidErrors:
27211 * @ctxt: a schema validation context
27212 * @err: the error function
27213 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027214 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027215 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027216 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027217 */
27218void
27219xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027220 xmlSchemaValidityErrorFunc err,
27221 xmlSchemaValidityWarningFunc warn, void *ctx)
27222{
Daniel Veillard4255d502002-04-16 15:50:10 +000027223 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027224 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027225 ctxt->error = err;
27226 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027227 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027228 if (ctxt->pctxt != NULL)
27229 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027230}
27231
27232/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027233 * xmlSchemaSetValidStructuredErrors:
27234 * @ctxt: a schema validation context
27235 * @serror: the structured error function
27236 * @ctx: the functions context
27237 *
27238 * Set the structured error callback
27239 */
27240void
27241xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027242 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027243{
27244 if (ctxt == NULL)
27245 return;
27246 ctxt->serror = serror;
27247 ctxt->error = NULL;
27248 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027249 ctxt->errCtxt = ctx;
27250 if (ctxt->pctxt != NULL)
27251 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027252}
27253
27254/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027255 * xmlSchemaGetValidErrors:
27256 * @ctxt: a XML-Schema validation context
27257 * @err: the error function result
27258 * @warn: the warning function result
27259 * @ctx: the functions context result
27260 *
27261 * Get the error and warning callback informations
27262 *
27263 * Returns -1 in case of error and 0 otherwise
27264 */
27265int
27266xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027267 xmlSchemaValidityErrorFunc * err,
27268 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027269{
27270 if (ctxt == NULL)
27271 return (-1);
27272 if (err != NULL)
27273 *err = ctxt->error;
27274 if (warn != NULL)
27275 *warn = ctxt->warning;
27276 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027277 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027278 return (0);
27279}
27280
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027281
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027282/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027283 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027284 * @ctxt: a schema validation context
27285 * @options: a combination of xmlSchemaValidOption
27286 *
27287 * Sets the options to be used during the validation.
27288 *
27289 * Returns 0 in case of success, -1 in case of an
27290 * API error.
27291 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027292int
27293xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27294 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027295
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027296{
27297 int i;
27298
27299 if (ctxt == NULL)
27300 return (-1);
27301 /*
27302 * WARNING: Change the start value if adding to the
27303 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027304 * TODO: Is there an other, more easy to maintain,
27305 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027306 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027307 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027308 if (options & 1<<i)
27309 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027310 }
27311 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027312 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027313}
27314
27315/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027316 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027317 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027318 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027319 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027320 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027321 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027322 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027323int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027324xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027325
27326{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027327 if (ctxt == NULL)
27328 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027329 else
27330 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027331}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027332
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027333static int
27334xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27335{
27336 xmlAttrPtr attr;
27337 int ret = 0;
27338 xmlSchemaNodeInfoPtr ielem = NULL;
27339 xmlNodePtr node, valRoot;
27340 const xmlChar *nsName;
27341
27342 /* DOC VAL TODO: Move this to the start function. */
27343 valRoot = xmlDocGetRootElement(vctxt->doc);
27344 if (valRoot == NULL) {
27345 /* VAL TODO: Error code? */
27346 VERROR(1, NULL, "The document has no document element");
27347 return (1);
27348 }
27349 vctxt->depth = -1;
27350 vctxt->validationRoot = valRoot;
27351 node = valRoot;
27352 while (node != NULL) {
27353 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27354 goto next_sibling;
27355 if (node->type == XML_ELEMENT_NODE) {
27356
27357 /*
27358 * Init the node-info.
27359 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027360 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027361 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27362 goto internal_error;
27363 ielem = vctxt->inode;
27364 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027365 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027366 ielem->localName = node->name;
27367 if (node->ns != NULL)
27368 ielem->nsName = node->ns->href;
27369 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27370 /*
27371 * Register attributes.
27372 * DOC VAL TODO: We do not register namespace declaration
27373 * attributes yet.
27374 */
27375 vctxt->nbAttrInfos = 0;
27376 if (node->properties != NULL) {
27377 attr = node->properties;
27378 do {
27379 if (attr->ns != NULL)
27380 nsName = attr->ns->href;
27381 else
27382 nsName = NULL;
27383 ret = xmlSchemaValidatorPushAttribute(vctxt,
27384 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027385 /*
27386 * Note that we give it the line number of the
27387 * parent element.
27388 */
27389 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027390 attr->name, nsName, 0,
27391 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27392 if (ret == -1) {
27393 VERROR_INT("xmlSchemaDocWalk",
27394 "calling xmlSchemaValidatorPushAttribute()");
27395 goto internal_error;
27396 }
27397 attr = attr->next;
27398 } while (attr);
27399 }
27400 /*
27401 * Validate the element.
27402 */
27403 ret = xmlSchemaValidateElem(vctxt);
27404 if (ret != 0) {
27405 if (ret == -1) {
27406 VERROR_INT("xmlSchemaDocWalk",
27407 "calling xmlSchemaValidateElem()");
27408 goto internal_error;
27409 }
27410 /*
27411 * Don't stop validation; just skip the content
27412 * of this element.
27413 */
27414 goto leave_node;
27415 }
27416 if ((vctxt->skipDepth != -1) &&
27417 (vctxt->depth >= vctxt->skipDepth))
27418 goto leave_node;
27419 } else if ((node->type == XML_TEXT_NODE) ||
27420 (node->type == XML_CDATA_SECTION_NODE)) {
27421 /*
27422 * Process character content.
27423 */
27424 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27425 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27426 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27427 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27428 if (ret < 0) {
27429 VERROR_INT("xmlSchemaVDocWalk",
27430 "calling xmlSchemaVPushText()");
27431 goto internal_error;
27432 }
27433 /*
27434 * DOC VAL TODO: Should we skip further validation of the
27435 * element content here?
27436 */
27437 } else if ((node->type == XML_ENTITY_NODE) ||
27438 (node->type == XML_ENTITY_REF_NODE)) {
27439 /*
27440 * DOC VAL TODO: What to do with entities?
27441 */
27442 TODO
27443 } else {
27444 goto leave_node;
27445 /*
27446 * DOC VAL TODO: XInclude nodes, etc.
27447 */
27448 }
27449 /*
27450 * Walk the doc.
27451 */
27452 if (node->children != NULL) {
27453 node = node->children;
27454 continue;
27455 }
27456leave_node:
27457 if (node->type == XML_ELEMENT_NODE) {
27458 /*
27459 * Leaving the scope of an element.
27460 */
27461 if (node != vctxt->inode->node) {
27462 VERROR_INT("xmlSchemaVDocWalk",
27463 "element position mismatch");
27464 goto internal_error;
27465 }
27466 ret = xmlSchemaValidatorPopElem(vctxt);
27467 if (ret != 0) {
27468 if (ret < 0) {
27469 VERROR_INT("xmlSchemaVDocWalk",
27470 "calling xmlSchemaValidatorPopElem()");
27471 goto internal_error;
27472 }
27473 }
27474 if (node == valRoot)
27475 goto exit;
27476 }
27477next_sibling:
27478 if (node->next != NULL)
27479 node = node->next;
27480 else {
27481 node = node->parent;
27482 goto leave_node;
27483 }
27484 }
27485
27486exit:
27487 return (ret);
27488internal_error:
27489 return (-1);
27490}
27491
27492static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027493xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027494 /*
27495 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027497 vctxt->err = 0;
27498 vctxt->nberrors = 0;
27499 vctxt->depth = -1;
27500 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027501 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027502 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000027503#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027504 vctxt->createIDCNodeTables = 1;
27505#else
27506 vctxt->createIDCNodeTables = 0;
27507#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027508 /*
27509 * Create a schema + parser if necessary.
27510 */
27511 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027512 xmlSchemaParserCtxtPtr pctxt;
27513
27514 vctxt->xsiAssemble = 1;
27515 /*
27516 * If not schema was given then we will create a schema
27517 * dynamically using XSI schema locations.
27518 *
27519 * Create the schema parser context.
27520 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027521 if ((vctxt->pctxt == NULL) &&
27522 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27523 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027524 pctxt = vctxt->pctxt;
27525 pctxt->xsiAssemble = 1;
27526 /*
27527 * Create the schema.
27528 */
27529 vctxt->schema = xmlSchemaNewSchema(pctxt);
27530 if (vctxt->schema == NULL)
27531 return (-1);
27532 /*
27533 * Create the schema construction context.
27534 */
27535 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27536 if (pctxt->constructor == NULL)
27537 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027538 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027539 /*
27540 * Take ownership of the constructor to be able to free it.
27541 */
27542 pctxt->ownsConstructor = 1;
27543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027544 /*
27545 * Augment the IDC definitions.
27546 */
27547 if (vctxt->schema->idcDef != NULL) {
27548 xmlHashScan(vctxt->schema->idcDef,
27549 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27550 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027551 return(0);
27552}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027553
Daniel Veillardf10ae122005-07-10 19:03:16 +000027554static void
27555xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027556 if (vctxt->xsiAssemble) {
27557 if (vctxt->schema != NULL) {
27558 xmlSchemaFree(vctxt->schema);
27559 vctxt->schema = NULL;
27560 }
27561 }
27562 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027563}
27564
27565static int
27566xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27567{
27568 int ret = 0;
27569
27570 if (xmlSchemaPreRun(vctxt) < 0)
27571 return(-1);
27572
27573 if (vctxt->doc != NULL) {
27574 /*
27575 * Tree validation.
27576 */
27577 ret = xmlSchemaVDocWalk(vctxt);
27578#ifdef LIBXML_READER_ENABLED
27579 } else if (vctxt->reader != NULL) {
27580 /*
27581 * XML Reader validation.
27582 */
27583#ifdef XML_SCHEMA_READER_ENABLED
27584 ret = xmlSchemaVReaderWalk(vctxt);
27585#endif
27586#endif
27587 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27588 /*
27589 * SAX validation.
27590 */
27591 ret = xmlParseDocument(vctxt->parserCtxt);
27592 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027593 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027594 "no instance to validate");
27595 ret = -1;
27596 }
27597
27598 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027599 if (ret == 0)
27600 ret = vctxt->err;
27601 return (ret);
27602}
27603
27604/**
27605 * xmlSchemaValidateOneElement:
27606 * @ctxt: a schema validation context
27607 * @elem: an element node
27608 *
27609 * Validate a branch of a tree, starting with the given @elem.
27610 *
27611 * Returns 0 if the element and its subtree is valid, a positive error
27612 * code number otherwise and -1 in case of an internal or API error.
27613 */
27614int
27615xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27616{
27617 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27618 return (-1);
27619
27620 if (ctxt->schema == NULL)
27621 return (-1);
27622
27623 ctxt->doc = elem->doc;
27624 ctxt->node = elem;
27625 ctxt->validationRoot = elem;
27626 return(xmlSchemaVStart(ctxt));
27627}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027628
Daniel Veillard259f0df2004-08-18 09:13:18 +000027629/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027630 * xmlSchemaValidateDoc:
27631 * @ctxt: a schema validation context
27632 * @doc: a parsed document tree
27633 *
27634 * Validate a document tree in memory.
27635 *
27636 * Returns 0 if the document is schemas valid, a positive error code
27637 * number otherwise and -1 in case of internal or API error.
27638 */
27639int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027640xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27641{
Daniel Veillard4255d502002-04-16 15:50:10 +000027642 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027643 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027645 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027646 ctxt->node = xmlDocGetRootElement(doc);
27647 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027648 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027649 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27650 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027651 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027652 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027653 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027654 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027655 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027656}
27657
Daniel Veillardcdc82732005-07-08 15:04:06 +000027658
27659/************************************************************************
27660 * *
27661 * Function and data for SAX streaming API *
27662 * *
27663 ************************************************************************/
27664typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27665typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27666
27667struct _xmlSchemaSplitSAXData {
27668 xmlSAXHandlerPtr user_sax;
27669 void *user_data;
27670 xmlSchemaValidCtxtPtr ctxt;
27671 xmlSAXHandlerPtr schemas_sax;
27672};
27673
Daniel Veillard971771e2005-07-09 17:32:57 +000027674#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27675
27676struct _xmlSchemaSAXPlug {
27677 unsigned int magic;
27678
27679 /* the original callbacks informations */
27680 xmlSAXHandlerPtr *user_sax_ptr;
27681 xmlSAXHandlerPtr user_sax;
27682 void **user_data_ptr;
27683 void *user_data;
27684
27685 /* the block plugged back and validation informations */
27686 xmlSAXHandler schemas_sax;
27687 xmlSchemaValidCtxtPtr ctxt;
27688};
27689
Daniel Veillardcdc82732005-07-08 15:04:06 +000027690/* All those functions just bounces to the user provided SAX handlers */
27691static void
27692internalSubsetSplit(void *ctx, const xmlChar *name,
27693 const xmlChar *ExternalID, const xmlChar *SystemID)
27694{
Daniel Veillard971771e2005-07-09 17:32:57 +000027695 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027696 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27697 (ctxt->user_sax->internalSubset != NULL))
27698 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27699 SystemID);
27700}
27701
27702static int
27703isStandaloneSplit(void *ctx)
27704{
Daniel Veillard971771e2005-07-09 17:32:57 +000027705 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027706 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27707 (ctxt->user_sax->isStandalone != NULL))
27708 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27709 return(0);
27710}
27711
27712static int
27713hasInternalSubsetSplit(void *ctx)
27714{
Daniel Veillard971771e2005-07-09 17:32:57 +000027715 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027716 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27717 (ctxt->user_sax->hasInternalSubset != NULL))
27718 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27719 return(0);
27720}
27721
27722static int
27723hasExternalSubsetSplit(void *ctx)
27724{
Daniel Veillard971771e2005-07-09 17:32:57 +000027725 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027726 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27727 (ctxt->user_sax->hasExternalSubset != NULL))
27728 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27729 return(0);
27730}
27731
27732static void
27733externalSubsetSplit(void *ctx, const xmlChar *name,
27734 const xmlChar *ExternalID, const xmlChar *SystemID)
27735{
Daniel Veillard971771e2005-07-09 17:32:57 +000027736 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027737 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27738 (ctxt->user_sax->internalSubset != NULL))
27739 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27740 SystemID);
27741}
27742
27743static xmlParserInputPtr
27744resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27745{
Daniel Veillard971771e2005-07-09 17:32:57 +000027746 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027747 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27748 (ctxt->user_sax->resolveEntity != NULL))
27749 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27750 systemId));
27751 return(NULL);
27752}
27753
27754static xmlEntityPtr
27755getEntitySplit(void *ctx, const xmlChar *name)
27756{
Daniel Veillard971771e2005-07-09 17:32:57 +000027757 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027758 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27759 (ctxt->user_sax->getEntity != NULL))
27760 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27761 return(NULL);
27762}
27763
27764static xmlEntityPtr
27765getParameterEntitySplit(void *ctx, const xmlChar *name)
27766{
Daniel Veillard971771e2005-07-09 17:32:57 +000027767 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027768 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27769 (ctxt->user_sax->getParameterEntity != NULL))
27770 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27771 return(NULL);
27772}
27773
27774
27775static void
27776entityDeclSplit(void *ctx, const xmlChar *name, int type,
27777 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27778{
Daniel Veillard971771e2005-07-09 17:32:57 +000027779 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027780 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27781 (ctxt->user_sax->entityDecl != NULL))
27782 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27783 systemId, content);
27784}
27785
27786static void
27787attributeDeclSplit(void *ctx, const xmlChar * elem,
27788 const xmlChar * name, int type, int def,
27789 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27790{
Daniel Veillard971771e2005-07-09 17:32:57 +000027791 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027792 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27793 (ctxt->user_sax->attributeDecl != NULL)) {
27794 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27795 def, defaultValue, tree);
27796 } else {
27797 xmlFreeEnumeration(tree);
27798 }
27799}
27800
27801static void
27802elementDeclSplit(void *ctx, const xmlChar *name, int type,
27803 xmlElementContentPtr content)
27804{
Daniel Veillard971771e2005-07-09 17:32:57 +000027805 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027806 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27807 (ctxt->user_sax->elementDecl != NULL))
27808 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27809}
27810
27811static void
27812notationDeclSplit(void *ctx, const xmlChar *name,
27813 const xmlChar *publicId, const xmlChar *systemId)
27814{
Daniel Veillard971771e2005-07-09 17:32:57 +000027815 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027816 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27817 (ctxt->user_sax->notationDecl != NULL))
27818 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27819 systemId);
27820}
27821
27822static void
27823unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27824 const xmlChar *publicId, const xmlChar *systemId,
27825 const xmlChar *notationName)
27826{
Daniel Veillard971771e2005-07-09 17:32:57 +000027827 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027828 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27829 (ctxt->user_sax->unparsedEntityDecl != NULL))
27830 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27831 systemId, notationName);
27832}
27833
27834static void
27835setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27836{
Daniel Veillard971771e2005-07-09 17:32:57 +000027837 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027838 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27839 (ctxt->user_sax->setDocumentLocator != NULL))
27840 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27841}
27842
27843static void
27844startDocumentSplit(void *ctx)
27845{
Daniel Veillard971771e2005-07-09 17:32:57 +000027846 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027847 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27848 (ctxt->user_sax->startDocument != NULL))
27849 ctxt->user_sax->startDocument(ctxt->user_data);
27850}
27851
27852static void
27853endDocumentSplit(void *ctx)
27854{
Daniel Veillard971771e2005-07-09 17:32:57 +000027855 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027856 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27857 (ctxt->user_sax->endDocument != NULL))
27858 ctxt->user_sax->endDocument(ctxt->user_data);
27859}
27860
27861static void
27862processingInstructionSplit(void *ctx, const xmlChar *target,
27863 const xmlChar *data)
27864{
Daniel Veillard971771e2005-07-09 17:32:57 +000027865 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027866 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27867 (ctxt->user_sax->processingInstruction != NULL))
27868 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27869}
27870
27871static void
27872commentSplit(void *ctx, const xmlChar *value)
27873{
Daniel Veillard971771e2005-07-09 17:32:57 +000027874 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027875 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27876 (ctxt->user_sax->comment != NULL))
27877 ctxt->user_sax->comment(ctxt->user_data, value);
27878}
27879
27880/*
27881 * Varargs error callbacks to the user application, harder ...
27882 */
27883
Daniel Veillardffa3c742005-07-21 13:24:09 +000027884static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027885warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027886 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027887 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27888 (ctxt->user_sax->warning != NULL)) {
27889 TODO
27890 }
27891}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027892static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027893errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027894 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027895 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27896 (ctxt->user_sax->error != NULL)) {
27897 TODO
27898 }
27899}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027900static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027901fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027902 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027903 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27904 (ctxt->user_sax->fatalError != NULL)) {
27905 TODO
27906 }
27907}
27908
27909/*
27910 * Those are function where both the user handler and the schemas handler
27911 * need to be called.
27912 */
27913static void
27914charactersSplit(void *ctx, const xmlChar *ch, int len)
27915{
Daniel Veillard971771e2005-07-09 17:32:57 +000027916 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027917 if (ctxt == NULL)
27918 return;
27919 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27920 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27921 if (ctxt->ctxt != NULL)
27922 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27923}
27924
27925static void
27926ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27927{
Daniel Veillard971771e2005-07-09 17:32:57 +000027928 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027929 if (ctxt == NULL)
27930 return;
27931 if ((ctxt->user_sax != NULL) &&
27932 (ctxt->user_sax->ignorableWhitespace != NULL))
27933 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27934 if (ctxt->ctxt != NULL)
27935 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27936}
27937
27938static void
27939cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27940{
Daniel Veillard971771e2005-07-09 17:32:57 +000027941 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027942 if (ctxt == NULL)
27943 return;
27944 if ((ctxt->user_sax != NULL) &&
27945 (ctxt->user_sax->ignorableWhitespace != NULL))
27946 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27947 if (ctxt->ctxt != NULL)
27948 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27949}
27950
27951static void
27952referenceSplit(void *ctx, const xmlChar *name)
27953{
Daniel Veillard971771e2005-07-09 17:32:57 +000027954 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027955 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27956 (ctxt->user_sax->reference != NULL))
27957 ctxt->user_sax->reference(ctxt->user_data, name);
27958 if (ctxt->ctxt != NULL)
27959 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27960}
27961
27962static void
27963startElementNsSplit(void *ctx, const xmlChar * localname,
27964 const xmlChar * prefix, const xmlChar * URI,
27965 int nb_namespaces, const xmlChar ** namespaces,
27966 int nb_attributes, int nb_defaulted,
27967 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027968 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027969 if (ctxt == NULL)
27970 return;
27971 if ((ctxt->user_sax != NULL) &&
27972 (ctxt->user_sax->startElementNs != NULL))
27973 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27974 URI, nb_namespaces, namespaces,
27975 nb_attributes, nb_defaulted,
27976 attributes);
27977 if (ctxt->ctxt != NULL)
27978 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27979 URI, nb_namespaces, namespaces,
27980 nb_attributes, nb_defaulted,
27981 attributes);
27982}
27983
27984static void
27985endElementNsSplit(void *ctx, const xmlChar * localname,
27986 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027987 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027988 if (ctxt == NULL)
27989 return;
27990 if ((ctxt->user_sax != NULL) &&
27991 (ctxt->user_sax->endElementNs != NULL))
27992 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27993 if (ctxt->ctxt != NULL)
27994 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27995}
27996
Daniel Veillard4255d502002-04-16 15:50:10 +000027997/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027998 * xmlSchemaSAXPlug:
27999 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028000 * @sax: a pointer to the original xmlSAXHandlerPtr
28001 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028002 *
28003 * Plug a SAX based validation layer in a SAX parsing event flow.
28004 * The original @saxptr and @dataptr data are replaced by new pointers
28005 * but the calls to the original will be maintained.
28006 *
28007 * Returns a pointer to a data structure needed to unplug the validation layer
28008 * or NULL in case of errors.
28009 */
28010xmlSchemaSAXPlugPtr
28011xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28012 xmlSAXHandlerPtr *sax, void **user_data)
28013{
28014 xmlSchemaSAXPlugPtr ret;
28015 xmlSAXHandlerPtr old_sax;
28016
28017 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28018 return(NULL);
28019
28020 /*
28021 * We only allow to plug into SAX2 event streams
28022 */
28023 old_sax = *sax;
28024 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28025 return(NULL);
28026 if ((old_sax != NULL) &&
28027 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28028 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28029 return(NULL);
28030
28031 /*
28032 * everything seems right allocate the local data needed for that layer
28033 */
28034 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28035 if (ret == NULL) {
28036 return(NULL);
28037 }
28038 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28039 ret->magic = XML_SAX_PLUG_MAGIC;
28040 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28041 ret->ctxt = ctxt;
28042 ret->user_sax_ptr = sax;
28043 ret->user_sax = old_sax;
28044 if (old_sax == NULL) {
28045 /*
28046 * go direct, no need for the split block and functions.
28047 */
28048 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28049 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28050 /*
28051 * Note that we use the same text-function for both, to prevent
28052 * the parser from testing for ignorable whitespace.
28053 */
28054 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28055 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28056
28057 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28058 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28059
28060 ret->user_data = ctxt;
28061 *user_data = ctxt;
28062 } else {
28063 /*
28064 * for each callback unused by Schemas initialize it to the Split
28065 * routine only if non NULL in the user block, this can speed up
28066 * things at the SAX level.
28067 */
28068 if (old_sax->internalSubset != NULL)
28069 ret->schemas_sax.internalSubset = internalSubsetSplit;
28070 if (old_sax->isStandalone != NULL)
28071 ret->schemas_sax.isStandalone = isStandaloneSplit;
28072 if (old_sax->hasInternalSubset != NULL)
28073 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28074 if (old_sax->hasExternalSubset != NULL)
28075 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28076 if (old_sax->resolveEntity != NULL)
28077 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28078 if (old_sax->getEntity != NULL)
28079 ret->schemas_sax.getEntity = getEntitySplit;
28080 if (old_sax->entityDecl != NULL)
28081 ret->schemas_sax.entityDecl = entityDeclSplit;
28082 if (old_sax->notationDecl != NULL)
28083 ret->schemas_sax.notationDecl = notationDeclSplit;
28084 if (old_sax->attributeDecl != NULL)
28085 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28086 if (old_sax->elementDecl != NULL)
28087 ret->schemas_sax.elementDecl = elementDeclSplit;
28088 if (old_sax->unparsedEntityDecl != NULL)
28089 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28090 if (old_sax->setDocumentLocator != NULL)
28091 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28092 if (old_sax->startDocument != NULL)
28093 ret->schemas_sax.startDocument = startDocumentSplit;
28094 if (old_sax->endDocument != NULL)
28095 ret->schemas_sax.endDocument = endDocumentSplit;
28096 if (old_sax->processingInstruction != NULL)
28097 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28098 if (old_sax->comment != NULL)
28099 ret->schemas_sax.comment = commentSplit;
28100 if (old_sax->warning != NULL)
28101 ret->schemas_sax.warning = warningSplit;
28102 if (old_sax->error != NULL)
28103 ret->schemas_sax.error = errorSplit;
28104 if (old_sax->fatalError != NULL)
28105 ret->schemas_sax.fatalError = fatalErrorSplit;
28106 if (old_sax->getParameterEntity != NULL)
28107 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28108 if (old_sax->externalSubset != NULL)
28109 ret->schemas_sax.externalSubset = externalSubsetSplit;
28110
28111 /*
28112 * the 6 schemas callback have to go to the splitter functions
28113 * Note that we use the same text-function for ignorableWhitespace
28114 * if possible, to prevent the parser from testing for ignorable
28115 * whitespace.
28116 */
28117 ret->schemas_sax.characters = charactersSplit;
28118 if ((old_sax->ignorableWhitespace != NULL) &&
28119 (old_sax->ignorableWhitespace != old_sax->characters))
28120 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28121 else
28122 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28123 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28124 ret->schemas_sax.reference = referenceSplit;
28125 ret->schemas_sax.startElementNs = startElementNsSplit;
28126 ret->schemas_sax.endElementNs = endElementNsSplit;
28127
28128 ret->user_data_ptr = user_data;
28129 ret->user_data = *user_data;
28130 *user_data = ret;
28131 }
28132
28133 /*
28134 * plug the pointers back.
28135 */
28136 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028137 ctxt->sax = *sax;
28138 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28139 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028140 return(ret);
28141}
28142
28143/**
28144 * xmlSchemaSAXUnplug:
28145 * @plug: a data structure returned by xmlSchemaSAXPlug
28146 *
28147 * Unplug a SAX based validation layer in a SAX parsing event flow.
28148 * The original pointers used in the call are restored.
28149 *
28150 * Returns 0 in case of success and -1 in case of failure.
28151 */
28152int
28153xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28154{
28155 xmlSAXHandlerPtr *sax;
28156 void **user_data;
28157
28158 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28159 return(-1);
28160 plug->magic = 0;
28161
Daniel Veillardf10ae122005-07-10 19:03:16 +000028162 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028163 /* restore the data */
28164 sax = plug->user_sax_ptr;
28165 *sax = plug->user_sax;
28166 if (plug->user_sax != NULL) {
28167 user_data = plug->user_data_ptr;
28168 *user_data = plug->user_data;
28169 }
28170
28171 /* free and return */
28172 xmlFree(plug);
28173 return(0);
28174}
28175
28176/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028177 * xmlSchemaValidateStream:
28178 * @ctxt: a schema validation context
28179 * @input: the input to use for reading the data
28180 * @enc: an optional encoding information
28181 * @sax: a SAX handler for the resulting events
28182 * @user_data: the context to provide to the SAX handler.
28183 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028184 * Validate an input based on a flow of SAX event from the parser
28185 * and forward the events to the @sax handler with the provided @user_data
28186 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028187 *
28188 * Returns 0 if the document is schemas valid, a positive error code
28189 * number otherwise and -1 in case of internal or API error.
28190 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028191int
Daniel Veillard4255d502002-04-16 15:50:10 +000028192xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028193 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28194 xmlSAXHandlerPtr sax, void *user_data)
28195{
Daniel Veillard971771e2005-07-09 17:32:57 +000028196 xmlSchemaSAXPlugPtr plug = NULL;
28197 xmlSAXHandlerPtr old_sax = NULL;
28198 xmlParserCtxtPtr pctxt = NULL;
28199 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028200 int ret;
28201
Daniel Veillard4255d502002-04-16 15:50:10 +000028202 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028203 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028204
Daniel Veillardcdc82732005-07-08 15:04:06 +000028205 /*
28206 * prepare the parser
28207 */
28208 pctxt = xmlNewParserCtxt();
28209 if (pctxt == NULL)
28210 return (-1);
28211 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028212 pctxt->sax = sax;
28213 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028214#if 0
28215 if (options)
28216 xmlCtxtUseOptions(pctxt, options);
28217#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028218 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028219
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028220 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028221 if (inputStream == NULL) {
28222 ret = -1;
28223 goto done;
28224 }
28225 inputPush(pctxt, inputStream);
28226 ctxt->parserCtxt = pctxt;
28227 ctxt->input = input;
28228
28229 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028230 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028231 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028232 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28233 if (plug == NULL) {
28234 ret = -1;
28235 goto done;
28236 }
28237 ctxt->input = input;
28238 ctxt->enc = enc;
28239 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028240 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28241 ret = xmlSchemaVStart(ctxt);
28242
28243 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28244 ret = ctxt->parserCtxt->errNo;
28245 if (ret == 0)
28246 ret = 1;
28247 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028248
28249done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028250 ctxt->parserCtxt = NULL;
28251 ctxt->sax = NULL;
28252 ctxt->input = NULL;
28253 if (plug != NULL) {
28254 xmlSchemaSAXUnplug(plug);
28255 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028256 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028257 if (pctxt != NULL) {
28258 pctxt->sax = old_sax;
28259 xmlFreeParserCtxt(pctxt);
28260 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028261 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028262}
28263
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028264/**
28265 * xmlSchemaValidateFile:
28266 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028267 * @filename: the URI of the instance
28268 * @options: a future set of options, currently unused
28269 *
28270 * Do a schemas validation of the given resource, it will use the
28271 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028272 *
28273 * Returns 0 if the document is valid, a positive error code
28274 * number otherwise and -1 in case of an internal or API error.
28275 */
28276int
28277xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028278 const char * filename,
28279 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028280{
28281 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028282 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028283
28284 if ((ctxt == NULL) || (filename == NULL))
28285 return (-1);
28286
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028287 input = xmlParserInputBufferCreateFilename(filename,
28288 XML_CHAR_ENCODING_NONE);
28289 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028290 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028291 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28292 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028293 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028294}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028295
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028296#define bottom_xmlschemas
28297#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028298#endif /* LIBXML_SCHEMAS_ENABLED */