blob: ee22a6da87d42f5fe5a8f0d9d41ced08a1a459b9 [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
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000087/* #define WXS_ELEM_DECL_CONS_ENABLED */
88
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000089#ifdef DEBUG_IDC
90 #ifndef DEBUG_IDC_NODE_TABLE
91 #define DEBUG_IDC_NODE_TABLE
92 #endif
Daniel Veillarddee23482008-04-11 12:58:43 +000093#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000094
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000095/* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000097#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000098
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000099/* #define ENABLE_NAMED_LOCALS */
100
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +0000101/* #define ENABLE_IDC_NODE_TABLES_TEST */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000102
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000103#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000104
105#ifdef LIBXML_READER_ENABLED
106/* #define XML_SCHEMA_READER_ENABLED */
107#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000108
Daniel Veillard4255d502002-04-16 15:50:10 +0000109#define UNBOUNDED (1 << 30)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800110#define TODO \
Daniel Veillard4255d502002-04-16 15:50:10 +0000111 xmlGenericError(xmlGenericErrorContext, \
112 "Unimplemented block at %s:%d\n", \
113 __FILE__, __LINE__);
114
William M. Brack2f2a6632004-08-20 23:09:47 +0000115#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000116
Daniel Veillard4255d502002-04-16 15:50:10 +0000117/*
118 * The XML Schemas namespaces
119 */
120static const xmlChar *xmlSchemaNs = (const xmlChar *)
121 "http://www.w3.org/2001/XMLSchema";
122
123static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124 "http://www.w3.org/2001/XMLSchema-instance";
125
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000126static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127 "http://www.w3.org/2000/xmlns/";
128
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000129/*
130* Come casting macros.
131*/
132#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +0000133#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000135#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137#define WXS_PTC_CAST (xmlSchemaParticlePtr)
138#define WXS_TYPE_CAST (xmlSchemaTypePtr)
139#define WXS_ELEM_CAST (xmlSchemaElementPtr)
140#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146#define WXS_IDC_CAST (xmlSchemaIDCPtr)
147#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000149
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000150/*
151* Macros to query common properties of components.
152*/
153#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000154
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000155#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156/*
157* Macros for element declarations.
158*/
159#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000160
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000161#define WXS_SUBST_HEAD(item) (item)->refDecl
162/*
163* Macros for attribute declarations.
164*/
165#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166/*
167* Macros for attribute uses.
168*/
169#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000170
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000171#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000172
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000173#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174
175#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176/*
177* Macros for attribute groups.
178*/
179#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181/*
182* Macros for particles.
183*/
184#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185
186#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000188#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000190#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191/*
192* Macros for model groups definitions.
193*/
194#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195/*
196* Macros for model groups.
197*/
198#define WXS_IS_MODEL_GROUP(i) \
199 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201 ((i)->type == XML_SCHEMA_TYPE_ALL))
202
203#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204/*
205* Macros for schema buckets.
206*/
207#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209
210#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212
213#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214
215#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216/*
217* Macros for complex/simple types.
218*/
219#define WXS_IS_ANYTYPE(i) \
220 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_COMPLEX(i) \
224 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226
227#define WXS_IS_SIMPLE(item) \
228 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000230 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000232#define WXS_IS_ANY_SIMPLE_TYPE(i) \
233 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000235
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000236#define WXS_IS_RESTRICTION(t) \
237 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000238
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000239#define WXS_IS_EXTENSION(t) \
240 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241
242#define WXS_IS_TYPE_NOT_FIXED(i) \
243 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245
246#define WXS_IS_TYPE_NOT_FIXED_1(item) \
247 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000248 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000249
250#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251
252#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000253/*
254* Macros for exclusively for complex types.
255*/
256#define WXS_HAS_COMPLEX_CONTENT(item) \
257 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000259 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000261#define WXS_HAS_SIMPLE_CONTENT(item) \
262 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000263 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000265#define WXS_HAS_MIXED_CONTENT(item) \
266 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000267
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000268#define WXS_EMPTIABLE(t) \
269 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000270
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000271#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000272
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000273#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276/*
277* Macros for exclusively for simple types.
278*/
279#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000280
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000281#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000282
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000283#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000284
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000285#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286/*
287* Misc parser context macros.
288*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000289#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290
291#define WXS_HAS_BUCKETS(ctx) \
292( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294
295#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000297#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000298
299#define WXS_SCHEMA(ctx) (ctx)->schema
300
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000301#define WXS_ADD_LOCAL(ctx, item) \
302 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000303
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000304#define WXS_ADD_GLOBAL(ctx, item) \
305 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000306
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000307#define WXS_ADD_PENDING(ctx, item) \
308 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000310* xmlSchemaItemList macros.
311*/
312#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000314* Misc macros.
315*/
316#define IS_SCHEMA(node, type) \
317 ((node != NULL) && (node->ns != NULL) && \
318 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000320
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000321#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000322
323/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000324* Since we put the default/fixed values into the dict, we can
325* use pointer comparison for those values.
326* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000327*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000328#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000329
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000330#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000331
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000332#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000333
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000334#define HFAILURE if (res == -1) goto exit_failure;
335
336#define HERROR if (res != 0) goto exit_error;
337
338#define HSTOP(ctx) if ((ctx)->stop) goto exit;
339/*
340* Some flags used for various schema constraints.
341*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000342#define SUBSET_RESTRICTION 1<<0
343#define SUBSET_EXTENSION 1<<1
344#define SUBSET_SUBSTITUTION 1<<2
345#define SUBSET_LIST 1<<3
346#define SUBSET_UNION 1<<4
347
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000348typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000350
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351typedef struct _xmlSchemaItemList xmlSchemaItemList;
352typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000353struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000354 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000355 int nbItems; /* used for dynamic addition of schemata */
356 int sizeItems; /* used for dynamic addition of schemata */
357};
358
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000359#define XML_SCHEMA_CTXT_PARSER 1
360#define XML_SCHEMA_CTXT_VALIDATOR 2
361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000362typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000365 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000366};
367
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000368typedef struct _xmlSchemaBucket xmlSchemaBucket;
369typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371#define XML_SCHEMA_SCHEMA_MAIN 0
372#define XML_SCHEMA_SCHEMA_IMPORT 1
373#define XML_SCHEMA_SCHEMA_INCLUDE 2
374#define XML_SCHEMA_SCHEMA_REDEFINE 3
375
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000376/**
Daniel Veillarddee23482008-04-11 12:58:43 +0000377 * xmlSchemaSchemaRelation:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000378 *
379 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000380 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000381typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383struct _xmlSchemaSchemaRelation {
384 xmlSchemaSchemaRelationPtr next;
385 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386 const xmlChar *importNamespace;
387 xmlSchemaBucketPtr bucket;
388};
389
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000390#define XML_SCHEMA_BUCKET_MARKED 1<<0
391#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000393struct _xmlSchemaBucket {
394 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000395 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000396 const xmlChar *schemaLocation;
397 const xmlChar *origTargetNamespace;
398 const xmlChar *targetNamespace;
399 xmlDocPtr doc;
400 xmlSchemaSchemaRelationPtr relations;
401 int located;
402 int parsed;
403 int imported;
404 int preserveDoc;
Daniel Veillarddee23482008-04-11 12:58:43 +0000405 xmlSchemaItemListPtr globals; /* Global components. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000406 xmlSchemaItemListPtr locals; /* Local components. */
407};
408
409/**
Daniel Veillarddee23482008-04-11 12:58:43 +0000410 * xmlSchemaImport:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000411 * (extends xmlSchemaBucket)
412 *
413 * Reflects a schema. Holds some information
414 * about the schema and its toplevel components. Duplicate
415 * toplevel components are not checked at this level.
416 */
417typedef struct _xmlSchemaImport xmlSchemaImport;
418typedef xmlSchemaImport *xmlSchemaImportPtr;
419struct _xmlSchemaImport {
420 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000421 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000422 const xmlChar *schemaLocation; /* The URI of the schema document. */
423 /* For chameleon includes, @origTargetNamespace will be NULL */
424 const xmlChar *origTargetNamespace;
Daniel Veillarddee23482008-04-11 12:58:43 +0000425 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000426 * For chameleon includes, @targetNamespace will be the
Daniel Veillarddee23482008-04-11 12:58:43 +0000427 * targetNamespace of the including schema.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000428 */
429 const xmlChar *targetNamespace;
430 xmlDocPtr doc; /* The schema node-tree. */
431 /* @relations will hold any included/imported/redefined schemas. */
432 xmlSchemaSchemaRelationPtr relations;
433 int located;
434 int parsed;
435 int imported;
436 int preserveDoc;
437 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000438 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000439 /* The imported schema. */
440 xmlSchemaPtr schema;
441};
442
443/*
444* (extends xmlSchemaBucket)
445*/
446typedef struct _xmlSchemaInclude xmlSchemaInclude;
447typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448struct _xmlSchemaInclude {
449 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000450 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000451 const xmlChar *schemaLocation;
452 const xmlChar *origTargetNamespace;
453 const xmlChar *targetNamespace;
454 xmlDocPtr doc;
455 xmlSchemaSchemaRelationPtr relations;
456 int located;
457 int parsed;
458 int imported;
459 int preserveDoc;
Daniel Veillarddee23482008-04-11 12:58:43 +0000460 xmlSchemaItemListPtr globals; /* Global components. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000461 xmlSchemaItemListPtr locals; /* Local components. */
462
463 /* The owning main or import schema bucket. */
464 xmlSchemaImportPtr ownerImport;
465};
466
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000467/**
468 * xmlSchemaBasicItem:
469 *
470 * The abstract base type for schema components.
471 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000472typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474struct _xmlSchemaBasicItem {
475 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000476};
477
478/**
479 * xmlSchemaAnnotItem:
480 *
481 * The abstract base type for annotated schema components.
482 * (Extends xmlSchemaBasicItem)
483 */
484typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486struct _xmlSchemaAnnotItem {
487 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000488 xmlSchemaAnnotPtr annot;
489};
490
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000491/**
492 * xmlSchemaTreeItem:
493 *
494 * The abstract base type for tree-like structured schema components.
495 * (Extends xmlSchemaAnnotItem)
496 */
497typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499struct _xmlSchemaTreeItem {
500 xmlSchemaTypeType type;
501 xmlSchemaAnnotPtr annot;
502 xmlSchemaTreeItemPtr next;
503 xmlSchemaTreeItemPtr children;
504};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000505
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000506
507#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508/**
509 * xmlSchemaAttributeUsePtr:
510 *
511 * The abstract base type for tree-like structured schema components.
512 * (Extends xmlSchemaTreeItem)
513 */
514typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516struct _xmlSchemaAttributeUse {
517 xmlSchemaTypeType type;
518 xmlSchemaAnnotPtr annot;
519 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000520 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000521 * The attr. decl. OR a QName-ref. to an attr. decl. OR
522 * a QName-ref. to an attribute group definition.
523 */
524 xmlSchemaAttributePtr attrDecl;
525
526 int flags;
527 xmlNodePtr node;
528 int occurs; /* required, optional */
529 const xmlChar * defValue;
530 xmlSchemaValPtr defVal;
531};
532
533/**
534 * xmlSchemaAttributeUseProhibPtr:
535 *
536 * A helper component to reflect attribute prohibitions.
537 * (Extends xmlSchemaBasicItem)
538 */
539typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541struct _xmlSchemaAttributeUseProhib {
542 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543 xmlNodePtr node;
544 const xmlChar *name;
545 const xmlChar *targetNamespace;
546 int isRef;
547};
548
549/**
550 * xmlSchemaRedef:
551 */
552typedef struct _xmlSchemaRedef xmlSchemaRedef;
553typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554struct _xmlSchemaRedef {
555 xmlSchemaRedefPtr next;
556 xmlSchemaBasicItemPtr item; /* The redefining component. */
557 xmlSchemaBasicItemPtr reference; /* The referencing component. */
558 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559 const xmlChar *refName; /* The name of the to-be-redefined component. */
560 const xmlChar *refTargetNs; /* The target namespace of the
561 to-be-redefined comp. */
562 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563};
564
565/**
566 * xmlSchemaConstructionCtxt:
567 */
568typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570struct _xmlSchemaConstructionCtxt {
571 xmlSchemaPtr mainSchema; /* The main schema. */
572 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573 xmlDictPtr dict;
574 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000576 xmlSchemaBucketPtr bucket; /* The current schema bucket */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000577 xmlSchemaItemListPtr pending; /* All Components of all schemas that
578 need to be fixed. */
579 xmlHashTablePtr substGroups;
580 xmlSchemaRedefPtr redefs;
581 xmlSchemaRedefPtr lastRedef;
582};
583
584#define XML_SCHEMAS_PARSE_ERROR 1
585#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586
587struct _xmlSchemaParserCtxt {
588 int type;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +0000589 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000590 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
591 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Kasimier T. Buchcikdfbc33a2006-01-03 10:51:59 +0000592 int err;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000593 int nberrors;
594 xmlStructuredErrorFunc serror;
595
596 xmlSchemaConstructionCtxtPtr constructor;
597 int ownsConstructor; /* TODO: Move this to parser *flags*. */
598
599 /* xmlSchemaPtr topschema; */
600 /* xmlHashTablePtr namespaces; */
601
602 xmlSchemaPtr schema; /* The main schema in use */
603 int counter;
604
605 const xmlChar *URL;
606 xmlDocPtr doc;
607 int preserve; /* Whether the doc should be freed */
608
609 const char *buffer;
610 int size;
611
612 /*
613 * Used to build complex element content models
614 */
615 xmlAutomataPtr am;
616 xmlAutomataStatePtr start;
617 xmlAutomataStatePtr end;
618 xmlAutomataStatePtr state;
619
Jan Pokornýbb654fe2016-04-13 16:56:07 +0200620 xmlDictPtr dict; /* dictionary for interned string names */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000621 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622 int options;
623 xmlSchemaValidCtxtPtr vctxt;
624 int isS4S;
625 int isRedefine;
626 int xsiAssemble;
627 int stop; /* If the parser should stop; i.e. a critical error. */
628 const xmlChar *targetNamespace;
629 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630
631 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000632 int redefCounter; /* Used for redefinitions. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000633 xmlSchemaItemListPtr attrProhibs;
634};
635
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000636/**
637 * xmlSchemaQNameRef:
638 *
639 * A component reference item (not a schema component)
640 * (Extends xmlSchemaBasicItem)
641 */
642typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644struct _xmlSchemaQNameRef {
645 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000646 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000647 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 const xmlChar *name;
649 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000650 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651};
652
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000653/**
654 * xmlSchemaParticle:
655 *
656 * A particle component.
657 * (Extends xmlSchemaTreeItem)
658 */
659typedef struct _xmlSchemaParticle xmlSchemaParticle;
660typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661struct _xmlSchemaParticle {
662 xmlSchemaTypeType type;
663 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000664 xmlSchemaTreeItemPtr next; /* next particle */
665 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000668 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000670 xmlNodePtr node;
671};
672
673/**
674 * xmlSchemaModelGroup:
675 *
676 * A model group component.
677 * (Extends xmlSchemaTreeItem)
678 */
679typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681struct _xmlSchemaModelGroup {
682 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683 xmlSchemaAnnotPtr annot;
684 xmlSchemaTreeItemPtr next; /* not used */
685 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686 xmlNodePtr node;
687};
688
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000689#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000690#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000691/**
692 * xmlSchemaModelGroupDef:
693 *
694 * A model group definition component.
695 * (Extends xmlSchemaTreeItem)
696 */
697typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699struct _xmlSchemaModelGroupDef {
700 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701 xmlSchemaAnnotPtr annot;
702 xmlSchemaTreeItemPtr next; /* not used */
703 xmlSchemaTreeItemPtr children; /* the "model group" */
704 const xmlChar *name;
705 const xmlChar *targetNamespace;
706 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000707 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000708};
709
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000710typedef struct _xmlSchemaIDC xmlSchemaIDC;
711typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713/**
714 * xmlSchemaIDCSelect:
715 *
716 * The identity-constraint "field" and "selector" item, holding the
717 * XPath expression.
718 */
719typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000721struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000722 xmlSchemaIDCSelectPtr next;
723 xmlSchemaIDCPtr idc;
724 int index; /* an index position if significant for IDC key-sequences */
725 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000726 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000727};
728
729/**
730 * xmlSchemaIDC:
731 *
732 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000733 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 */
735
736struct _xmlSchemaIDC {
737 xmlSchemaTypeType type;
738 xmlSchemaAnnotPtr annot;
739 xmlSchemaIDCPtr next;
740 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000741 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000742 const xmlChar *targetNamespace;
743 xmlSchemaIDCSelectPtr selector;
744 xmlSchemaIDCSelectPtr fields;
745 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000746 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000747};
748
749/**
750 * xmlSchemaIDCAug:
751 *
752 * The augmented IDC information used for validation.
753 */
754typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756struct _xmlSchemaIDCAug {
757 xmlSchemaIDCAugPtr next; /* next in a list */
758 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000759 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000760 tables need to be bubbled upwards */
761};
762
763/**
764 * xmlSchemaPSVIIDCKeySequence:
765 *
766 * The key sequence of a node table item.
767 */
768typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770struct _xmlSchemaPSVIIDCKey {
771 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000772 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000773};
774
775/**
776 * xmlSchemaPSVIIDCNode:
777 *
778 * The node table item of a node table.
779 */
780typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782struct _xmlSchemaPSVIIDCNode {
783 xmlNodePtr node;
784 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000785 int nodeLine;
Daniel Veillarddee23482008-04-11 12:58:43 +0000786 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000787
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000788};
789
790/**
791 * xmlSchemaPSVIIDCBinding:
792 *
793 * The identity-constraint binding item of the [identity-constraint table].
794 */
795typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797struct _xmlSchemaPSVIIDCBinding {
798 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799 xmlSchemaIDCPtr definition; /* the IDC definition */
800 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801 int nbNodes; /* number of entries in the node table */
802 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000803 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000804};
805
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000806
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000807#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810#define XPATH_STATE_OBJ_MATCHES -2
811#define XPATH_STATE_OBJ_BLOCKED -3
812
813typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816/**
817 * xmlSchemaIDCStateObj:
818 *
819 * The state object used to evaluate XPath expressions.
820 */
821typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000824 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000825 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000826 int depth; /* depth of creation */
827 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000828 int nbHistory;
829 int sizeHistory;
830 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831 matcher */
832 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000833 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000834};
835
836#define IDC_MATCHER 0
837
838/**
839 * xmlSchemaIDCMatcher:
840 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000841 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000842 */
843struct _xmlSchemaIDCMatcher {
844 int type;
845 int depth; /* the tree depth at creation time */
846 xmlSchemaIDCMatcherPtr next; /* next in the list */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000847 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000848 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000849 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000850 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851 elements */
852 int sizeKeySeqs;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000853 xmlSchemaItemListPtr targets; /* list of target-node
854 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000855};
856
857/*
858* Element info flags.
859*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000860#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
861#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
863#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
864
865#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
866#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
867#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
868
869#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
870#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
871#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
872#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000873
874/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000875 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000876 *
877 * Holds information of an element node.
878 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000879struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000880 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000881 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000882 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000883 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000884 const xmlChar *nsName;
885 const xmlChar *value;
886 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000887 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000888
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000889 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000890
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000891 int valNeeded;
892 int normVal;
893
894 xmlSchemaElementPtr decl; /* the element/attribute declaration */
895 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000896 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897 for the scope element*/
898 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000900 xmlRegExecCtxtPtr regexCtxt;
901
902 const xmlChar **nsBindings; /* Namespace bindings on this element */
903 int nbNsBindings;
Daniel Veillarddee23482008-04-11 12:58:43 +0000904 int sizeNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000905
906 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000907 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000908};
909
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000910#define XML_SCHEMAS_ATTR_UNKNOWN 1
911#define XML_SCHEMAS_ATTR_ASSESSED 2
912#define XML_SCHEMAS_ATTR_PROHIBITED 3
913#define XML_SCHEMAS_ATTR_ERR_MISSING 4
914#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917#define XML_SCHEMAS_ATTR_DEFAULT 8
918#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922#define XML_SCHEMAS_ATTR_WILD_SKIP 13
923#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000927/*
928* @metaType values of xmlSchemaAttrInfo.
929*/
930#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000935
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000936typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000939 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000940 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000941 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000942 const xmlChar *localName;
943 const xmlChar *nsName;
944 const xmlChar *value;
945 xmlSchemaValPtr val; /* the pre-computed value if any */
946 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947 int flags; /* combination of node info flags */
948
949 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000950 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000951 int state;
952 int metaType;
953 const xmlChar *vcValue; /* the value constraint value */
954 xmlSchemaNodeInfoPtr parent;
955};
956
957
958#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000959/**
960 * xmlSchemaValidCtxt:
961 *
962 * A Schemas validation context
963 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000964struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000965 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000966 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000967 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000968 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000969 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000970
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000971 xmlSchemaPtr schema; /* The schema in use */
972 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000973 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000974 xmlCharEncoding enc;
975 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000976 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000977 void *user_data; /* TODO: What is this for? */
Daniel Veillard97fa5b32012-08-14 11:01:07 +0800978 char *filename;
Daniel Veillard4255d502002-04-16 15:50:10 +0000979
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000980 int err;
981 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000982
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000983 xmlNodePtr node;
984 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000985 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000986
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000987 xmlRegExecCtxtPtr regexp;
988 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000989
Daniel Veillardc0826a72004-08-10 14:17:33 +0000990 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000991 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000992 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000993 xmlSchemaParserCtxtPtr pctxt;
994 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000995
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000996 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000997 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000998 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000999 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001000
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001001 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1002
1003 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1004 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +00001005 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001006
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001007 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1008 int nbIdcNodes;
1009 int sizeIdcNodes;
1010
1011 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1012 int nbIdcKeys;
1013 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001014
1015 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001016
1017 xmlDictPtr dict;
1018
Daniel Veillard39e5c892005-07-03 22:48:50 +00001019#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001020 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001021#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001022
1023 xmlSchemaAttrInfoPtr *attrInfos;
1024 int nbAttrInfos;
1025 int sizeAttrInfos;
1026
1027 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001028 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001029 int hasKeyrefs;
1030 int createIDCNodeTables;
1031 int psviExposeIDCNodeTables;
Daniel Veillard97fa5b32012-08-14 11:01:07 +08001032
1033 /* Locator for error reporting in streaming mode */
1034 xmlSchemaValidityLocatorFunc locFunc;
1035 void *locCtxt;
Daniel Veillard4255d502002-04-16 15:50:10 +00001036};
1037
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001038/**
1039 * xmlSchemaSubstGroup:
1040 *
1041 *
1042 */
1043typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1044typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1045struct _xmlSchemaSubstGroup {
1046 xmlSchemaElementPtr head;
1047 xmlSchemaItemListPtr members;
1048};
1049
Daniel Veillard4255d502002-04-16 15:50:10 +00001050/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001051 * *
1052 * Some predeclarations *
1053 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00001054 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001055
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001056static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1057 xmlSchemaPtr schema,
1058 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001059static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1060 xmlSchemaPtr schema,
1061 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001062static int
1063xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001064 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001065static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001066xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1067static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001068xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1069 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001070static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001071xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1072 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001073static void
1074xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001075static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001076xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001077static xmlSchemaTreeItemPtr
1078xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1079 xmlNodePtr node, xmlSchemaTypeType type,
1080 int withParticle);
1081static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001082xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001083static xmlSchemaTypeLinkPtr
1084xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001085static void
1086xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1087 const char *funcName,
1088 const char *message);
1089static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001090xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001091 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001092 xmlSchemaTypePtr baseType,
1093 int subset);
1094static void
1095xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001096 xmlSchemaParserCtxtPtr ctxt);
1097static void
1098xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001099static xmlSchemaQNameRefPtr
1100xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1101 xmlSchemaPtr schema,
1102 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001103
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001104/************************************************************************
1105 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001106 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001107 * *
1108 ************************************************************************/
1109
1110/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001111 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001112 * @type: the type of the schema item
1113 *
1114 * Returns the component name of a schema item.
1115 */
1116static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001117xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001118{
1119 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001120 case XML_SCHEMA_TYPE_BASIC:
1121 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001122 case XML_SCHEMA_TYPE_SIMPLE:
1123 return(BAD_CAST "simple type definition");
1124 case XML_SCHEMA_TYPE_COMPLEX:
1125 return(BAD_CAST "complex type definition");
1126 case XML_SCHEMA_TYPE_ELEMENT:
1127 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001128 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1129 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001130 case XML_SCHEMA_TYPE_ATTRIBUTE:
1131 return(BAD_CAST "attribute declaration");
1132 case XML_SCHEMA_TYPE_GROUP:
1133 return(BAD_CAST "model group definition");
1134 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1135 return(BAD_CAST "attribute group definition");
1136 case XML_SCHEMA_TYPE_NOTATION:
1137 return(BAD_CAST "notation declaration");
1138 case XML_SCHEMA_TYPE_SEQUENCE:
1139 return(BAD_CAST "model group (sequence)");
1140 case XML_SCHEMA_TYPE_CHOICE:
1141 return(BAD_CAST "model group (choice)");
1142 case XML_SCHEMA_TYPE_ALL:
1143 return(BAD_CAST "model group (all)");
1144 case XML_SCHEMA_TYPE_PARTICLE:
1145 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001146 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001147 return(BAD_CAST "unique identity-constraint");
1148 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001149 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001150 return(BAD_CAST "key identity-constraint");
1151 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001152 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001153 return(BAD_CAST "keyref identity-constraint");
1154 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001155 case XML_SCHEMA_TYPE_ANY:
1156 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001157 case XML_SCHEMA_EXTRA_QNAMEREF:
1158 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001159 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1160 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001161 default:
1162 return(BAD_CAST "Not a schema component");
1163 }
1164}
1165
1166/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001167 * xmlSchemaGetComponentTypeStr:
1168 * @type: the type of the schema item
1169 *
1170 * Returns the component name of a schema item.
1171 */
1172static const xmlChar *
1173xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1174{
1175 switch (item->type) {
1176 case XML_SCHEMA_TYPE_BASIC:
1177 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1178 return(BAD_CAST "complex type definition");
1179 else
Daniel Veillarddee23482008-04-11 12:58:43 +00001180 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001181 default:
1182 return(xmlSchemaItemTypeToStr(item->type));
1183 }
1184}
1185
1186/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001187 * xmlSchemaGetComponentNode:
1188 * @item: a schema component
1189 *
1190 * Returns node associated with the schema component.
1191 * NOTE that such a node need not be available; plus, a component's
1192 * node need not to reflect the component directly, since there is no
1193 * one-to-one relationship between the XML Schema representation and
1194 * the component representation.
1195 */
1196static xmlNodePtr
1197xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1198{
1199 switch (item->type) {
1200 case XML_SCHEMA_TYPE_ELEMENT:
1201 return (((xmlSchemaElementPtr) item)->node);
1202 case XML_SCHEMA_TYPE_ATTRIBUTE:
1203 return (((xmlSchemaAttributePtr) item)->node);
1204 case XML_SCHEMA_TYPE_COMPLEX:
1205 case XML_SCHEMA_TYPE_SIMPLE:
1206 return (((xmlSchemaTypePtr) item)->node);
1207 case XML_SCHEMA_TYPE_ANY:
1208 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1209 return (((xmlSchemaWildcardPtr) item)->node);
1210 case XML_SCHEMA_TYPE_PARTICLE:
1211 return (((xmlSchemaParticlePtr) item)->node);
1212 case XML_SCHEMA_TYPE_SEQUENCE:
1213 case XML_SCHEMA_TYPE_CHOICE:
1214 case XML_SCHEMA_TYPE_ALL:
1215 return (((xmlSchemaModelGroupPtr) item)->node);
1216 case XML_SCHEMA_TYPE_GROUP:
1217 return (((xmlSchemaModelGroupDefPtr) item)->node);
1218 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1219 return (((xmlSchemaAttributeGroupPtr) item)->node);
1220 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1221 case XML_SCHEMA_TYPE_IDC_KEY:
1222 case XML_SCHEMA_TYPE_IDC_KEYREF:
1223 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001224 case XML_SCHEMA_EXTRA_QNAMEREF:
1225 return(((xmlSchemaQNameRefPtr) item)->node);
1226 /* TODO: What to do with NOTATIONs?
1227 case XML_SCHEMA_TYPE_NOTATION:
1228 return (((xmlSchemaNotationPtr) item)->node);
1229 */
1230 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1231 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001232 default:
1233 return (NULL);
1234 }
1235}
1236
1237#if 0
1238/**
1239 * xmlSchemaGetNextComponent:
1240 * @item: a schema component
1241 *
1242 * Returns the next sibling of the schema component.
1243 */
1244static xmlSchemaBasicItemPtr
1245xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1246{
1247 switch (item->type) {
1248 case XML_SCHEMA_TYPE_ELEMENT:
1249 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1250 case XML_SCHEMA_TYPE_ATTRIBUTE:
1251 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1252 case XML_SCHEMA_TYPE_COMPLEX:
1253 case XML_SCHEMA_TYPE_SIMPLE:
1254 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1255 case XML_SCHEMA_TYPE_ANY:
1256 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1257 return (NULL);
1258 case XML_SCHEMA_TYPE_PARTICLE:
1259 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1260 case XML_SCHEMA_TYPE_SEQUENCE:
1261 case XML_SCHEMA_TYPE_CHOICE:
1262 case XML_SCHEMA_TYPE_ALL:
1263 return (NULL);
1264 case XML_SCHEMA_TYPE_GROUP:
1265 return (NULL);
1266 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1267 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1268 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1269 case XML_SCHEMA_TYPE_IDC_KEY:
1270 case XML_SCHEMA_TYPE_IDC_KEYREF:
1271 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1272 default:
1273 return (NULL);
1274 }
1275}
1276#endif
1277
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001278
1279/**
1280 * xmlSchemaFormatQName:
1281 * @buf: the string buffer
1282 * @namespaceName: the namespace name
1283 * @localName: the local name
1284 *
1285 * Returns the given QName in the format "{namespaceName}localName" or
1286 * just "localName" if @namespaceName is NULL.
1287 *
1288 * Returns the localName if @namespaceName is NULL, a formatted
1289 * string otherwise.
1290 */
1291static const xmlChar*
1292xmlSchemaFormatQName(xmlChar **buf,
1293 const xmlChar *namespaceName,
1294 const xmlChar *localName)
1295{
1296 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001297 if (namespaceName != NULL) {
1298 *buf = xmlStrdup(BAD_CAST "{");
1299 *buf = xmlStrcat(*buf, namespaceName);
1300 *buf = xmlStrcat(*buf, BAD_CAST "}");
1301 }
1302 if (localName != NULL) {
1303 if (namespaceName == NULL)
1304 return(localName);
1305 *buf = xmlStrcat(*buf, localName);
1306 } else {
1307 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
Daniel Veillarddee23482008-04-11 12:58:43 +00001308 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001309 return ((const xmlChar *) *buf);
1310}
1311
Daniel Veillarddee23482008-04-11 12:58:43 +00001312static const xmlChar*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001313xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1314{
1315 if (ns != NULL)
1316 return (xmlSchemaFormatQName(buf, ns->href, localName));
1317 else
1318 return (xmlSchemaFormatQName(buf, NULL, localName));
1319}
1320
1321static const xmlChar *
1322xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1323{
1324 switch (item->type) {
1325 case XML_SCHEMA_TYPE_ELEMENT:
1326 return (((xmlSchemaElementPtr) item)->name);
1327 case XML_SCHEMA_TYPE_ATTRIBUTE:
1328 return (((xmlSchemaAttributePtr) item)->name);
1329 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1330 return (((xmlSchemaAttributeGroupPtr) item)->name);
1331 case XML_SCHEMA_TYPE_BASIC:
1332 case XML_SCHEMA_TYPE_SIMPLE:
1333 case XML_SCHEMA_TYPE_COMPLEX:
1334 return (((xmlSchemaTypePtr) item)->name);
1335 case XML_SCHEMA_TYPE_GROUP:
1336 return (((xmlSchemaModelGroupDefPtr) item)->name);
1337 case XML_SCHEMA_TYPE_IDC_KEY:
1338 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1339 case XML_SCHEMA_TYPE_IDC_KEYREF:
1340 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001341 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1342 if (WXS_ATTRUSE_DECL(item) != NULL) {
1343 return(xmlSchemaGetComponentName(
1344 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1345 } else
1346 return(NULL);
1347 case XML_SCHEMA_EXTRA_QNAMEREF:
1348 return (((xmlSchemaQNameRefPtr) item)->name);
1349 case XML_SCHEMA_TYPE_NOTATION:
1350 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001351 default:
1352 /*
1353 * Other components cannot have names.
1354 */
1355 break;
1356 }
1357 return (NULL);
1358}
1359
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001360#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1361#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1362/*
1363static const xmlChar *
1364xmlSchemaGetQNameRefName(void *ref)
1365{
1366 return(((xmlSchemaQNameRefPtr) ref)->name);
1367}
1368
1369static const xmlChar *
1370xmlSchemaGetQNameRefTargetNs(void *ref)
1371{
1372 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1373}
1374*/
1375
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001376static const xmlChar *
1377xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1378{
1379 switch (item->type) {
1380 case XML_SCHEMA_TYPE_ELEMENT:
1381 return (((xmlSchemaElementPtr) item)->targetNamespace);
1382 case XML_SCHEMA_TYPE_ATTRIBUTE:
1383 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1384 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1385 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1386 case XML_SCHEMA_TYPE_BASIC:
1387 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1388 case XML_SCHEMA_TYPE_SIMPLE:
1389 case XML_SCHEMA_TYPE_COMPLEX:
1390 return (((xmlSchemaTypePtr) item)->targetNamespace);
1391 case XML_SCHEMA_TYPE_GROUP:
1392 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1393 case XML_SCHEMA_TYPE_IDC_KEY:
1394 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1395 case XML_SCHEMA_TYPE_IDC_KEYREF:
1396 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001397 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1398 if (WXS_ATTRUSE_DECL(item) != NULL) {
1399 return(xmlSchemaGetComponentTargetNs(
1400 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1401 }
1402 /* TODO: Will returning NULL break something? */
1403 break;
1404 case XML_SCHEMA_EXTRA_QNAMEREF:
1405 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1406 case XML_SCHEMA_TYPE_NOTATION:
1407 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001408 default:
1409 /*
1410 * Other components cannot have names.
1411 */
1412 break;
1413 }
1414 return (NULL);
1415}
1416
1417static const xmlChar*
1418xmlSchemaGetComponentQName(xmlChar **buf,
1419 void *item)
1420{
1421 return (xmlSchemaFormatQName(buf,
1422 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1423 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1424}
1425
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001426static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001427xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001428{
1429 xmlChar *str = NULL;
1430
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001431 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001432 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001433 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1434 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001435 *buf = xmlStrcat(*buf, BAD_CAST "'");
1436 FREE_AND_NULL(str);
1437 return(*buf);
1438}
1439
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001440static const xmlChar*
1441xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1442{
1443 return(xmlSchemaGetComponentDesignation(buf, idc));
1444}
1445
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001446/**
1447 * xmlSchemaWildcardPCToString:
1448 * @pc: the type of processContents
1449 *
1450 * Returns a string representation of the type of
1451 * processContents.
1452 */
1453static const xmlChar *
1454xmlSchemaWildcardPCToString(int pc)
1455{
1456 switch (pc) {
1457 case XML_SCHEMAS_ANY_SKIP:
1458 return (BAD_CAST "skip");
1459 case XML_SCHEMAS_ANY_LAX:
1460 return (BAD_CAST "lax");
1461 case XML_SCHEMAS_ANY_STRICT:
1462 return (BAD_CAST "strict");
1463 default:
1464 return (BAD_CAST "invalid process contents");
1465 }
1466}
1467
1468/**
1469 * xmlSchemaGetCanonValueWhtspExt:
1470 * @val: the precomputed value
1471 * @retValue: the returned value
1472 * @ws: the whitespace type of the value
1473 *
Jan Pokorný7a7cad62013-11-29 23:26:26 +01001474 * Get a the canonical representation of the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001475 * The caller has to free the returned retValue.
1476 *
1477 * Returns 0 if the value could be built and -1 in case of
1478 * API errors or if the value type is not supported yet.
1479 */
1480static int
1481xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1482 xmlSchemaWhitespaceValueType ws,
1483 xmlChar **retValue)
1484{
1485 int list;
1486 xmlSchemaValType valType;
1487 const xmlChar *value, *value2 = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00001488
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001489
1490 if ((retValue == NULL) || (val == NULL))
1491 return (-1);
1492 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1493 *retValue = NULL;
1494 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00001495 value = NULL;
1496 valType = xmlSchemaGetValType(val);
1497 switch (valType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001498 case XML_SCHEMAS_STRING:
1499 case XML_SCHEMAS_NORMSTRING:
1500 case XML_SCHEMAS_ANYSIMPLETYPE:
1501 value = xmlSchemaValueGetAsString(val);
1502 if (value != NULL) {
1503 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1504 value2 = xmlSchemaCollapseString(value);
1505 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1506 value2 = xmlSchemaWhiteSpaceReplace(value);
1507 if (value2 != NULL)
1508 value = value2;
1509 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001510 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001511 default:
1512 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1513 if (value2 != NULL)
1514 xmlFree((xmlChar *) value2);
1515 goto internal_error;
1516 }
1517 value = value2;
1518 }
1519 if (*retValue == NULL)
1520 if (value == NULL) {
1521 if (! list)
1522 *retValue = xmlStrdup(BAD_CAST "");
1523 } else
1524 *retValue = xmlStrdup(value);
1525 else if (value != NULL) {
1526 /* List. */
1527 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1528 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1529 }
1530 FREE_AND_NULL(value2)
1531 val = xmlSchemaValueGetNext(val);
1532 } while (val != NULL);
1533
1534 return (0);
1535internal_error:
1536 if (*retValue != NULL)
1537 xmlFree((xmlChar *) (*retValue));
1538 if (value2 != NULL)
1539 xmlFree((xmlChar *) value2);
1540 return (-1);
1541}
1542
1543/**
1544 * xmlSchemaFormatItemForReport:
1545 * @buf: the string buffer
1546 * @itemDes: the designation of the item
1547 * @itemName: the name of the item
Daniel Veillarddee23482008-04-11 12:58:43 +00001548 * @item: the item as an object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001549 * @itemNode: the node of the item
1550 * @local: the local name
1551 * @parsing: if the function is used during the parse
1552 *
1553 * Returns a representation of the given item used
Daniel Veillarddee23482008-04-11 12:58:43 +00001554 * for error reports.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001555 *
Daniel Veillarddee23482008-04-11 12:58:43 +00001556 * The following order is used to build the resulting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001557 * designation if the arguments are not NULL:
1558 * 1a. If itemDes not NULL -> itemDes
1559 * 1b. If (itemDes not NULL) and (itemName not NULL)
1560 * -> itemDes + itemName
1561 * 2. If the preceding was NULL and (item not NULL) -> item
1562 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
Daniel Veillarddee23482008-04-11 12:58:43 +00001563 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001564 * If the itemNode is an attribute node, the name of the attribute
1565 * will be appended to the result.
1566 *
1567 * Returns the formatted string and sets @buf to the resulting value.
Daniel Veillarddee23482008-04-11 12:58:43 +00001568 */
1569static xmlChar*
1570xmlSchemaFormatItemForReport(xmlChar **buf,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001572 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001573 xmlNodePtr itemNode)
1574{
1575 xmlChar *str = NULL;
1576 int named = 1;
1577
1578 if (*buf != NULL) {
1579 xmlFree(*buf);
1580 *buf = NULL;
1581 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001582
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001583 if (itemDes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00001584 *buf = xmlStrdup(itemDes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001585 } else if (item != NULL) {
1586 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001587 case XML_SCHEMA_TYPE_BASIC: {
1588 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1589
1590 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001592 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001593 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001594 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001595 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1596 else
1597 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001602 case XML_SCHEMA_TYPE_SIMPLE: {
1603 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1604
1605 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001606 *buf = xmlStrdup(BAD_CAST"");
1607 } else {
1608 *buf = xmlStrdup(BAD_CAST "local ");
1609 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001610 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001611 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001612 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001613 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001614 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1616 else
1617 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001618 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001619 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001620 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 *buf = xmlStrcat(*buf, BAD_CAST "'");
1622 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001625 case XML_SCHEMA_TYPE_COMPLEX: {
1626 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1627
1628 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001629 *buf = xmlStrdup(BAD_CAST "");
1630 else
1631 *buf = xmlStrdup(BAD_CAST "local ");
1632 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001633 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001634 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001635 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001636 *buf = xmlStrcat(*buf, BAD_CAST "'");
1637 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001638 }
1639 break;
1640 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1641 xmlSchemaAttributeUsePtr ause;
Daniel Veillarddee23482008-04-11 12:58:43 +00001642
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001643 ause = WXS_ATTR_USE_CAST item;
1644 *buf = xmlStrdup(BAD_CAST "attribute use ");
1645 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1646 *buf = xmlStrcat(*buf, BAD_CAST "'");
1647 *buf = xmlStrcat(*buf,
1648 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1649 FREE_AND_NULL(str)
1650 *buf = xmlStrcat(*buf, BAD_CAST "'");
1651 } else {
1652 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1653 }
1654 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 break;
1656 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1657 xmlSchemaAttributePtr attr;
Daniel Veillarddee23482008-04-11 12:58:43 +00001658
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001659 attr = (xmlSchemaAttributePtr) item;
1660 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1661 *buf = xmlStrcat(*buf, BAD_CAST " '");
1662 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1663 attr->targetNamespace, attr->name));
1664 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001665 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001666 }
1667 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001668 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1669 xmlSchemaGetComponentDesignation(buf, item);
1670 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001671 case XML_SCHEMA_TYPE_ELEMENT: {
1672 xmlSchemaElementPtr elem;
1673
Daniel Veillarddee23482008-04-11 12:58:43 +00001674 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001675 *buf = xmlStrdup(BAD_CAST "element decl.");
1676 *buf = xmlStrcat(*buf, BAD_CAST " '");
1677 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1678 elem->targetNamespace, elem->name));
1679 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001680 }
1681 break;
1682 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1683 case XML_SCHEMA_TYPE_IDC_KEY:
Daniel Veillarddee23482008-04-11 12:58:43 +00001684 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1686 *buf = xmlStrdup(BAD_CAST "unique '");
1687 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1688 *buf = xmlStrdup(BAD_CAST "key '");
1689 else
1690 *buf = xmlStrdup(BAD_CAST "keyRef '");
1691 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1692 *buf = xmlStrcat(*buf, BAD_CAST "'");
1693 break;
1694 case XML_SCHEMA_TYPE_ANY:
1695 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1696 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1697 ((xmlSchemaWildcardPtr) item)->processContents));
1698 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1699 break;
1700 case XML_SCHEMA_FACET_MININCLUSIVE:
1701 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1702 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1703 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1704 case XML_SCHEMA_FACET_TOTALDIGITS:
1705 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1706 case XML_SCHEMA_FACET_PATTERN:
1707 case XML_SCHEMA_FACET_ENUMERATION:
1708 case XML_SCHEMA_FACET_WHITESPACE:
1709 case XML_SCHEMA_FACET_LENGTH:
1710 case XML_SCHEMA_FACET_MAXLENGTH:
1711 case XML_SCHEMA_FACET_MINLENGTH:
1712 *buf = xmlStrdup(BAD_CAST "facet '");
1713 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1714 *buf = xmlStrcat(*buf, BAD_CAST "'");
1715 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001716 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001717 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001718 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001719 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001720 *buf = xmlStrcat(*buf, BAD_CAST "'");
1721 FREE_AND_NULL(str)
1722 }
1723 break;
1724 case XML_SCHEMA_TYPE_SEQUENCE:
1725 case XML_SCHEMA_TYPE_CHOICE:
1726 case XML_SCHEMA_TYPE_ALL:
1727 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001728 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1729 break;
1730 case XML_SCHEMA_TYPE_NOTATION: {
1731 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1732 *buf = xmlStrcat(*buf, BAD_CAST " '");
1733 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1734 *buf = xmlStrcat(*buf, BAD_CAST "'");
1735 FREE_AND_NULL(str);
1736 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001737 default:
1738 named = 0;
1739 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001740 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001741 named = 0;
1742
1743 if ((named == 0) && (itemNode != NULL)) {
1744 xmlNodePtr elem;
1745
1746 if (itemNode->type == XML_ATTRIBUTE_NODE)
1747 elem = itemNode->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00001748 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001749 elem = itemNode;
1750 *buf = xmlStrdup(BAD_CAST "Element '");
1751 if (elem->ns != NULL) {
1752 *buf = xmlStrcat(*buf,
1753 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1754 FREE_AND_NULL(str)
1755 } else
1756 *buf = xmlStrcat(*buf, elem->name);
1757 *buf = xmlStrcat(*buf, BAD_CAST "'");
Daniel Veillarddee23482008-04-11 12:58:43 +00001758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001759 }
1760 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1761 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1762 if (itemNode->ns != NULL) {
1763 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1764 itemNode->ns->href, itemNode->name));
1765 FREE_AND_NULL(str)
1766 } else
1767 *buf = xmlStrcat(*buf, itemNode->name);
1768 *buf = xmlStrcat(*buf, BAD_CAST "'");
1769 }
1770 FREE_AND_NULL(str)
Daniel Veillarddee23482008-04-11 12:58:43 +00001771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 return (*buf);
1773}
1774
1775/**
1776 * xmlSchemaFormatFacetEnumSet:
1777 * @buf: the string buffer
1778 * @type: the type holding the enumeration facets
1779 *
1780 * Builds a string consisting of all enumeration elements.
1781 *
1782 * Returns a string of all enumeration elements.
1783 */
1784static const xmlChar *
1785xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlChar **buf, xmlSchemaTypePtr type)
1787{
1788 xmlSchemaFacetPtr facet;
1789 xmlSchemaWhitespaceValueType ws;
1790 xmlChar *value = NULL;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001791 int res, found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001792
1793 if (*buf != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00001794 xmlFree(*buf);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001795 *buf = NULL;
1796
1797 do {
1798 /*
1799 * Use the whitespace type of the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +00001800 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001801 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1802 for (facet = type->facets; facet != NULL; facet = facet->next) {
1803 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1804 continue;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001805 found = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001806 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1807 ws, &value);
1808 if (res == -1) {
1809 xmlSchemaInternalErr(actxt,
1810 "xmlSchemaFormatFacetEnumSet",
1811 "compute the canonical lexical representation");
1812 if (*buf != NULL)
1813 xmlFree(*buf);
1814 *buf = NULL;
1815 return (NULL);
1816 }
1817 if (*buf == NULL)
1818 *buf = xmlStrdup(BAD_CAST "'");
1819 else
1820 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1821 *buf = xmlStrcat(*buf, BAD_CAST value);
1822 *buf = xmlStrcat(*buf, BAD_CAST "'");
1823 if (value != NULL) {
1824 xmlFree((xmlChar *)value);
1825 value = NULL;
1826 }
1827 }
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001828 /*
1829 * The enumeration facet of a type restricts the enumeration
1830 * facet of the ancestor type; i.e., such restricted enumerations
1831 * do not belong to the set of the given type. Thus we break
1832 * on the first found enumeration.
1833 */
1834 if (found)
1835 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001836 type = type->baseType;
1837 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1838
1839 return ((const xmlChar *) *buf);
1840}
1841
1842/************************************************************************
1843 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001844 * Error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001845 * *
1846 ************************************************************************/
1847
1848#if 0
1849static void
1850xmlSchemaErrMemory(const char *msg)
1851{
1852 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1853 msg);
1854}
1855#endif
1856
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001857static void
1858xmlSchemaPSimpleErr(const char *msg)
1859{
1860 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1861 msg);
1862}
1863
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001864/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001865 * xmlSchemaPErrMemory:
1866 * @node: a context node
1867 * @extra: extra informations
1868 *
1869 * Handle an out of memory condition
1870 */
1871static void
1872xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1873 const char *extra, xmlNodePtr node)
1874{
1875 if (ctxt != NULL)
1876 ctxt->nberrors++;
1877 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1878 extra);
1879}
1880
1881/**
1882 * xmlSchemaPErr:
1883 * @ctxt: the parsing context
1884 * @node: the context node
1885 * @error: the error code
1886 * @msg: the error message
1887 * @str1: extra data
1888 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001889 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890 * Handle a parser error
1891 */
1892static void
1893xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1894 const char *msg, const xmlChar * str1, const xmlChar * str2)
1895{
1896 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001897 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001898 void *data = NULL;
1899
1900 if (ctxt != NULL) {
1901 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001902 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001903 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001904 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001905 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001906 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001907 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001908 error, XML_ERR_ERROR, NULL, 0,
1909 (const char *) str1, (const char *) str2, NULL, 0, 0,
1910 msg, str1, str2);
1911}
1912
1913/**
1914 * xmlSchemaPErr2:
1915 * @ctxt: the parsing context
1916 * @node: the context node
1917 * @node: the current child
1918 * @error: the error code
1919 * @msg: the error message
1920 * @str1: extra data
1921 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001922 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001923 * Handle a parser error
1924 */
1925static void
1926xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1927 xmlNodePtr child, int error,
1928 const char *msg, const xmlChar * str1, const xmlChar * str2)
1929{
1930 if (child != NULL)
1931 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1932 else
1933 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1934}
1935
Daniel Veillard01fa6152004-06-29 17:04:39 +00001936
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001937/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001938 * xmlSchemaPErrExt:
1939 * @ctxt: the parsing context
1940 * @node: the context node
Daniel Veillarddee23482008-04-11 12:58:43 +00001941 * @error: the error code
Daniel Veillard3646d642004-06-02 19:19:14 +00001942 * @strData1: extra data
1943 * @strData2: extra data
1944 * @strData3: extra data
1945 * @msg: the message
1946 * @str1: extra parameter for the message display
1947 * @str2: extra parameter for the message display
1948 * @str3: extra parameter for the message display
1949 * @str4: extra parameter for the message display
1950 * @str5: extra parameter for the message display
Daniel Veillarddee23482008-04-11 12:58:43 +00001951 *
Daniel Veillard3646d642004-06-02 19:19:14 +00001952 * Handle a parser error
1953 */
1954static void
1955xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
Daniel Veillarddee23482008-04-11 12:58:43 +00001956 const xmlChar * strData1, const xmlChar * strData2,
1957 const xmlChar * strData3, const char *msg, const xmlChar * str1,
Daniel Veillard3646d642004-06-02 19:19:14 +00001958 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1959 const xmlChar * str5)
1960{
1961
1962 xmlGenericErrorFunc channel = NULL;
1963 xmlStructuredErrorFunc schannel = NULL;
1964 void *data = NULL;
1965
1966 if (ctxt != NULL) {
1967 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001968 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001969 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001970 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001971 schannel = ctxt->serror;
1972 }
1973 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1974 error, XML_ERR_ERROR, NULL, 0,
Daniel Veillarddee23482008-04-11 12:58:43 +00001975 (const char *) strData1, (const char *) strData2,
1976 (const char *) strData3, 0, 0, msg, str1, str2,
William M. Brack803812b2004-06-03 02:11:24 +00001977 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001978}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001980/************************************************************************
1981 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001982 * Allround error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001983 * *
1984 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001985
1986/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001987 * xmlSchemaVTypeErrMemory:
1988 * @node: a context node
1989 * @extra: extra informations
1990 *
1991 * Handle an out of memory condition
1992 */
1993static void
1994xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1995 const char *extra, xmlNodePtr node)
1996{
1997 if (ctxt != NULL) {
1998 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001999 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002000 }
2001 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2002 extra);
2003}
2004
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002005static void
2006xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2007 const char *msg, const xmlChar *str)
2008{
2009 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2010 msg, (const char *) str);
2011}
2012
2013#define WXS_ERROR_TYPE_ERROR 1
2014#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002015/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002016 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002017 * @ctxt: the validation context
2018 * @node: the context node
2019 * @error: the error code
2020 * @msg: the error message
2021 * @str1: extra data
2022 * @str2: extra data
2023 * @str3: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002024 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002025 * Handle a validation error
2026 */
2027static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002028xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002029 xmlErrorLevel errorLevel,
2030 int error, xmlNodePtr node, int line, const char *msg,
2031 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002032 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002033{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002034 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002035 xmlGenericErrorFunc channel = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002036 void *data = NULL;
2037
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002038 if (ctxt != NULL) {
2039 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2040 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002041 const char *file = NULL;
Juergen Keild201e712014-08-07 11:42:07 +08002042 int col = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002043 if (errorLevel != XML_ERR_WARNING) {
2044 vctxt->nberrors++;
2045 vctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002046 channel = vctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002047 } else {
2048 channel = vctxt->warning;
2049 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002050 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002051 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002052
2053 /*
2054 * Error node. If we specify a line number, then
2055 * do not channel any node to the error function.
2056 */
2057 if (line == 0) {
2058 if ((node == NULL) &&
2059 (vctxt->depth >= 0) &&
2060 (vctxt->inode != NULL)) {
2061 node = vctxt->inode->node;
2062 }
2063 /*
2064 * Get filename and line if no node-tree.
2065 */
2066 if ((node == NULL) &&
2067 (vctxt->parserCtxt != NULL) &&
2068 (vctxt->parserCtxt->input != NULL)) {
2069 file = vctxt->parserCtxt->input->filename;
2070 line = vctxt->parserCtxt->input->line;
Juergen Keild201e712014-08-07 11:42:07 +08002071 col = vctxt->parserCtxt->input->col;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002072 }
2073 } else {
2074 /*
2075 * Override the given node's (if any) position
2076 * and channel only the given line number.
2077 */
2078 node = NULL;
2079 /*
2080 * Get filename.
2081 */
2082 if (vctxt->doc != NULL)
2083 file = (const char *) vctxt->doc->URL;
2084 else if ((vctxt->parserCtxt != NULL) &&
2085 (vctxt->parserCtxt->input != NULL))
2086 file = vctxt->parserCtxt->input->filename;
Daniel Veillarddee23482008-04-11 12:58:43 +00002087 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08002088 if (vctxt->locFunc != NULL) {
2089 if ((file == NULL) || (line == 0)) {
2090 unsigned long l;
2091 const char *f;
2092 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2093 if (file == NULL)
2094 file = f;
2095 if (line == 0)
2096 line = (int) l;
2097 }
2098 }
2099 if ((file == NULL) && (vctxt->filename != NULL))
2100 file = vctxt->filename;
2101
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002102 __xmlRaiseError(schannel, channel, data, ctxt,
2103 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002104 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002105 (const char *) str1, (const char *) str2,
Juergen Keild201e712014-08-07 11:42:07 +08002106 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002107
2108 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2109 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002110 if (errorLevel != XML_ERR_WARNING) {
2111 pctxt->nberrors++;
2112 pctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002113 channel = pctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002114 } else {
2115 channel = pctxt->warning;
2116 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002118 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002119 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002120 node, XML_FROM_SCHEMASP, error,
2121 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002122 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002123 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002124 } else {
2125 TODO
2126 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002127 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002128}
2129
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002130/**
2131 * xmlSchemaErr3:
2132 * @ctxt: the validation context
2133 * @node: the context node
2134 * @error: the error code
2135 * @msg: the error message
2136 * @str1: extra data
2137 * @str2: extra data
2138 * @str3: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002139 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002140 * Handle a validation error
2141 */
2142static void
Daniel Veillarddee23482008-04-11 12:58:43 +00002143xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002144 int error, xmlNodePtr node, const char *msg,
2145 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2146{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002147 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2148 msg, str1, str2, str3, NULL);
2149}
2150
2151static void
Daniel Veillarddee23482008-04-11 12:58:43 +00002152xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002153 int error, xmlNodePtr node, const char *msg,
2154 const xmlChar *str1, const xmlChar *str2,
2155 const xmlChar *str3, const xmlChar *str4)
2156{
2157 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2158 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002159}
2160
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002161static void
2162xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2163 int error, xmlNodePtr node, const char *msg,
2164 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002165{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002166 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002167}
2168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169static xmlChar *
2170xmlSchemaFormatNodeForError(xmlChar ** msg,
2171 xmlSchemaAbstractCtxtPtr actxt,
2172 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173{
2174 xmlChar *str = NULL;
2175
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002176 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002177 if ((node != NULL) &&
2178 (node->type != XML_ELEMENT_NODE) &&
2179 (node->type != XML_ATTRIBUTE_NODE))
2180 {
Daniel Veillarddee23482008-04-11 12:58:43 +00002181 /*
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002182 * Don't try to format other nodes than element and
2183 * attribute nodes.
2184 * Play save and return an empty string.
2185 */
2186 *msg = xmlStrdup(BAD_CAST "");
2187 return(*msg);
2188 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002189 if (node != NULL) {
2190 /*
2191 * Work on tree nodes.
2192 */
2193 if (node->type == XML_ATTRIBUTE_NODE) {
2194 xmlNodePtr elem = node->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00002195
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002196 *msg = xmlStrdup(BAD_CAST "Element '");
2197 if (elem->ns != NULL)
2198 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2199 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002200 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2202 NULL, elem->name));
2203 FREE_AND_NULL(str);
2204 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002205 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002206 } else {
2207 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002208 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002209 if (node->ns != NULL)
2210 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2211 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002212 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002213 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214 NULL, node->name));
2215 FREE_AND_NULL(str);
2216 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2217 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2218 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2219 /*
2220 * Work on node infos.
Daniel Veillarddee23482008-04-11 12:58:43 +00002221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002222 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2223 xmlSchemaNodeInfoPtr ielem =
2224 vctxt->elemInfos[vctxt->depth];
2225
2226 *msg = xmlStrdup(BAD_CAST "Element '");
2227 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2228 ielem->nsName, ielem->localName));
2229 FREE_AND_NULL(str);
2230 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002231 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 } else {
2233 *msg = xmlStrdup(BAD_CAST "Element '");
2234 }
2235 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2236 vctxt->inode->nsName, vctxt->inode->localName));
2237 FREE_AND_NULL(str);
2238 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002239 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
Daniel Veillarddee23482008-04-11 12:58:43 +00002240 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002241 * Hmm, no node while parsing?
2242 * Return an empty string, in case NULL will break something.
2243 */
2244 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002245 } else {
2246 TODO
2247 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002248 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 /*
2250 * VAL TODO: The output of the given schema component is currently
2251 * disabled.
2252 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002253#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2255 *msg = xmlStrcat(*msg, BAD_CAST " [");
2256 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2257 NULL, type, NULL, 0));
2258 FREE_AND_NULL(str)
2259 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002261#endif
2262 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002263}
2264
Daniel Veillardc0826a72004-08-10 14:17:33 +00002265static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002266xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002268 const char *message,
2269 const xmlChar *str1,
2270 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002271{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002272 xmlChar *msg = NULL;
2273
Daniel Veillard14b56432006-03-09 18:41:40 +00002274 if (actxt == NULL)
2275 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002276 msg = xmlStrdup(BAD_CAST "Internal error: ");
2277 msg = xmlStrcat(msg, BAD_CAST funcName);
Daniel Veillarddee23482008-04-11 12:58:43 +00002278 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002279 msg = xmlStrcat(msg, BAD_CAST message);
2280 msg = xmlStrcat(msg, BAD_CAST ".\n");
2281
2282 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2283 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002284 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002285
Daniel Veillarddee23482008-04-11 12:58:43 +00002286 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002287 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002288 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289
2290 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002291}
2292
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002293static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002294xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2295 const char *funcName,
2296 const char *message)
2297{
2298 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2299}
2300
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002301#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002302static void
2303xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2304 const char *funcName,
2305 const char *message,
2306 const xmlChar *str1,
2307 const xmlChar *str2)
2308{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002309 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002310 str1, str2);
2311}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002312#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002313
2314static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002315xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2316 xmlParserErrors error,
2317 xmlNodePtr node,
2318 xmlSchemaBasicItemPtr item,
2319 const char *message,
2320 const xmlChar *str1, const xmlChar *str2,
2321 const xmlChar *str3, const xmlChar *str4)
2322{
2323 xmlChar *msg = NULL;
2324
2325 if ((node == NULL) && (item != NULL) &&
2326 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2327 node = WXS_ITEM_NODE(item);
2328 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2329 msg = xmlStrcat(msg, BAD_CAST ": ");
2330 } else
2331 xmlSchemaFormatNodeForError(&msg, actxt, node);
2332 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002333 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002334 xmlSchemaErr4(actxt, error, node,
2335 (const char *) msg, str1, str2, str3, str4);
2336 FREE_AND_NULL(msg)
2337}
2338
2339static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002340xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2341 xmlParserErrors error,
2342 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002343 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002344 const char *message,
2345 const xmlChar *str1,
2346 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002347{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002348 xmlSchemaCustomErr4(actxt, error, node, item,
Daniel Veillarddee23482008-04-11 12:58:43 +00002349 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350}
2351
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002352
2353
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002354static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002355xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2356 xmlParserErrors error,
2357 xmlNodePtr node,
2358 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2359 const char *message,
2360 const xmlChar *str1,
2361 const xmlChar *str2,
2362 const xmlChar *str3)
2363{
2364 xmlChar *msg = NULL;
2365
2366 xmlSchemaFormatNodeForError(&msg, actxt, node);
2367 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002368 msg = xmlStrcat(msg, BAD_CAST ".\n");
2369
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002370 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002371 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2372 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002373
2374 FREE_AND_NULL(msg)
2375}
2376
2377
2378
2379static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002380xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2381 xmlParserErrors error,
2382 xmlSchemaPSVIIDCNodePtr idcNode,
2383 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2384 const char *message,
2385 const xmlChar *str1,
2386 const xmlChar *str2)
2387{
2388 xmlChar *msg = NULL, *qname = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002389
2390 msg = xmlStrdup(BAD_CAST "Element '%s': ");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002391 msg = xmlStrcat(msg, (const xmlChar *) message);
2392 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002393 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002394 error, NULL, idcNode->nodeLine, (const char *) msg,
2395 xmlSchemaFormatQName(&qname,
2396 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
Daniel Veillarddee23482008-04-11 12:58:43 +00002397 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002398 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002399 FREE_AND_NULL(qname);
2400 FREE_AND_NULL(msg);
2401}
2402
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002403static int
2404xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2405 xmlNodePtr node)
2406{
2407 if (node != NULL)
2408 return (node->type);
2409 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2410 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2411 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2412 return (-1);
2413}
2414
2415static int
2416xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2417{
2418 switch (item->type) {
2419 case XML_SCHEMA_TYPE_COMPLEX:
2420 case XML_SCHEMA_TYPE_SIMPLE:
2421 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2422 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002423 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002424 case XML_SCHEMA_TYPE_GROUP:
2425 return (1);
2426 case XML_SCHEMA_TYPE_ELEMENT:
2427 if ( ((xmlSchemaElementPtr) item)->flags &
2428 XML_SCHEMAS_ELEM_GLOBAL)
2429 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002430 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 case XML_SCHEMA_TYPE_ATTRIBUTE:
2432 if ( ((xmlSchemaAttributePtr) item)->flags &
2433 XML_SCHEMAS_ATTR_GLOBAL)
2434 return(1);
2435 break;
2436 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002437 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002438 return(1);
2439 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002440 return (0);
2441}
2442
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002443static void
2444xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2445 xmlParserErrors error,
2446 xmlNodePtr node,
2447 const xmlChar *value,
2448 xmlSchemaTypePtr type,
2449 int displayValue)
2450{
2451 xmlChar *msg = NULL;
2452
2453 xmlSchemaFormatNodeForError(&msg, actxt, node);
2454
2455 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2456 XML_ATTRIBUTE_NODE))
2457 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2458 else
2459 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2460 "value of ");
2461
2462 if (! xmlSchemaIsGlobalItem(type))
2463 msg = xmlStrcat(msg, BAD_CAST "the local ");
2464 else
2465 msg = xmlStrcat(msg, BAD_CAST "the ");
2466
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002467 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002468 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002469 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002470 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002471 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002472 msg = xmlStrcat(msg, BAD_CAST "union type");
2473
2474 if (xmlSchemaIsGlobalItem(type)) {
2475 xmlChar *str = NULL;
2476 msg = xmlStrcat(msg, BAD_CAST " '");
2477 if (type->builtInType != 0) {
2478 msg = xmlStrcat(msg, BAD_CAST "xs:");
2479 msg = xmlStrcat(msg, type->name);
Daniel Veillarddee23482008-04-11 12:58:43 +00002480 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002481 msg = xmlStrcat(msg,
2482 xmlSchemaFormatQName(&str,
2483 type->targetNamespace, type->name));
2484 msg = xmlStrcat(msg, BAD_CAST "'");
2485 FREE_AND_NULL(str);
2486 }
2487 msg = xmlStrcat(msg, BAD_CAST ".\n");
2488 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2489 XML_ATTRIBUTE_NODE))
2490 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2491 else
2492 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2493 FREE_AND_NULL(msg)
2494}
2495
Daniel Veillardc0826a72004-08-10 14:17:33 +00002496static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002497xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2498 xmlSchemaNodeInfoPtr ni,
2499 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002500{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002501 if (node != NULL) {
2502 if (node->ns != NULL)
2503 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2504 else
2505 return (xmlSchemaFormatQName(str, NULL, node->name));
2506 } else if (ni != NULL)
2507 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2508 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002509}
2510
Daniel Veillardc0826a72004-08-10 14:17:33 +00002511static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002512xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2513 xmlParserErrors error,
2514 xmlSchemaAttrInfoPtr ni,
2515 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002516{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002517 xmlChar *msg = NULL, *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002518
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002519 xmlSchemaFormatNodeForError(&msg, actxt, node);
2520 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2521 xmlSchemaErr(actxt, error, node, (const char *) msg,
2522 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
Daniel Veillarddee23482008-04-11 12:58:43 +00002523 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002525 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526}
2527
Daniel Veillardc0826a72004-08-10 14:17:33 +00002528static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002529xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2530 xmlParserErrors error,
2531 xmlNodePtr node,
2532 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002533 const char *message,
2534 int nbval,
2535 int nbneg,
2536 xmlChar **values)
2537{
2538 xmlChar *str = NULL, *msg = NULL;
2539 xmlChar *localName, *nsName;
2540 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002541 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00002542
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002543 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002544 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002545 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002546 /*
2547 * Note that is does not make sense to report that we have a
2548 * wildcard here, since the wildcard might be unfolded into
2549 * multiple transitions.
2550 */
2551 if (nbval + nbneg > 0) {
2552 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002554 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002555 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002556 nsName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002557
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002558 for (i = 0; i < nbval + nbneg; i++) {
2559 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002560 if (cur == NULL)
2561 continue;
2562 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2563 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002564 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002565 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002566 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002567 /*
2568 * Get the local name.
2569 */
2570 localName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002571
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002572 end = cur;
2573 if (*end == '*') {
2574 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002575 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002576 } else {
2577 while ((*end != 0) && (*end != '|'))
2578 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002579 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Daniel Veillarddee23482008-04-11 12:58:43 +00002580 }
2581 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002582 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002583 /*
2584 * Skip "*|*" if they come with negated expressions, since
2585 * they represent the same negated wildcard.
2586 */
2587 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2588 /*
2589 * Get the namespace name.
2590 */
2591 cur = end;
2592 if (*end == '*') {
2593 nsName = xmlStrdup(BAD_CAST "{*}");
2594 } else {
2595 while (*end != 0)
2596 end++;
Daniel Veillarddee23482008-04-11 12:58:43 +00002597
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002598 if (i >= nbval)
2599 nsName = xmlStrdup(BAD_CAST "{##other:");
2600 else
2601 nsName = xmlStrdup(BAD_CAST "{");
Daniel Veillarddee23482008-04-11 12:58:43 +00002602
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002603 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2604 nsName = xmlStrcat(nsName, BAD_CAST "}");
2605 }
2606 str = xmlStrcat(str, BAD_CAST nsName);
2607 FREE_AND_NULL(nsName)
2608 } else {
2609 FREE_AND_NULL(localName);
2610 continue;
2611 }
Daniel Veillarddee23482008-04-11 12:58:43 +00002612 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002613 str = xmlStrcat(str, BAD_CAST localName);
2614 FREE_AND_NULL(localName);
Daniel Veillarddee23482008-04-11 12:58:43 +00002615
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002616 if (i < nbval + nbneg -1)
2617 str = xmlStrcat(str, BAD_CAST ", ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002619 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002620 msg = xmlStrcat(msg, BAD_CAST str);
2621 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002622 } else
2623 msg = xmlStrcat(msg, BAD_CAST "\n");
2624 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002625 xmlFree(msg);
2626}
2627
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002628static void
2629xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2630 xmlParserErrors error,
2631 xmlNodePtr node,
2632 const xmlChar *value,
2633 unsigned long length,
2634 xmlSchemaTypePtr type,
2635 xmlSchemaFacetPtr facet,
2636 const char *message,
2637 const xmlChar *str1,
2638 const xmlChar *str2)
2639{
2640 xmlChar *str = NULL, *msg = NULL;
2641 xmlSchemaTypeType facetType;
2642 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2643
2644 xmlSchemaFormatNodeForError(&msg, actxt, node);
2645 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2646 facetType = XML_SCHEMA_FACET_ENUMERATION;
2647 /*
2648 * If enumerations are validated, one must not expect the
2649 * facet to be given.
Daniel Veillarddee23482008-04-11 12:58:43 +00002650 */
2651 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002652 facetType = facet->type;
2653 msg = xmlStrcat(msg, BAD_CAST "[");
2654 msg = xmlStrcat(msg, BAD_CAST "facet '");
2655 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2656 msg = xmlStrcat(msg, BAD_CAST "'] ");
2657 if (message == NULL) {
2658 /*
2659 * Use a default message.
2660 */
2661 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2662 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2663 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2664
2665 char len[25], actLen[25];
2666
2667 /* FIXME, TODO: What is the max expected string length of the
2668 * this value?
2669 */
2670 if (nodeType == XML_ATTRIBUTE_NODE)
2671 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2672 else
2673 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2674
2675 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2676 snprintf(actLen, 24, "%lu", length);
2677
2678 if (facetType == XML_SCHEMA_FACET_LENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002679 msg = xmlStrcat(msg,
2680 BAD_CAST "this differs from the allowed length of '%s'.\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002681 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002682 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002683 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2684 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002685 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002686 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002687
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002688 if (nodeType == XML_ATTRIBUTE_NODE)
2689 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2690 value, (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002691 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002692 xmlSchemaErr(actxt, error, node, (const char *) msg,
2693 (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002694
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002695 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2696 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2697 "of the set {%s}.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002698 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002699 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2700 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2701 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2702 "by the pattern '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002703 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002704 facet->value);
2705 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2706 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2707 "minimum value allowed ('%s').\n");
2708 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2709 facet->value);
2710 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2711 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2712 "maximum value allowed ('%s').\n");
2713 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2714 facet->value);
2715 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002716 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717 "'%s'.\n");
2718 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2719 facet->value);
2720 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002721 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002722 "'%s'.\n");
2723 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2724 facet->value);
2725 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2726 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2727 "digits than are allowed ('%s').\n");
2728 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2729 facet->value);
2730 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2731 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2732 "digits than are allowed ('%s').\n");
2733 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2734 facet->value);
Daniel Veillarddee23482008-04-11 12:58:43 +00002735 } else if (nodeType == XML_ATTRIBUTE_NODE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002736 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002737 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2738 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002739 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2740 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2741 }
2742 } else {
2743 msg = xmlStrcat(msg, (const xmlChar *) message);
2744 msg = xmlStrcat(msg, BAD_CAST ".\n");
2745 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
Daniel Veillarddee23482008-04-11 12:58:43 +00002746 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002747 FREE_AND_NULL(str)
2748 xmlFree(msg);
2749}
2750
2751#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002752 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002753
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002754#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002755
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002756#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2757#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002758
2759#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2760
2761
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002762/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002763 * xmlSchemaPMissingAttrErr:
2764 * @ctxt: the schema validation context
2765 * @ownerDes: the designation of the owner
2766 * @ownerName: the name of the owner
2767 * @ownerItem: the owner as a schema object
2768 * @ownerElem: the owner as an element node
2769 * @node: the parent element node of the missing attribute node
2770 * @type: the corresponding type of the attribute node
2771 *
2772 * Reports an illegal attribute.
2773 */
2774static void
2775xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002776 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002777 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002778 xmlNodePtr ownerElem,
2779 const char *name,
2780 const char *message)
2781{
2782 xmlChar *des = NULL;
2783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002784 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2785
Daniel Veillardc0826a72004-08-10 14:17:33 +00002786 if (message != NULL)
2787 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 else
2789 xmlSchemaPErr(ctxt, ownerElem, error,
2790 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002791 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002792 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793}
2794
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795
Daniel Veillardc0826a72004-08-10 14:17:33 +00002796/**
2797 * xmlSchemaPResCompAttrErr:
2798 * @ctxt: the schema validation context
2799 * @error: the error code
2800 * @ownerDes: the designation of the owner
2801 * @ownerItem: the owner as a schema object
2802 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002803 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002804 * @refName: the referenced local name
2805 * @refURI: the referenced namespace URI
2806 * @message: optional message
2807 *
2808 * Used to report QName attribute values that failed to resolve
2809 * to schema components.
2810 */
2811static void
2812xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002813 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002814 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002815 xmlNodePtr ownerElem,
2816 const char *name,
2817 const xmlChar *refName,
2818 const xmlChar *refURI,
2819 xmlSchemaTypeType refType,
2820 const char *refTypeStr)
2821{
2822 xmlChar *des = NULL, *strA = NULL;
2823
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002826 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002827 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002828 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002829 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2830 "%s.\n", BAD_CAST des, BAD_CAST name,
2831 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002832 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002833 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002834 FREE_AND_NULL(strA)
2835}
2836
William M. Brack2f2a6632004-08-20 23:09:47 +00002837/**
2838 * xmlSchemaPCustomAttrErr:
2839 * @ctxt: the schema parser context
2840 * @error: the error code
2841 * @ownerDes: the designation of the owner
2842 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002843 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002844 *
2845 * Reports an illegal attribute during the parse.
2846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847static void
2848xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002849 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002850 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002851 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002852 xmlAttrPtr attr,
2853 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002854{
2855 xmlChar *des = NULL;
2856
2857 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002858 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002859 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002860 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002861 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002862 } else
2863 des = *ownerDes;
Daniel Veillard14b56432006-03-09 18:41:40 +00002864 if (attr == NULL) {
2865 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2866 "%s, attribute '%s': %s.\n",
Daniel Veillardaac7c682006-03-10 13:40:16 +00002867 BAD_CAST des, (const xmlChar *) "Unknown",
2868 (const xmlChar *) msg, NULL, NULL);
Daniel Veillard14b56432006-03-09 18:41:40 +00002869 } else {
2870 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2871 "%s, attribute '%s': %s.\n",
2872 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2873 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002874 if (ownerDes == NULL)
2875 FREE_AND_NULL(des);
2876}
2877
2878/**
2879 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002881 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002882 * @ownerDes: the designation of the attribute's owner
2883 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002884 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002885 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002886 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002887 */
2888static void
2889xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002890 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002891 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002892 xmlAttrPtr attr)
2893{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002894 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002895
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002896 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2897 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2898 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2899 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2900 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002901 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002902 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002903}
2904
William M. Brack2f2a6632004-08-20 23:09:47 +00002905/**
2906 * xmlSchemaPCustomErr:
2907 * @ctxt: the schema parser context
2908 * @error: the error code
2909 * @itemDes: the designation of the schema item
2910 * @item: the schema item
2911 * @itemElem: the node of the schema item
2912 * @message: the error message
2913 * @str1: an optional param for the error message
2914 * @str2: an optional param for the error message
2915 * @str3: an optional param for the error message
2916 *
2917 * Reports an error during parsing.
2918 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002919static void
2920xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002921 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002922 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002923 xmlNodePtr itemElem,
2924 const char *message,
2925 const xmlChar *str1,
2926 const xmlChar *str2,
2927 const xmlChar *str3)
2928{
2929 xmlChar *des = NULL, *msg = NULL;
2930
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002931 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932 msg = xmlStrdup(BAD_CAST "%s: ");
2933 msg = xmlStrcat(msg, (const xmlChar *) message);
2934 msg = xmlStrcat(msg, BAD_CAST ".\n");
2935 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002936 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002937 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002938 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002940 FREE_AND_NULL(msg);
2941}
2942
William M. Brack2f2a6632004-08-20 23:09:47 +00002943/**
2944 * xmlSchemaPCustomErr:
2945 * @ctxt: the schema parser context
2946 * @error: the error code
2947 * @itemDes: the designation of the schema item
2948 * @item: the schema item
2949 * @itemElem: the node of the schema item
2950 * @message: the error message
2951 * @str1: the optional param for the error message
2952 *
2953 * Reports an error during parsing.
2954 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002955static void
2956xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002957 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002958 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002959 xmlNodePtr itemElem,
2960 const char *message,
2961 const xmlChar *str1)
2962{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002963 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002964 str1, NULL, NULL);
2965}
2966
William M. Brack2f2a6632004-08-20 23:09:47 +00002967/**
2968 * xmlSchemaPAttrUseErr:
2969 * @ctxt: the schema parser context
2970 * @error: the error code
2971 * @itemDes: the designation of the schema type
2972 * @item: the schema type
2973 * @itemElem: the node of the schema type
2974 * @attr: the invalid schema attribute
2975 * @message: the error message
2976 * @str1: the optional param for the error message
2977 *
2978 * Reports an attribute use error during parsing.
2979 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002980static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002981xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002982 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002983 xmlNodePtr node,
2984 xmlSchemaBasicItemPtr ownerItem,
2985 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002986 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002987 const xmlChar *str1, const xmlChar *str2,
2988 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002989{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002990 xmlChar *str = NULL, *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002991
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002992 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00002993 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002994 msg = xmlStrcat(msg,
2995 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002996 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002997 FREE_AND_NULL(str);
2998 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002999 msg = xmlStrcat(msg, (const xmlChar *) message);
3000 msg = xmlStrcat(msg, BAD_CAST ".\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00003001 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003002 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003 xmlFree(msg);
3004}
3005
William M. Brack2f2a6632004-08-20 23:09:47 +00003006/**
3007 * xmlSchemaPIllegalFacetAtomicErr:
3008 * @ctxt: the schema parser context
3009 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003010 * @type: the schema type
3011 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00003012 * @facet: the illegal facet
3013 *
3014 * Reports an illegal facet for atomic simple types.
3015 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003016static void
3017xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003018 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003019 xmlSchemaTypePtr type,
3020 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021 xmlSchemaFacetPtr facet)
3022{
3023 xmlChar *des = NULL, *strT = NULL;
3024
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003025 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3026 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003027 "%s: The facet '%s' is not allowed on types derived from the "
3028 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003029 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003030 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00003031 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003032 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003033 FREE_AND_NULL(strT);
3034}
3035
William M. Brack2f2a6632004-08-20 23:09:47 +00003036/**
3037 * xmlSchemaPIllegalFacetListUnionErr:
3038 * @ctxt: the schema parser context
3039 * @error: the error code
3040 * @itemDes: the designation of the schema item involved
3041 * @item: the schema item involved
3042 * @facet: the illegal facet
3043 *
3044 * Reports an illegal facet for <list> and <union>.
3045 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003046static void
3047xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003048 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003049 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003050 xmlSchemaFacetPtr facet)
3051{
Daniel Veillardb2947172006-03-27 09:45:01 +00003052 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003053
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003054 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3055 type->node);
3056 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003057 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003058 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003059 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003060}
3061
3062/**
3063 * xmlSchemaPMutualExclAttrErr:
3064 * @ctxt: the schema validation context
3065 * @error: the error code
3066 * @elemDes: the designation of the parent element node
3067 * @attr: the bad attribute node
3068 * @type: the corresponding type of the attribute node
3069 *
3070 * Reports an illegal attribute.
3071 */
3072static void
3073xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3074 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003075 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003077 const char *name1,
3078 const char *name2)
3079{
3080 xmlChar *des = NULL;
3081
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003082 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003083 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003084 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003085 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003086 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003087}
3088
3089/**
3090 * xmlSchemaPSimpleTypeErr:
3091 * @ctxt: the schema validation context
3092 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003093 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003094 * @ownerDes: the designation of the owner
Daniel Veillarddee23482008-04-11 12:58:43 +00003095 * @ownerItem: the schema object if existent
Daniel Veillardc0826a72004-08-10 14:17:33 +00003096 * @node: the validated node
3097 * @value: the validated value
3098 *
3099 * Reports a simple type validation error.
3100 * TODO: Should this report the value of an element as well?
3101 */
3102static void
Daniel Veillarddee23482008-04-11 12:58:43 +00003103xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003104 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003105 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003106 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003107 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003108 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003109 const xmlChar *value,
3110 const char *message,
3111 const xmlChar *str1,
3112 const xmlChar *str2)
3113{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003114 xmlChar *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00003115
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003116 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003117 if (message == NULL) {
3118 /*
3119 * Use default messages.
Daniel Veillarddee23482008-04-11 12:58:43 +00003120 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003121 if (type != NULL) {
3122 if (node->type == XML_ATTRIBUTE_NODE)
3123 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3124 else
3125 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
Daniel Veillarddee23482008-04-11 12:58:43 +00003126 "valid value of ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003127 if (! xmlSchemaIsGlobalItem(type))
3128 msg = xmlStrcat(msg, BAD_CAST "the local ");
3129 else
3130 msg = xmlStrcat(msg, BAD_CAST "the ");
Daniel Veillarddee23482008-04-11 12:58:43 +00003131
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003132 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003133 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003134 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003135 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003136 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003137 msg = xmlStrcat(msg, BAD_CAST "union type");
Daniel Veillarddee23482008-04-11 12:58:43 +00003138
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003139 if (xmlSchemaIsGlobalItem(type)) {
3140 xmlChar *str = NULL;
3141 msg = xmlStrcat(msg, BAD_CAST " '");
3142 if (type->builtInType != 0) {
3143 msg = xmlStrcat(msg, BAD_CAST "xs:");
3144 msg = xmlStrcat(msg, type->name);
Daniel Veillarddee23482008-04-11 12:58:43 +00003145 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146 msg = xmlStrcat(msg,
3147 xmlSchemaFormatQName(&str,
3148 type->targetNamespace, type->name));
3149 msg = xmlStrcat(msg, BAD_CAST "'.");
3150 FREE_AND_NULL(str);
3151 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003152 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003153 if (node->type == XML_ATTRIBUTE_NODE)
3154 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3155 else
3156 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3157 "valid.");
Daniel Veillarddee23482008-04-11 12:58:43 +00003158 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003159 if (expected) {
3160 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3161 msg = xmlStrcat(msg, BAD_CAST expected);
3162 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3163 } else
3164 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003166 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3167 else
3168 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3169 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003170 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003171 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003172 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003173 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003174 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003175 /* Cleanup. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003176 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003177}
3178
William M. Brack2f2a6632004-08-20 23:09:47 +00003179/**
3180 * xmlSchemaPContentErr:
3181 * @ctxt: the schema parser context
3182 * @error: the error code
3183 * @onwerDes: the designation of the holder of the content
3184 * @ownerItem: the owner item of the holder of the content
3185 * @ownerElem: the node of the holder of the content
3186 * @child: the invalid child node
3187 * @message: the optional error message
3188 * @content: the optional string describing the correct content
3189 *
3190 * Reports an error concerning the content of a schema element.
3191 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003192static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003193xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003194 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003195 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003196 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003197 xmlNodePtr child,
3198 const char *message,
3199 const char *content)
3200{
3201 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003202
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003203 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003204 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003205 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3206 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003207 BAD_CAST des, BAD_CAST message);
3208 else {
3209 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003210 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3211 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003212 BAD_CAST des, BAD_CAST content);
3213 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003214 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3215 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003216 BAD_CAST des, NULL);
3217 }
3218 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003219 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003220}
3221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003222/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003223 * *
3224 * Streamable error functions *
3225 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003226 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003227
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003228
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003229
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003230
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003231/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003232 * *
3233 * Validation helper functions *
3234 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003236
Daniel Veillardc0826a72004-08-10 14:17:33 +00003237
Daniel Veillard4255d502002-04-16 15:50:10 +00003238/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003239 * *
3240 * Allocation functions *
3241 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003242 ************************************************************************/
3243
3244/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003245 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003246 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003247 *
3248 * Allocate a new Schema structure.
3249 *
3250 * Returns the newly allocated structure or NULL in case or error
3251 */
3252static xmlSchemaPtr
3253xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3254{
3255 xmlSchemaPtr ret;
3256
3257 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3258 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003259 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 return (NULL);
3261 }
3262 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003263 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003264 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003265
3266 return (ret);
3267}
3268
3269/**
3270 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003271 *
3272 * Allocate a new Facet structure.
3273 *
3274 * Returns the newly allocated structure or NULL in case or error
3275 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003276xmlSchemaFacetPtr
3277xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003278{
3279 xmlSchemaFacetPtr ret;
3280
3281 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3282 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003283 return (NULL);
3284 }
3285 memset(ret, 0, sizeof(xmlSchemaFacet));
3286
3287 return (ret);
3288}
3289
3290/**
3291 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003292 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003293 * @node: a node
3294 *
3295 * Allocate a new annotation structure.
3296 *
3297 * Returns the newly allocated structure or NULL in case or error
3298 */
3299static xmlSchemaAnnotPtr
3300xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3301{
3302 xmlSchemaAnnotPtr ret;
3303
3304 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3305 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003306 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003307 return (NULL);
3308 }
3309 memset(ret, 0, sizeof(xmlSchemaAnnot));
3310 ret->content = node;
3311 return (ret);
3312}
3313
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003314static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003315xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003316{
3317 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003318
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003319 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3320 if (ret == NULL) {
3321 xmlSchemaPErrMemory(NULL,
3322 "allocating an item list structure", NULL);
3323 return (NULL);
3324 }
3325 memset(ret, 0, sizeof(xmlSchemaItemList));
3326 return (ret);
3327}
3328
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003329static void
3330xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3331{
3332 if (list->items != NULL) {
3333 xmlFree(list->items);
3334 list->items = NULL;
3335 }
3336 list->nbItems = 0;
3337 list->sizeItems = 0;
3338}
3339
3340static int
3341xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3342{
3343 if (list->items == NULL) {
3344 list->items = (void **) xmlMalloc(
3345 20 * sizeof(void *));
3346 if (list->items == NULL) {
3347 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3348 return(-1);
3349 }
3350 list->sizeItems = 20;
3351 } else if (list->sizeItems <= list->nbItems) {
3352 list->sizeItems *= 2;
3353 list->items = (void **) xmlRealloc(list->items,
3354 list->sizeItems * sizeof(void *));
3355 if (list->items == NULL) {
3356 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3357 list->sizeItems = 0;
3358 return(-1);
3359 }
3360 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003361 list->items[list->nbItems++] = item;
3362 return(0);
3363}
3364
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003365static int
3366xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3367 int initialSize,
3368 void *item)
3369{
3370 if (list->items == NULL) {
3371 if (initialSize <= 0)
3372 initialSize = 1;
3373 list->items = (void **) xmlMalloc(
3374 initialSize * sizeof(void *));
3375 if (list->items == NULL) {
3376 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3377 return(-1);
3378 }
3379 list->sizeItems = initialSize;
3380 } else if (list->sizeItems <= list->nbItems) {
3381 list->sizeItems *= 2;
3382 list->items = (void **) xmlRealloc(list->items,
3383 list->sizeItems * sizeof(void *));
3384 if (list->items == NULL) {
3385 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3386 list->sizeItems = 0;
3387 return(-1);
3388 }
3389 }
3390 list->items[list->nbItems++] = item;
3391 return(0);
3392}
3393
3394static int
3395xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003396{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003397 if (list->items == NULL) {
3398 list->items = (void **) xmlMalloc(
3399 20 * sizeof(void *));
3400 if (list->items == NULL) {
3401 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3402 return(-1);
3403 }
3404 list->sizeItems = 20;
3405 } else if (list->sizeItems <= list->nbItems) {
3406 list->sizeItems *= 2;
3407 list->items = (void **) xmlRealloc(list->items,
3408 list->sizeItems * sizeof(void *));
3409 if (list->items == NULL) {
3410 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3411 list->sizeItems = 0;
3412 return(-1);
3413 }
3414 }
3415 /*
3416 * Just append if the index is greater/equal than the item count.
3417 */
3418 if (idx >= list->nbItems) {
3419 list->items[list->nbItems++] = item;
3420 } else {
3421 int i;
3422 for (i = list->nbItems; i > idx; i--)
3423 list->items[i] = list->items[i-1];
3424 list->items[idx] = item;
3425 list->nbItems++;
3426 }
3427 return(0);
3428}
3429
3430#if 0 /* enable if ever needed */
3431static int
3432xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3433 int initialSize,
3434 void *item,
3435 int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003436{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003437 if (list->items == NULL) {
3438 if (initialSize <= 0)
3439 initialSize = 1;
3440 list->items = (void **) xmlMalloc(
3441 initialSize * sizeof(void *));
3442 if (list->items == NULL) {
3443 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444 return(-1);
3445 }
3446 list->sizeItems = initialSize;
3447 } else if (list->sizeItems <= list->nbItems) {
3448 list->sizeItems *= 2;
3449 list->items = (void **) xmlRealloc(list->items,
3450 list->sizeItems * sizeof(void *));
3451 if (list->items == NULL) {
3452 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453 list->sizeItems = 0;
3454 return(-1);
3455 }
3456 }
3457 /*
3458 * Just append if the index is greater/equal than the item count.
3459 */
3460 if (idx >= list->nbItems) {
3461 list->items[list->nbItems++] = item;
3462 } else {
3463 int i;
3464 for (i = list->nbItems; i > idx; i--)
3465 list->items[i] = list->items[i-1];
3466 list->items[idx] = item;
3467 list->nbItems++;
3468 }
3469 return(0);
3470}
3471#endif
3472
3473static int
3474xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3475{
3476 int i;
3477 if ((list->items == NULL) || (idx >= list->nbItems)) {
3478 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3479 "index error.\n");
3480 return(-1);
3481 }
3482
3483 if (list->nbItems == 1) {
3484 /* TODO: Really free the list? */
3485 xmlFree(list->items);
3486 list->items = NULL;
3487 list->nbItems = 0;
3488 list->sizeItems = 0;
3489 } else if (list->nbItems -1 == idx) {
3490 list->nbItems--;
Daniel Veillarddee23482008-04-11 12:58:43 +00003491 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003492 for (i = idx; i < list->nbItems -1; i++)
3493 list->items[i] = list->items[i+1];
3494 list->nbItems--;
3495 }
3496 return(0);
3497}
3498
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003499/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003500 * xmlSchemaItemListFree:
3501 * @annot: a schema type structure
3502 *
3503 * Deallocate a annotation structure
3504 */
3505static void
3506xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3507{
3508 if (list == NULL)
3509 return;
3510 if (list->items != NULL)
3511 xmlFree(list->items);
3512 xmlFree(list);
3513}
3514
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003515static void
3516xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003517{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003518 if (bucket == NULL)
3519 return;
3520 if (bucket->globals != NULL) {
3521 xmlSchemaComponentListFree(bucket->globals);
3522 xmlSchemaItemListFree(bucket->globals);
3523 }
3524 if (bucket->locals != NULL) {
3525 xmlSchemaComponentListFree(bucket->locals);
Daniel Veillarddee23482008-04-11 12:58:43 +00003526 xmlSchemaItemListFree(bucket->locals);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003527 }
3528 if (bucket->relations != NULL) {
3529 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3530 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00003531 prev = cur;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003532 cur = cur->next;
3533 xmlFree(prev);
3534 } while (cur != NULL);
3535 }
3536 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3537 xmlFreeDoc(bucket->doc);
Daniel Veillarddee23482008-04-11 12:58:43 +00003538 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003539 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003540 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3541 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003542 }
3543 xmlFree(bucket);
3544}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003545
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003546static xmlSchemaBucketPtr
3547xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003548 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003549{
3550 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003551 int size;
3552 xmlSchemaPtr mainSchema;
3553
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003554 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003555 PERROR_INT("xmlSchemaBucketCreate",
3556 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003557 return(NULL);
3558 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003559 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003560 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003561 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003562 size = sizeof(xmlSchemaInclude);
3563 else
3564 size = sizeof(xmlSchemaImport);
3565 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3566 if (ret == NULL) {
3567 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3568 return(NULL);
3569 }
3570 memset(ret, 0, size);
3571 ret->targetNamespace = targetNamespace;
3572 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003573 ret->globals = xmlSchemaItemListCreate();
3574 if (ret->globals == NULL) {
3575 xmlFree(ret);
3576 return(NULL);
3577 }
3578 ret->locals = xmlSchemaItemListCreate();
3579 if (ret->locals == NULL) {
3580 xmlFree(ret);
3581 return(NULL);
3582 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003583 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003584 * The following will assure that only the first bucket is marked as
3585 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3586 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003587 * An xmlSchema will be created for every distinct targetNamespace.
3588 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003589 */
3590 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003591 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003592 PERROR_INT("xmlSchemaBucketCreate",
3593 "first bucket but it's an include or redefine");
3594 xmlSchemaBucketFree(ret);
3595 return(NULL);
3596 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003597 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003598 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3599 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003600 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3601 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003602 /*
3603 * Ensure that the main schema gets a targetNamespace.
3604 */
3605 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003606 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +00003607 if (type == XML_SCHEMA_SCHEMA_MAIN) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003608 PERROR_INT("xmlSchemaBucketCreate",
3609 "main bucket but it's not the first one");
3610 xmlSchemaBucketFree(ret);
3611 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003612 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003613 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003614 * Create a schema for imports and assign the
3615 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003616 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003617 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3618 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003619 xmlSchemaBucketFree(ret);
3620 return(NULL);
3621 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003622 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003623 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003624 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003625 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003626 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003627 /*
3628 * Imports go into the "schemasImports" slot of the main *schema*.
3629 * Note that we create an import entry for the main schema as well; i.e.,
3630 * even if there's only one schema, we'll get an import.
3631 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003632 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003633 mainSchema->schemasImports = xmlHashCreateDict(5,
3634 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003635 if (mainSchema->schemasImports == NULL) {
3636 xmlSchemaBucketFree(ret);
3637 return(NULL);
3638 }
3639 }
3640 if (targetNamespace == NULL)
3641 res = xmlHashAddEntry(mainSchema->schemasImports,
3642 XML_SCHEMAS_NO_NAMESPACE, ret);
3643 else
3644 res = xmlHashAddEntry(mainSchema->schemasImports,
3645 targetNamespace, ret);
3646 if (res != 0) {
3647 PERROR_INT("xmlSchemaBucketCreate",
3648 "failed to add the schema bucket to the hash");
3649 xmlSchemaBucketFree(ret);
3650 return(NULL);
3651 }
3652 } else {
3653 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003654 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3655 WXS_INCBUCKET(ret)->ownerImport =
3656 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003657 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003658 WXS_INCBUCKET(ret)->ownerImport =
3659 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003660
3661 /* Includes got into the "includes" slot of the *main* schema. */
3662 if (mainSchema->includes == NULL) {
3663 mainSchema->includes = xmlSchemaItemListCreate();
3664 if (mainSchema->includes == NULL) {
3665 xmlSchemaBucketFree(ret);
3666 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003667 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003668 }
3669 xmlSchemaItemListAdd(mainSchema->includes, ret);
3670 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003671 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003672 * Add to list of all buckets; this is used for lookup
3673 * during schema construction time only.
3674 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003675 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003676 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003677 return(ret);
3678}
3679
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003680static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003681xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003682{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003683 if (*list == NULL) {
3684 *list = xmlSchemaItemListCreate();
3685 if (*list == NULL)
3686 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003687 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003688 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003689 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003690}
3691
3692/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003693 * xmlSchemaFreeAnnot:
3694 * @annot: a schema type structure
3695 *
3696 * Deallocate a annotation structure
3697 */
3698static void
3699xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3700{
3701 if (annot == NULL)
3702 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003703 if (annot->next == NULL) {
3704 xmlFree(annot);
3705 } else {
3706 xmlSchemaAnnotPtr prev;
3707
3708 do {
3709 prev = annot;
3710 annot = annot->next;
3711 xmlFree(prev);
3712 } while (annot != NULL);
3713 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003714}
3715
3716/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003717 * xmlSchemaFreeNotation:
3718 * @schema: a schema notation structure
3719 *
3720 * Deallocate a Schema Notation structure.
3721 */
3722static void
3723xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3724{
3725 if (nota == NULL)
3726 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 xmlFree(nota);
3728}
3729
3730/**
3731 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003732 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003733 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003734 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 */
3736static void
3737xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3738{
3739 if (attr == NULL)
3740 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003742 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003743 if (attr->defVal != NULL)
3744 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003745 xmlFree(attr);
3746}
3747
3748/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003749 * xmlSchemaFreeAttributeUse:
3750 * @use: an attribute use
3751 *
3752 * Deallocates an attribute use structure.
3753 */
3754static void
3755xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3756{
3757 if (use == NULL)
3758 return;
3759 if (use->annot != NULL)
3760 xmlSchemaFreeAnnot(use->annot);
3761 if (use->defVal != NULL)
3762 xmlSchemaFreeValue(use->defVal);
3763 xmlFree(use);
3764}
3765
3766/**
3767 * xmlSchemaFreeAttributeUseProhib:
3768 * @prohib: an attribute use prohibition
3769 *
3770 * Deallocates an attribute use structure.
3771 */
3772static void
3773xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3774{
3775 if (prohib == NULL)
3776 return;
3777 xmlFree(prohib);
3778}
3779
3780/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003781 * xmlSchemaFreeWildcardNsSet:
3782 * set: a schema wildcard namespace
3783 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003784 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003785 */
3786static void
3787xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3788{
3789 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003790
Daniel Veillard3646d642004-06-02 19:19:14 +00003791 while (set != NULL) {
3792 next = set->next;
3793 xmlFree(set);
3794 set = next;
3795 }
3796}
3797
3798/**
3799 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003800 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003801 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003803 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003804void
Daniel Veillard3646d642004-06-02 19:19:14 +00003805xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3806{
3807 if (wildcard == NULL)
3808 return;
3809 if (wildcard->annot != NULL)
3810 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003811 if (wildcard->nsSet != NULL)
3812 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3813 if (wildcard->negNsSet != NULL)
3814 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003815 xmlFree(wildcard);
3816}
3817
3818/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003819 * xmlSchemaFreeAttributeGroup:
3820 * @schema: a schema attribute group structure
3821 *
3822 * Deallocate a Schema Attribute Group structure.
3823 */
3824static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003825xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003826{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003827 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003828 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003829 if (attrGr->annot != NULL)
3830 xmlSchemaFreeAnnot(attrGr->annot);
3831 if (attrGr->attrUses != NULL)
3832 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3833 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003834}
3835
3836/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003837 * xmlSchemaFreeQNameRef:
3838 * @item: a QName reference structure
3839 *
3840 * Deallocatea a QName reference structure.
3841 */
3842static void
3843xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3844{
3845 xmlFree(item);
3846}
3847
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003848/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003849 * xmlSchemaFreeTypeLinkList:
3850 * @alink: a type link
3851 *
3852 * Deallocate a list of types.
3853 */
3854static void
3855xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3856{
3857 xmlSchemaTypeLinkPtr next;
3858
3859 while (link != NULL) {
3860 next = link->next;
3861 xmlFree(link);
3862 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003863 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003864}
3865
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003866static void
3867xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3868{
3869 xmlSchemaIDCStateObjPtr next;
3870 while (sto != NULL) {
3871 next = sto->next;
3872 if (sto->history != NULL)
3873 xmlFree(sto->history);
3874 if (sto->xpathCtxt != NULL)
3875 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3876 xmlFree(sto);
3877 sto = next;
3878 }
3879}
3880
3881/**
3882 * xmlSchemaFreeIDC:
3883 * @idc: a identity-constraint definition
3884 *
3885 * Deallocates an identity-constraint definition.
3886 */
3887static void
3888xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3889{
3890 xmlSchemaIDCSelectPtr cur, prev;
3891
3892 if (idcDef == NULL)
3893 return;
3894 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003895 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003896 /* Selector */
3897 if (idcDef->selector != NULL) {
3898 if (idcDef->selector->xpathComp != NULL)
3899 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3900 xmlFree(idcDef->selector);
3901 }
3902 /* Fields */
3903 if (idcDef->fields != NULL) {
3904 cur = idcDef->fields;
3905 do {
3906 prev = cur;
3907 cur = cur->next;
3908 if (prev->xpathComp != NULL)
3909 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003910 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003911 } while (cur != NULL);
3912 }
3913 xmlFree(idcDef);
3914}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003915
Daniel Veillard01fa6152004-06-29 17:04:39 +00003916/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003917 * xmlSchemaFreeElement:
3918 * @schema: a schema element structure
3919 *
3920 * Deallocate a Schema Element structure.
3921 */
3922static void
3923xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3924{
3925 if (elem == NULL)
3926 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003927 if (elem->annot != NULL)
3928 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003929 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003931 if (elem->defVal != NULL)
3932 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003933 xmlFree(elem);
3934}
3935
3936/**
3937 * xmlSchemaFreeFacet:
3938 * @facet: a schema facet structure
3939 *
3940 * Deallocate a Schema Facet structure.
3941 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003942void
Daniel Veillard4255d502002-04-16 15:50:10 +00003943xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3944{
3945 if (facet == NULL)
3946 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003947 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003948 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003949 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003950 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003951 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003952 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003953 xmlFree(facet);
3954}
3955
3956/**
3957 * xmlSchemaFreeType:
3958 * @type: a schema type structure
3959 *
3960 * Deallocate a Schema Type structure.
3961 */
3962void
3963xmlSchemaFreeType(xmlSchemaTypePtr type)
3964{
3965 if (type == NULL)
3966 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003967 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003968 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003969 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003970 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003971
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003972 facet = type->facets;
3973 while (facet != NULL) {
3974 next = facet->next;
3975 xmlSchemaFreeFacet(facet);
3976 facet = next;
3977 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003978 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003979 if (type->attrUses != NULL)
3980 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003981 if (type->memberTypes != NULL)
3982 xmlSchemaFreeTypeLinkList(type->memberTypes);
3983 if (type->facetSet != NULL) {
3984 xmlSchemaFacetLinkPtr next, link;
3985
3986 link = type->facetSet;
3987 do {
3988 next = link->next;
3989 xmlFree(link);
3990 link = next;
3991 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003992 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003993 if (type->contModel != NULL)
3994 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003995 xmlFree(type);
3996}
3997
3998/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003999 * xmlSchemaFreeModelGroupDef:
4000 * @item: a schema model group definition
4001 *
4002 * Deallocates a schema model group definition.
4003 */
4004static void
4005xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4006{
4007 if (item->annot != NULL)
4008 xmlSchemaFreeAnnot(item->annot);
4009 xmlFree(item);
4010}
4011
4012/**
4013 * xmlSchemaFreeModelGroup:
4014 * @item: a schema model group
4015 *
4016 * Deallocates a schema model group structure.
4017 */
4018static void
4019xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4020{
4021 if (item->annot != NULL)
4022 xmlSchemaFreeAnnot(item->annot);
4023 xmlFree(item);
4024}
4025
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004026static void
4027xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4028{
4029 if ((list == NULL) || (list->nbItems == 0))
4030 return;
4031 {
4032 xmlSchemaTreeItemPtr item;
4033 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4034 int i;
4035
4036 for (i = 0; i < list->nbItems; i++) {
4037 item = items[i];
4038 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004039 continue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004040 switch (item->type) {
4041 case XML_SCHEMA_TYPE_SIMPLE:
4042 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004043 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004044 break;
4045 case XML_SCHEMA_TYPE_ATTRIBUTE:
4046 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004047 break;
4048 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4049 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4050 break;
4051 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4052 xmlSchemaFreeAttributeUseProhib(
4053 (xmlSchemaAttributeUseProhibPtr) item);
4054 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004055 case XML_SCHEMA_TYPE_ELEMENT:
4056 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4057 break;
4058 case XML_SCHEMA_TYPE_PARTICLE:
4059 if (item->annot != NULL)
4060 xmlSchemaFreeAnnot(item->annot);
4061 xmlFree(item);
4062 break;
4063 case XML_SCHEMA_TYPE_SEQUENCE:
4064 case XML_SCHEMA_TYPE_CHOICE:
4065 case XML_SCHEMA_TYPE_ALL:
4066 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4067 break;
4068 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4069 xmlSchemaFreeAttributeGroup(
4070 (xmlSchemaAttributeGroupPtr) item);
4071 break;
4072 case XML_SCHEMA_TYPE_GROUP:
4073 xmlSchemaFreeModelGroupDef(
4074 (xmlSchemaModelGroupDefPtr) item);
4075 break;
4076 case XML_SCHEMA_TYPE_ANY:
4077 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4078 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4079 break;
4080 case XML_SCHEMA_TYPE_IDC_KEY:
4081 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4082 case XML_SCHEMA_TYPE_IDC_KEYREF:
4083 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4084 break;
4085 case XML_SCHEMA_TYPE_NOTATION:
4086 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4087 break;
4088 case XML_SCHEMA_EXTRA_QNAMEREF:
4089 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4090 break;
4091 default: {
4092 /* TODO: This should never be hit. */
4093 xmlSchemaPSimpleInternalErr(NULL,
4094 "Internal error: xmlSchemaComponentListFree, "
4095 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004096 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004097 }
4098 break;
4099 }
4100 }
4101 list->nbItems = 0;
4102 }
4103}
4104
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004105/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004106 * xmlSchemaFree:
4107 * @schema: a schema structure
4108 *
4109 * Deallocate a Schema structure.
4110 */
4111void
4112xmlSchemaFree(xmlSchemaPtr schema)
4113{
4114 if (schema == NULL)
4115 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004116 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004117 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004118 TODO
4119 /*
4120 * Note that those slots are not responsible for freeing
4121 * schema components anymore; this will now be done by
4122 * the schema buckets.
4123 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004124 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004125 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004126 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004127 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004128 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004129 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004130 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004131 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004132 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004133 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004134 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004135 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004136 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004137 xmlHashFree(schema->idcDef, NULL);
4138
Daniel Veillard1d913862003-11-21 00:28:39 +00004139 if (schema->schemasImports != NULL)
4140 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004141 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004142 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004143 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4144 int i;
4145 for (i = 0; i < list->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +00004146 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004147 }
4148 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004149 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004150 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004151 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004152 /* Never free the doc here, since this will be done by the buckets. */
4153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004154 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004155 xmlFree(schema);
4156}
4157
4158/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004159 * *
4160 * Debug functions *
4161 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004162 ************************************************************************/
4163
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004164#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004165
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004166static void
4167xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4168
Daniel Veillard4255d502002-04-16 15:50:10 +00004169/**
4170 * xmlSchemaElementDump:
4171 * @elem: an element
4172 * @output: the file output
4173 *
4174 * Dump the element
4175 */
4176static void
4177xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004178 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004179 const xmlChar * namespace ATTRIBUTE_UNUSED,
4180 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004181{
4182 if (elem == NULL)
4183 return;
4184
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004185
4186 fprintf(output, "Element");
4187 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4188 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004189 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004190 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004191 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004192 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004193#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004194 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004195 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004196 if (elem->maxOccurs >= UNBOUNDED)
4197 fprintf(output, "max: unbounded\n");
4198 else if (elem->maxOccurs != 1)
4199 fprintf(output, "max: %d\n", elem->maxOccurs);
4200 else
4201 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004202 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004203#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004204 /*
4205 * Misc other properties.
4206 */
4207 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4208 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4209 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004210 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004211 fprintf(output, " props: ");
4212 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4213 fprintf(output, "[fixed] ");
4214 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4215 fprintf(output, "[default] ");
4216 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4217 fprintf(output, "[abstract] ");
4218 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4219 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004220 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004221 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004222 /*
4223 * Default/fixed value.
4224 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004226 fprintf(output, " value: '%s'\n", elem->value);
4227 /*
4228 * Type.
4229 */
4230 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004231 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004232 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004233 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004234 else
4235 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004236 } else if (elem->subtypes != NULL) {
4237 /*
4238 * Dump local types.
4239 */
4240 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004241 }
4242 /*
4243 * Substitution group.
4244 */
4245 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004246 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004247 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004248 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004249 else
4250 fprintf(output, "\n");
4251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004252}
4253
4254/**
4255 * xmlSchemaAnnotDump:
4256 * @output: the file output
4257 * @annot: a annotation
4258 *
4259 * Dump the annotation
4260 */
4261static void
4262xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4263{
4264 xmlChar *content;
4265
4266 if (annot == NULL)
4267 return;
4268
4269 content = xmlNodeGetContent(annot->content);
4270 if (content != NULL) {
4271 fprintf(output, " Annot: %s\n", content);
4272 xmlFree(content);
4273 } else
4274 fprintf(output, " Annot: empty\n");
4275}
4276
4277/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004278 * xmlSchemaContentModelDump:
4279 * @particle: the schema particle
4280 * @output: the file output
4281 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 *
4283 * Dump a SchemaType structure
4284 */
4285static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004286xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4287{
4288 xmlChar *str = NULL;
4289 xmlSchemaTreeItemPtr term;
4290 char shift[100];
4291 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004292
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004293 if (particle == NULL)
4294 return;
4295 for (i = 0;((i < depth) && (i < 25));i++)
4296 shift[2 * i] = shift[2 * i + 1] = ' ';
4297 shift[2 * i] = shift[2 * i + 1] = 0;
Daniel Veillardbccae2d2009-06-04 11:22:45 +02004298 fprintf(output, "%s", shift);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004299 if (particle->children == NULL) {
4300 fprintf(output, "MISSING particle term\n");
4301 return;
4302 }
4303 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004304 if (term == NULL) {
4305 fprintf(output, "(NULL)");
4306 } else {
4307 switch (term->type) {
4308 case XML_SCHEMA_TYPE_ELEMENT:
4309 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4310 ((xmlSchemaElementPtr)term)->targetNamespace,
4311 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004312 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004313 break;
4314 case XML_SCHEMA_TYPE_SEQUENCE:
4315 fprintf(output, "SEQUENCE");
4316 break;
4317 case XML_SCHEMA_TYPE_CHOICE:
4318 fprintf(output, "CHOICE");
4319 break;
4320 case XML_SCHEMA_TYPE_ALL:
4321 fprintf(output, "ALL");
4322 break;
4323 case XML_SCHEMA_TYPE_ANY:
4324 fprintf(output, "ANY");
4325 break;
4326 default:
4327 fprintf(output, "UNKNOWN\n");
4328 return;
4329 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004330 }
4331 if (particle->minOccurs != 1)
4332 fprintf(output, " min: %d", particle->minOccurs);
4333 if (particle->maxOccurs >= UNBOUNDED)
4334 fprintf(output, " max: unbounded");
4335 else if (particle->maxOccurs != 1)
4336 fprintf(output, " max: %d", particle->maxOccurs);
4337 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004338 if (term &&
4339 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4340 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4341 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4342 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004343 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4344 output, depth +1);
4345 }
4346 if (particle->next != NULL)
4347 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4348 output, depth);
4349}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004350
4351/**
4352 * xmlSchemaAttrUsesDump:
4353 * @uses: attribute uses list
Daniel Veillarddee23482008-04-11 12:58:43 +00004354 * @output: the file output
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004355 *
4356 * Dumps a list of attribute use components.
4357 */
4358static void
4359xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4360{
4361 xmlSchemaAttributeUsePtr use;
4362 xmlSchemaAttributeUseProhibPtr prohib;
4363 xmlSchemaQNameRefPtr ref;
4364 const xmlChar *name, *tns;
4365 xmlChar *str = NULL;
4366 int i;
4367
4368 if ((uses == NULL) || (uses->nbItems == 0))
4369 return;
4370
Daniel Veillarddee23482008-04-11 12:58:43 +00004371 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004372 for (i = 0; i < uses->nbItems; i++) {
4373 use = uses->items[i];
4374 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4375 fprintf(output, " [prohibition] ");
4376 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4377 name = prohib->name;
4378 tns = prohib->targetNamespace;
4379 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4380 fprintf(output, " [reference] ");
4381 ref = (xmlSchemaQNameRefPtr) use;
4382 name = ref->name;
4383 tns = ref->targetNamespace;
4384 } else {
4385 fprintf(output, " [use] ");
4386 name = WXS_ATTRUSE_DECL_NAME(use);
4387 tns = WXS_ATTRUSE_DECL_TNS(use);
4388 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004389 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004390 (const char *) xmlSchemaFormatQName(&str, tns, name));
4391 FREE_AND_NULL(str);
4392 }
4393}
4394
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004395/**
4396 * xmlSchemaTypeDump:
4397 * @output: the file output
4398 * @type: a type structure
4399 *
4400 * Dump a SchemaType structure
4401 */
4402static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004403xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4404{
4405 if (type == NULL) {
4406 fprintf(output, "Type: NULL\n");
4407 return;
4408 }
4409 fprintf(output, "Type: ");
4410 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004411 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004413 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004414 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004415 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004416 switch (type->type) {
4417 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004418 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004419 break;
4420 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004421 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004422 break;
4423 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004424 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004425 break;
4426 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004427 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004428 break;
4429 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004430 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004431 break;
4432 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004433 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 break;
4435 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004436 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004437 break;
4438 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004439 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 break;
4441 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004442 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 break;
4444 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004445 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004447 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004448 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004450 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004451 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004452 break;
4453 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004454 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004455 break;
4456 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004457 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004458 break;
4459 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004460 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004461 break;
4462 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004463 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004464 break;
4465 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004466 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004467 break;
4468 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004469 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004470 break;
4471 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004472 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 }
4475 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004476 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004477 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004478 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004479 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004480 else
4481 fprintf(output, "\n");
4482 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004483 if (type->attrUses != NULL)
4484 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004485 if (type->annot != NULL)
4486 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004487#ifdef DUMP_CONTENT_MODEL
4488 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4489 (type->subtypes != NULL)) {
4490 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4491 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004493#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004494}
4495
4496/**
4497 * xmlSchemaDump:
4498 * @output: the file output
4499 * @schema: a schema structure
4500 *
4501 * Dump a Schema structure.
4502 */
4503void
4504xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4505{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004506 if (output == NULL)
4507 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 if (schema == NULL) {
4509 fprintf(output, "Schemas: NULL\n");
4510 return;
4511 }
4512 fprintf(output, "Schemas: ");
4513 if (schema->name != NULL)
4514 fprintf(output, "%s, ", schema->name);
4515 else
4516 fprintf(output, "no name, ");
4517 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004518 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004519 else
4520 fprintf(output, "no target namespace");
4521 fprintf(output, "\n");
4522 if (schema->annot != NULL)
4523 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004524 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4525 output);
4526 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004528}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004529
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004530#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004531/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004533 * @vctxt: the WXS validation context
4534 *
4535 * Displays the current IDC table for debug purposes.
4536 */
4537static void
4538xmlSchemaDebugDumpIDCTable(FILE * output,
4539 const xmlChar *namespaceName,
4540 const xmlChar *localName,
4541 xmlSchemaPSVIIDCBindingPtr bind)
4542{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004543 xmlChar *str = NULL;
4544 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004545 xmlSchemaPSVIIDCNodePtr tab;
4546 xmlSchemaPSVIIDCKeyPtr key;
4547 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004548
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004549 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004550 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004551 FREE_AND_NULL(str)
4552
4553 if (bind == NULL)
4554 return;
4555 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004556 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Daniel Veillarddee23482008-04-11 12:58:43 +00004557 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004558 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004559 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004560 for (i = 0; i < bind->nbNodes; i++) {
4561 tab = bind->nodeTable[i];
4562 fprintf(output, " ( ");
4563 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004564 key = tab->keys[j];
4565 if ((key != NULL) && (key->val != NULL)) {
4566 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004567 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004568 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004569 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004570 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004572 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004573 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004574 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004575 else
4576 fprintf(output, "(key missing), ");
4577 }
4578 fprintf(output, ")\n");
4579 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004580 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004581 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004582 for (i = 0; i < bind->dupls->nbItems; i++) {
4583 tab = bind->dupls->items[i];
4584 fprintf(output, " ( ");
4585 for (j = 0; j < bind->definition->nbFields; j++) {
4586 key = tab->keys[j];
4587 if ((key != NULL) && (key->val != NULL)) {
4588 res = xmlSchemaGetCanonValue(key->val, &value);
4589 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004590 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004591 else
4592 fprintf(output, "CANON-VALUE-FAILED ");
4593 if (res == 0)
4594 FREE_AND_NULL(value)
4595 } else if (key != NULL)
4596 fprintf(output, "(no val), ");
4597 else
4598 fprintf(output, "(key missing), ");
4599 }
4600 fprintf(output, ")\n");
4601 }
4602 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004603 bind = bind->next;
4604 } while (bind != NULL);
4605}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004606#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004607#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004608
4609/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004610 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004611 * Utilities *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004612 * *
4613 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004614
Daniel Veillardc0826a72004-08-10 14:17:33 +00004615/**
4616 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004617 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004618 * @name: the name of the attribute
4619 *
4620 * Seeks an attribute with a name of @name in
4621 * no namespace.
4622 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004623 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004624 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004625static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004626xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004627{
4628 xmlAttrPtr prop;
4629
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004630 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004631 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004632 prop = node->properties;
4633 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004634 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004635 return(prop);
4636 prop = prop->next;
4637 }
4638 return (NULL);
4639}
4640
4641/**
4642 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004643 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004644 * @uri: the uri
4645 * @name: the name of the attribute
4646 *
4647 * Seeks an attribute with a local name of @name and
4648 * a namespace URI of @uri.
4649 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004650 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004651 */
4652static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004653xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004654{
4655 xmlAttrPtr prop;
4656
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004657 if ((node == NULL) || (name == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00004658 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004659 prop = node->properties;
4660 while (prop != NULL) {
4661 if ((prop->ns != NULL) &&
4662 xmlStrEqual(prop->name, BAD_CAST name) &&
4663 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004664 return(prop);
4665 prop = prop->next;
4666 }
4667 return (NULL);
4668}
4669
4670static const xmlChar *
4671xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4672{
4673 xmlChar *val;
4674 const xmlChar *ret;
4675
4676 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004677 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004678 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004679 ret = xmlDictLookup(ctxt->dict, val, -1);
4680 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004681 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004682}
4683
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004684static const xmlChar *
4685xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4686{
4687 return((const xmlChar*) xmlNodeGetContent(node));
4688}
4689
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004690/**
4691 * xmlSchemaGetProp:
4692 * @ctxt: the parser context
4693 * @node: the node
4694 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004695 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004696 * Read a attribute value and internalize the string
4697 *
4698 * Returns the string or NULL if not present.
4699 */
4700static const xmlChar *
4701xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4702 const char *name)
4703{
4704 xmlChar *val;
4705 const xmlChar *ret;
4706
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004707 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004708 if (val == NULL)
4709 return(NULL);
4710 ret = xmlDictLookup(ctxt->dict, val, -1);
4711 xmlFree(val);
4712 return(ret);
4713}
4714
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004715/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004716 * *
4717 * Parsing functions *
4718 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 ************************************************************************/
4720
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004721#define WXS_FIND_GLOBAL_ITEM(slot) \
4722 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4723 ret = xmlHashLookup(schema->slot, name); \
4724 if (ret != NULL) goto exit; \
4725 } \
4726 if (xmlHashSize(schema->schemasImports) > 1) { \
4727 xmlSchemaImportPtr import; \
4728 if (nsName == NULL) \
4729 import = xmlHashLookup(schema->schemasImports, \
4730 XML_SCHEMAS_NO_NAMESPACE); \
4731 else \
4732 import = xmlHashLookup(schema->schemasImports, nsName); \
4733 if (import == NULL) \
4734 goto exit; \
4735 ret = xmlHashLookup(import->schema->slot, name); \
4736 }
4737
Daniel Veillard4255d502002-04-16 15:50:10 +00004738/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004739 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004740 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004741 * @name: the element name
4742 * @ns: the element namespace
4743 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004744 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004745 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004746 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004747 */
4748static xmlSchemaElementPtr
4749xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004750 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004751{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004752 xmlSchemaElementPtr ret = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00004753
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004754 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004755 return(NULL);
4756 if (schema != NULL) {
4757 WXS_FIND_GLOBAL_ITEM(elemDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004758 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004759exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004760#ifdef DEBUG
4761 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004762 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004763 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004764 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004765 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004766 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004767 }
4768#endif
4769 return (ret);
4770}
4771
4772/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004773 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004774 * @schema: the main schema
4775 * @name: the type's name
4776 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004777 *
4778 * Lookup a type in the schemas or the predefined types
4779 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004781 */
4782static xmlSchemaTypePtr
4783xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004784 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004786 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004787
4788 if (name == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004789 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004790 /* First try the built-in types. */
Daniel Veillarddee23482008-04-11 12:58:43 +00004791 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004792 ret = xmlSchemaGetPredefinedType(name, nsName);
4793 if (ret != NULL)
4794 goto exit;
4795 /*
4796 * Note that we try the parsed schemas as well here
4797 * since one might have parsed the S4S, which contain more
4798 * than the built-in types.
4799 * TODO: Can we optimize this?
4800 */
4801 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004803 WXS_FIND_GLOBAL_ITEM(typeDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004804 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004805exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004806
Daniel Veillard4255d502002-04-16 15:50:10 +00004807#ifdef DEBUG
4808 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004809 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 fprintf(stderr, "Unable to lookup type %s", name);
4811 else
4812 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004813 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 }
4815#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004816 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004817}
4818
Daniel Veillard3646d642004-06-02 19:19:14 +00004819/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004820 * xmlSchemaGetAttributeDecl:
4821 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004822 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004823 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004824 *
4825 * Lookup a an attribute in the schema or imported schemas
4826 *
4827 * Returns the attribute declaration or NULL if not found.
4828 */
4829static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004830xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004831 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004832{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004833 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004834
4835 if ((name == NULL) || (schema == NULL))
4836 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004837 if (schema != NULL) {
4838 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004839 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004840exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004841#ifdef DEBUG
4842 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004843 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004844 fprintf(stderr, "Unable to lookup attribute %s", name);
4845 else
4846 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004847 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004848 }
4849#endif
4850 return (ret);
4851}
4852
4853/**
4854 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004855 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004857 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004858 *
4859 * Lookup a an attribute group in the schema or imported schemas
4860 *
4861 * Returns the attribute group definition or NULL if not found.
4862 */
4863static xmlSchemaAttributeGroupPtr
4864xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004865 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004866{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004867 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004868
4869 if ((name == NULL) || (schema == NULL))
4870 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004871 if (schema != NULL) {
4872 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4873 }
4874exit:
4875 /* TODO:
4876 if ((ret != NULL) && (ret->redef != NULL)) {
4877 * Return the last redefinition. *
4878 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004879 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004880 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004881#ifdef DEBUG
4882 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004883 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004884 fprintf(stderr, "Unable to lookup attribute group %s", name);
4885 else
4886 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004887 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004888 }
4889#endif
4890 return (ret);
4891}
4892
4893/**
4894 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004895 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004896 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004897 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004898 *
4899 * Lookup a group in the schema or imported schemas
4900 *
4901 * Returns the group definition or NULL if not found.
4902 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004903static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004904xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004905 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004906{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004907 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004908
4909 if ((name == NULL) || (schema == NULL))
4910 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004911 if (schema != NULL) {
4912 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004913 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004914exit:
Daniel Veillarddee23482008-04-11 12:58:43 +00004915
Daniel Veillard3646d642004-06-02 19:19:14 +00004916#ifdef DEBUG
4917 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004918 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004919 fprintf(stderr, "Unable to lookup group %s", name);
4920 else
4921 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004922 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004923 }
4924#endif
4925 return (ret);
4926}
4927
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004928static xmlSchemaNotationPtr
4929xmlSchemaGetNotation(xmlSchemaPtr schema,
4930 const xmlChar *name,
4931 const xmlChar *nsName)
4932{
4933 xmlSchemaNotationPtr ret = NULL;
4934
4935 if ((name == NULL) || (schema == NULL))
4936 return (NULL);
4937 if (schema != NULL) {
4938 WXS_FIND_GLOBAL_ITEM(notaDecl)
4939 }
4940exit:
4941 return (ret);
4942}
4943
4944static xmlSchemaIDCPtr
4945xmlSchemaGetIDC(xmlSchemaPtr schema,
4946 const xmlChar *name,
4947 const xmlChar *nsName)
4948{
4949 xmlSchemaIDCPtr ret = NULL;
4950
4951 if ((name == NULL) || (schema == NULL))
4952 return (NULL);
4953 if (schema != NULL) {
4954 WXS_FIND_GLOBAL_ITEM(idcDef)
4955 }
4956exit:
4957 return (ret);
4958}
4959
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004960/**
4961 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004962 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004963 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004965 *
4966 * Lookup a group in the schema or imported schemas
4967 *
4968 * Returns the group definition or NULL if not found.
4969 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004970static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004971xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4972 xmlSchemaTypeType itemType,
4973 const xmlChar *name,
4974 const xmlChar *targetNs)
4975{
4976 switch (itemType) {
4977 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004978 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004979 name, targetNs));
4980 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004981 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004982 name, targetNs));
4983 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004984 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004985 return (NULL);
4986 }
4987}
4988
Daniel Veillard4255d502002-04-16 15:50:10 +00004989/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004990 * *
4991 * Parsing functions *
4992 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004993 ************************************************************************/
4994
4995#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004996 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004997
4998/**
4999 * xmlSchemaIsBlank:
5000 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00005002 *
5003 * Check if a string is ignorable
5004 *
5005 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5006 */
5007static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005008xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005009{
Daniel Veillard4255d502002-04-16 15:50:10 +00005010 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005011 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005012 if (len < 0) {
5013 while (*str != 0) {
5014 if (!(IS_BLANK_CH(*str)))
5015 return (0);
5016 str++;
5017 }
5018 } else while ((*str != 0) && (len != 0)) {
5019 if (!(IS_BLANK_CH(*str)))
5020 return (0);
5021 str++;
5022 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00005023 }
Daniel Veillarddee23482008-04-11 12:58:43 +00005024
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005025 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005026}
5027
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005028#define WXS_COMP_NAME(c, t) ((t) (c))->name
5029#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5030/*
5031* xmlSchemaFindRedefCompInGraph:
5032* ATTENTION TODO: This uses pointer comp. for strings.
5033*/
5034static xmlSchemaBasicItemPtr
5035xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5036 xmlSchemaTypeType type,
5037 const xmlChar *name,
5038 const xmlChar *nsName)
5039{
5040 xmlSchemaBasicItemPtr ret;
5041 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005042
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005043 if ((bucket == NULL) || (name == NULL))
5044 return(NULL);
5045 if ((bucket->globals == NULL) ||
5046 (bucket->globals->nbItems == 0))
5047 goto subschemas;
5048 /*
5049 * Search in global components.
5050 */
5051 for (i = 0; i < bucket->globals->nbItems; i++) {
5052 ret = bucket->globals->items[i];
5053 if (ret->type == type) {
5054 switch (type) {
5055 case XML_SCHEMA_TYPE_COMPLEX:
5056 case XML_SCHEMA_TYPE_SIMPLE:
5057 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5058 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5059 nsName))
5060 {
5061 return(ret);
5062 }
5063 break;
5064 case XML_SCHEMA_TYPE_GROUP:
5065 if ((WXS_COMP_NAME(ret,
5066 xmlSchemaModelGroupDefPtr) == name) &&
5067 (WXS_COMP_TNS(ret,
5068 xmlSchemaModelGroupDefPtr) == nsName))
5069 {
5070 return(ret);
5071 }
5072 break;
5073 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5074 if ((WXS_COMP_NAME(ret,
5075 xmlSchemaAttributeGroupPtr) == name) &&
5076 (WXS_COMP_TNS(ret,
5077 xmlSchemaAttributeGroupPtr) == nsName))
5078 {
5079 return(ret);
5080 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005081 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005082 default:
5083 /* Should not be hit. */
5084 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005085 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005086 }
5087 }
5088subschemas:
5089 /*
5090 * Process imported/included schemas.
5091 */
5092 if (bucket->relations != NULL) {
5093 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5094
5095 /*
5096 * TODO: Marking the bucket will not avoid multiple searches
5097 * in the same schema, but avoids at least circularity.
5098 */
5099 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5100 do {
5101 if ((rel->bucket != NULL) &&
5102 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5103 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5104 type, name, nsName);
5105 if (ret != NULL)
5106 return(ret);
5107 }
5108 rel = rel->next;
5109 } while (rel != NULL);
5110 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5111 }
5112 return(NULL);
5113}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005114
5115/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005116 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005117 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005118 * @schema: the schema being built
5119 * @name: the item name
5120 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005121 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005122 * *WARNING* this interface is highly subject to change
5123 *
5124 * Returns the new struture or NULL in case of error
5125 */
5126static xmlSchemaNotationPtr
5127xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005128 const xmlChar *name, const xmlChar *nsName,
5129 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005130{
5131 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005132
5133 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5134 return (NULL);
5135
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5137 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005139 return (NULL);
5140 }
5141 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005142 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005143 ret->name = name;
5144 ret->targetNamespace = nsName;
5145 /* TODO: do we need the node to be set?
5146 * ret->node = node;*/
5147 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005148 return (ret);
5149}
5150
Daniel Veillard4255d502002-04-16 15:50:10 +00005151/**
5152 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005153 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005154 * @schema: the schema being built
5155 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005156 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005157 *
5158 * Add an XML schema Attrribute declaration
5159 * *WARNING* this interface is highly subject to change
5160 *
5161 * Returns the new struture or NULL in case of error
5162 */
5163static xmlSchemaAttributePtr
5164xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005165 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005166 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005167{
5168 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005169
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005170 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005171 return (NULL);
5172
5173 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5174 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 return (NULL);
5177 }
5178 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005179 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5180 ret->node = node;
5181 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005182 ret->targetNamespace = nsName;
5183
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005184 if (topLevel)
5185 WXS_ADD_GLOBAL(ctxt, ret);
5186 else
5187 WXS_ADD_LOCAL(ctxt, ret);
5188 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 return (ret);
5190}
5191
5192/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005193 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005194 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 * @schema: the schema being built
5196 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005197 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005198 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005199 * Add an XML schema Attrribute declaration
5200 * *WARNING* this interface is highly subject to change
5201 *
5202 * Returns the new struture or NULL in case of error
5203 */
5204static xmlSchemaAttributeUsePtr
5205xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5206 xmlNodePtr node)
5207{
5208 xmlSchemaAttributeUsePtr ret = NULL;
5209
5210 if (pctxt == NULL)
5211 return (NULL);
5212
5213 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5214 if (ret == NULL) {
5215 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5216 return (NULL);
5217 }
5218 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5219 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5220 ret->node = node;
5221
5222 WXS_ADD_LOCAL(pctxt, ret);
5223 return (ret);
5224}
5225
5226/*
5227* xmlSchemaAddRedef:
5228*
5229* Adds a redefinition information. This is used at a later stage to:
5230* resolve references to the redefined components and to check constraints.
5231*/
5232static xmlSchemaRedefPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00005233xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005234 xmlSchemaBucketPtr targetBucket,
5235 void *item,
5236 const xmlChar *refName,
5237 const xmlChar *refTargetNs)
5238{
5239 xmlSchemaRedefPtr ret;
5240
5241 ret = (xmlSchemaRedefPtr)
5242 xmlMalloc(sizeof(xmlSchemaRedef));
5243 if (ret == NULL) {
5244 xmlSchemaPErrMemory(pctxt,
5245 "allocating redefinition info", NULL);
5246 return (NULL);
5247 }
5248 memset(ret, 0, sizeof(xmlSchemaRedef));
5249 ret->item = item;
5250 ret->targetBucket = targetBucket;
5251 ret->refName = refName;
5252 ret->refTargetNs = refTargetNs;
5253 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5254 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5255 else
5256 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5257 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5258
5259 return (ret);
5260}
5261
5262/**
5263 * xmlSchemaAddAttributeGroupDefinition:
5264 * @ctxt: a schema parser context
5265 * @schema: the schema being built
5266 * @name: the item name
5267 * @nsName: the target namespace
5268 * @node: the corresponding node
5269 *
5270 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005271 *
5272 * Returns the new struture or NULL in case of error
5273 */
5274static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005275xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5276 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5277 const xmlChar *name,
5278 const xmlChar *nsName,
5279 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005280{
5281 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005282
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005283 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005284 return (NULL);
5285
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005286 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005287 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005289 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005290 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005291 }
5292 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005293 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005294 ret->name = name;
5295 ret->targetNamespace = nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +00005296 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005297
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005298 /* TODO: Remove the flag. */
5299 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5300 if (pctxt->isRedefine) {
5301 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5302 ret, name, nsName);
5303 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005304 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005305 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005306 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005307 pctxt->redefCounter = 0;
5308 }
5309 WXS_ADD_GLOBAL(pctxt, ret);
5310 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005311 return (ret);
5312}
5313
5314/**
5315 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005316 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 * @schema: the schema being built
5318 * @name: the type name
5319 * @namespace: the type namespace
5320 *
5321 * Add an XML schema Element declaration
5322 * *WARNING* this interface is highly subject to change
5323 *
5324 * Returns the new struture or NULL in case of error
5325 */
5326static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005327xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005328 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005329 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005330{
5331 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005332
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005333 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005334 return (NULL);
5335
Daniel Veillard4255d502002-04-16 15:50:10 +00005336 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5337 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005339 return (NULL);
5340 }
5341 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005342 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5343 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005344 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005345 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005346
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005347 if (topLevel)
5348 WXS_ADD_GLOBAL(ctxt, ret);
5349 else
5350 WXS_ADD_LOCAL(ctxt, ret);
5351 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005352 return (ret);
5353}
5354
5355/**
5356 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005357 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005358 * @schema: the schema being built
5359 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005360 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005361 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005362 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005363 * *WARNING* this interface is highly subject to change
5364 *
5365 * Returns the new struture or NULL in case of error
5366 */
5367static xmlSchemaTypePtr
5368xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005369 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005370 const xmlChar * name, const xmlChar * nsName,
5371 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005372{
5373 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005374
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005375 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005376 return (NULL);
5377
5378 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5379 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005380 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005381 return (NULL);
5382 }
5383 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005384 ret->type = type;
5385 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005386 ret->targetNamespace = nsName;
5387 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005388 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005389 if (ctxt->isRedefine) {
5390 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5391 ret, name, nsName);
5392 if (ctxt->redef == NULL) {
5393 xmlFree(ret);
5394 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005395 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005396 ctxt->redefCounter = 0;
5397 }
5398 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005399 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005400 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005401 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005402 return (ret);
5403}
5404
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005405static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005406xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005407 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005408 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005409 const xmlChar *refNs)
5410{
5411 xmlSchemaQNameRefPtr ret;
5412
5413 ret = (xmlSchemaQNameRefPtr)
5414 xmlMalloc(sizeof(xmlSchemaQNameRef));
5415 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005416 xmlSchemaPErrMemory(pctxt,
5417 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005418 return (NULL);
5419 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005420 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005421 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5422 ret->name = refName;
5423 ret->targetNamespace = refNs;
5424 ret->item = NULL;
5425 ret->itemType = refType;
5426 /*
5427 * Store the reference item in the schema.
5428 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005429 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430 return (ret);
5431}
5432
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005433static xmlSchemaAttributeUseProhibPtr
5434xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5435{
5436 xmlSchemaAttributeUseProhibPtr ret;
5437
5438 ret = (xmlSchemaAttributeUseProhibPtr)
5439 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5440 if (ret == NULL) {
5441 xmlSchemaPErrMemory(pctxt,
5442 "allocating attribute use prohibition", NULL);
5443 return (NULL);
5444 }
5445 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5446 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5447 WXS_ADD_LOCAL(pctxt, ret);
5448 return (ret);
5449}
5450
5451
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005452/**
5453 * xmlSchemaAddModelGroup:
5454 * @ctxt: a schema parser context
5455 * @schema: the schema being built
5456 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005457 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005458 *
5459 * Adds a schema model group
5460 * *WARNING* this interface is highly subject to change
5461 *
5462 * Returns the new struture or NULL in case of error
5463 */
5464static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005465xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5466 xmlSchemaPtr schema,
5467 xmlSchemaTypeType type,
5468 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005469{
5470 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005471
5472 if ((ctxt == NULL) || (schema == NULL))
5473 return (NULL);
5474
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005475 ret = (xmlSchemaModelGroupPtr)
5476 xmlMalloc(sizeof(xmlSchemaModelGroup));
5477 if (ret == NULL) {
5478 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5479 NULL);
5480 return (NULL);
5481 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005482 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005483 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005484 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005485 WXS_ADD_LOCAL(ctxt, ret);
5486 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5487 (type == XML_SCHEMA_TYPE_CHOICE))
5488 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005489 return (ret);
5490}
5491
5492
5493/**
5494 * xmlSchemaAddParticle:
5495 * @ctxt: a schema parser context
5496 * @schema: the schema being built
5497 * @node: the corresponding node in the schema doc
5498 * @min: the minOccurs
5499 * @max: the maxOccurs
5500 *
5501 * Adds an XML schema particle component.
5502 * *WARNING* this interface is highly subject to change
5503 *
5504 * Returns the new struture or NULL in case of error
5505 */
5506static xmlSchemaParticlePtr
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005507xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005508 xmlNodePtr node, int min, int max)
5509{
5510 xmlSchemaParticlePtr ret = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005511 if (ctxt == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005512 return (NULL);
5513
5514#ifdef DEBUG
5515 fprintf(stderr, "Adding particle component\n");
5516#endif
5517 ret = (xmlSchemaParticlePtr)
5518 xmlMalloc(sizeof(xmlSchemaParticle));
5519 if (ret == NULL) {
5520 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5521 NULL);
5522 return (NULL);
5523 }
5524 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5525 ret->annot = NULL;
5526 ret->node = node;
5527 ret->minOccurs = min;
5528 ret->maxOccurs = max;
5529 ret->next = NULL;
5530 ret->children = NULL;
5531
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005532 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005533 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005534 * Note that addition to pending components will be done locally
5535 * to the specific parsing function, since the most particles
5536 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005537 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005538 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005539 return (ret);
5540}
5541
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005542/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005543 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005544 * @ctxt: a schema validation context
5545 * @schema: the schema being built
5546 * @name: the group name
5547 *
5548 * Add an XML schema Group definition
5549 *
5550 * Returns the new struture or NULL in case of error
5551 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005552static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005553xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5554 xmlSchemaPtr schema,
5555 const xmlChar *name,
5556 const xmlChar *nsName,
5557 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005558{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005559 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005560
5561 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5562 return (NULL);
5563
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005564 ret = (xmlSchemaModelGroupDefPtr)
5565 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005566 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005568 return (NULL);
5569 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005570 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005571 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005572 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005573 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005574 ret->targetNamespace = nsName;
5575
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005576 if (ctxt->isRedefine) {
5577 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5578 ret, name, nsName);
5579 if (ctxt->redef == NULL) {
5580 xmlFree(ret);
5581 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005582 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005583 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005584 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005585 WXS_ADD_GLOBAL(ctxt, ret);
5586 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 return (ret);
5588}
5589
Daniel Veillard3646d642004-06-02 19:19:14 +00005590/**
5591 * xmlSchemaNewWildcardNs:
5592 * @ctxt: a schema validation context
5593 *
5594 * Creates a new wildcard namespace constraint.
5595 *
5596 * Returns the new struture or NULL in case of error
5597 */
5598static xmlSchemaWildcardNsPtr
5599xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5600{
5601 xmlSchemaWildcardNsPtr ret;
5602
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005603 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005604 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5605 if (ret == NULL) {
5606 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005607 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005608 }
5609 ret->value = NULL;
5610 ret->next = NULL;
5611 return (ret);
5612}
5613
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005614static xmlSchemaIDCPtr
5615xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5616 const xmlChar *name, const xmlChar *nsName,
5617 int category, xmlNodePtr node)
5618{
Daniel Veillarddee23482008-04-11 12:58:43 +00005619 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005620
5621 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5622 return (NULL);
5623
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005624 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5625 if (ret == NULL) {
5626 xmlSchemaPErrMemory(ctxt,
5627 "allocating an identity-constraint definition", NULL);
5628 return (NULL);
5629 }
5630 memset(ret, 0, sizeof(xmlSchemaIDC));
5631 /* The target namespace of the parent element declaration. */
5632 ret->targetNamespace = nsName;
5633 ret->name = name;
5634 ret->type = category;
Daniel Veillarddee23482008-04-11 12:58:43 +00005635 ret->node = node;
5636
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005637 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005638 /*
5639 * Only keyrefs need to be fixup up.
5640 */
5641 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005642 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005643 return (ret);
5644}
5645
Daniel Veillard3646d642004-06-02 19:19:14 +00005646/**
5647 * xmlSchemaAddWildcard:
5648 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005649 * @schema: a schema
5650 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005651 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005652 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005653 *
5654 * Returns the new struture or NULL in case of error
5655 */
5656static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005657xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5658 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005659{
5660 xmlSchemaWildcardPtr ret = NULL;
5661
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005662 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005663 return (NULL);
5664
5665 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5666 if (ret == NULL) {
5667 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5668 return (NULL);
5669 }
5670 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005671 ret->type = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00005672 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005673 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005674 return (ret);
5675}
5676
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005677static void
5678xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5679{
5680 if (group == NULL)
5681 return;
5682 if (group->members != NULL)
5683 xmlSchemaItemListFree(group->members);
5684 xmlFree(group);
5685}
5686
5687static xmlSchemaSubstGroupPtr
5688xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5689 xmlSchemaElementPtr head)
5690{
5691 xmlSchemaSubstGroupPtr ret;
5692
5693 /* Init subst group hash. */
5694 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5695 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5696 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5697 return(NULL);
5698 }
5699 /* Create a new substitution group. */
5700 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5701 if (ret == NULL) {
5702 xmlSchemaPErrMemory(NULL,
5703 "allocating a substitution group container", NULL);
5704 return(NULL);
5705 }
5706 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5707 ret->head = head;
5708 /* Create list of members. */
5709 ret->members = xmlSchemaItemListCreate();
5710 if (ret->members == NULL) {
5711 xmlSchemaSubstGroupFree(ret);
5712 return(NULL);
5713 }
5714 /* Add subst group to hash. */
5715 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5716 head->name, head->targetNamespace, ret) != 0) {
5717 PERROR_INT("xmlSchemaSubstGroupAdd",
5718 "failed to add a new substitution container");
5719 xmlSchemaSubstGroupFree(ret);
5720 return(NULL);
5721 }
5722 return(ret);
5723}
5724
5725static xmlSchemaSubstGroupPtr
5726xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5727 xmlSchemaElementPtr head)
Daniel Veillarddee23482008-04-11 12:58:43 +00005728{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005729 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5730 return(NULL);
5731 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5732 head->name, head->targetNamespace));
5733
5734}
5735
5736/**
5737 * xmlSchemaAddElementSubstitutionMember:
5738 * @pctxt: a schema parser context
5739 * @head: the head of the substitution group
5740 * @member: the new member of the substitution group
5741 *
5742 * Allocate a new annotation structure.
5743 *
5744 * Returns the newly allocated structure or NULL in case or error
5745 */
5746static int
5747xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5748 xmlSchemaElementPtr head,
5749 xmlSchemaElementPtr member)
5750{
5751 xmlSchemaSubstGroupPtr substGroup = NULL;
5752
5753 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5754 return (-1);
5755
5756 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5757 if (substGroup == NULL)
5758 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5759 if (substGroup == NULL)
5760 return(-1);
5761 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5762 return(-1);
5763 return(0);
5764}
5765
Daniel Veillard4255d502002-04-16 15:50:10 +00005766/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005767 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005768 * Utilities for parsing *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005769 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 ************************************************************************/
5771
Daniel Veillard4255d502002-04-16 15:50:10 +00005772/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005773 * xmlSchemaPValAttrNodeQNameValue:
5774 * @ctxt: a schema parser context
5775 * @schema: the schema context
5776 * @ownerDes: the designation of the parent element
5777 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005778 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779 * @local: the resulting local part if found, the attribute value otherwise
5780 * @uri: the resulting namespace URI if found
5781 *
5782 * Extracts the local name and the URI of a QName value and validates it.
5783 * This one is intended to be used on attribute values that
5784 * should resolve to schema components.
5785 *
5786 * Returns 0, in case the QName is valid, a positive error code
5787 * if not valid and -1 if an internal error occurs.
5788 */
5789static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005790xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005792 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 xmlAttrPtr attr,
5794 const xmlChar *value,
5795 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005796 const xmlChar **local)
5797{
5798 const xmlChar *pref;
5799 xmlNsPtr ns;
5800 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005801
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 *uri = NULL;
5803 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005804 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005805 if (ret > 0) {
5806 xmlSchemaPSimpleTypeErr(ctxt,
5807 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5808 ownerItem, (xmlNodePtr) attr,
5809 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5810 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005812 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005813 } else if (ret < 0)
5814 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005815
5816 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005817 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005818 if (ns)
5819 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5820 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005821 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5822 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005823 /*
5824 * This one takes care of included schemas with no
5825 * target namespace.
5826 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005827 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005828 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005829 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005830 return (0);
5831 }
5832 /*
5833 * At this point xmlSplitQName3 has to return a local name.
5834 */
5835 *local = xmlSplitQName3(value, &len);
5836 *local = xmlDictLookup(ctxt->dict, *local, -1);
5837 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005838 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5839 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005840 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005841 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005842 ownerItem, (xmlNodePtr) attr,
5843 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5844 "The value '%s' of simple type 'xs:QName' has no "
5845 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005846 return (ctxt->err);
5847 } else {
5848 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005849 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850 return (0);
5851}
5852
5853/**
5854 * xmlSchemaPValAttrNodeQName:
5855 * @ctxt: a schema parser context
5856 * @schema: the schema context
5857 * @ownerDes: the designation of the owner element
5858 * @ownerItem: the owner as a schema object
5859 * @attr: the attribute node
5860 * @local: the resulting local part if found, the attribute value otherwise
5861 * @uri: the resulting namespace URI if found
5862 *
5863 * Extracts and validates the QName of an attribute value.
5864 * This one is intended to be used on attribute values that
5865 * should resolve to schema components.
5866 *
5867 * Returns 0, in case the QName is valid, a positive error code
5868 * if not valid and -1 if an internal error occurs.
5869 */
5870static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005871xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005872 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005873 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005874 xmlAttrPtr attr,
5875 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005876 const xmlChar **local)
5877{
5878 const xmlChar *value;
5879
5880 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005881 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005882 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005883}
5884
5885/**
5886 * xmlSchemaPValAttrQName:
5887 * @ctxt: a schema parser context
5888 * @schema: the schema context
5889 * @ownerDes: the designation of the parent element
5890 * @ownerItem: the owner as a schema object
5891 * @ownerElem: the parent node of the attribute
5892 * @name: the name of the attribute
5893 * @local: the resulting local part if found, the attribute value otherwise
5894 * @uri: the resulting namespace URI if found
5895 *
5896 * Extracts and validates the QName of an attribute value.
5897 *
5898 * Returns 0, in case the QName is valid, a positive error code
5899 * if not valid and -1 if an internal error occurs.
5900 */
5901static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005902xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5903 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005904 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 xmlNodePtr ownerElem,
5906 const char *name,
5907 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005908 const xmlChar **local)
5909{
5910 xmlAttrPtr attr;
5911
5912 attr = xmlSchemaGetPropNode(ownerElem, name);
5913 if (attr == NULL) {
5914 *local = NULL;
5915 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005918 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005919 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005920}
5921
5922/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005923 * xmlSchemaPValAttrID:
5924 * @ctxt: a schema parser context
5925 * @schema: the schema context
5926 * @ownerDes: the designation of the parent element
5927 * @ownerItem: the owner as a schema object
5928 * @ownerElem: the parent node of the attribute
5929 * @name: the name of the attribute
5930 *
5931 * Extracts and validates the ID of an attribute value.
5932 *
5933 * Returns 0, in case the ID is valid, a positive error code
5934 * if not valid and -1 if an internal error occurs.
5935 */
5936static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005937xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005938{
5939 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005940 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005941
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005942 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005943 return(0);
5944 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5945 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005946 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005947 /*
5948 * NOTE: the IDness might have already be declared in the DTD
5949 */
5950 if (attr->atype != XML_ATTRIBUTE_ID) {
5951 xmlIDPtr res;
5952 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005953
5954 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005955 * TODO: Use xmlSchemaStrip here; it's not exported at this
5956 * moment.
5957 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005958 strip = xmlSchemaCollapseString(value);
5959 if (strip != NULL) {
5960 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005961 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005962 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005963 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005964 if (res == NULL) {
5965 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005966 xmlSchemaPSimpleTypeErr(ctxt,
5967 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005968 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005969 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5970 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005971 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005972 } else
5973 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005974 }
5975 } else if (ret > 0) {
5976 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005977 xmlSchemaPSimpleTypeErr(ctxt,
5978 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005979 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5981 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5982 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005983 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005984 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005985 if (value != NULL)
5986 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005987
5988 return (ret);
5989}
5990
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005991static int
5992xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5993 xmlNodePtr ownerElem,
5994 const xmlChar *name)
5995{
5996 xmlAttrPtr attr;
5997
5998 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5999 if (attr == NULL)
6000 return(0);
6001 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6002
6003}
6004
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006005/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006006 * xmlGetMaxOccurs:
6007 * @ctxt: a schema validation context
6008 * @node: a subtree containing XML Schema informations
6009 *
6010 * Get the maxOccurs property
6011 *
6012 * Returns the default if not found, or the value
6013 */
6014static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006015xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6016 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006017{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006018 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006020 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006021
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006022 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6023 if (attr == NULL)
6024 return (def);
6025 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006026
6027 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006028 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006029 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006030 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6031 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006032 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006033 val, NULL, NULL, NULL);
6034 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006035 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006036 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00006037 }
6038
6039 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006040 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006041 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006042 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006043 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006046 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 val, NULL, NULL, NULL);
6048 return (def);
6049 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006051 ret = ret * 10 + (*cur - '0');
6052 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 }
William M. Brack76e95df2003-10-18 16:20:14 +00006054 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006055 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006056 /*
6057 * TODO: Restrict the maximal value to Integer.
6058 */
6059 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006060 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006061 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6062 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006063 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006064 val, NULL, NULL, NULL);
6065 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006066 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006067 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006068}
6069
6070/**
6071 * xmlGetMinOccurs:
6072 * @ctxt: a schema validation context
6073 * @node: a subtree containing XML Schema informations
6074 *
6075 * Get the minOccurs property
6076 *
6077 * Returns the default if not found, or the value
6078 */
6079static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006080xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006081 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006082{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006083 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006084 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006085 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006086
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006087 attr = xmlSchemaGetPropNode(node, "minOccurs");
6088 if (attr == NULL)
6089 return (def);
6090 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006092 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006093 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006094 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006096 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6097 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006098 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006099 val, NULL, NULL, NULL);
6100 return (def);
6101 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006102 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006103 ret = ret * 10 + (*cur - '0');
6104 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006105 }
William M. Brack76e95df2003-10-18 16:20:14 +00006106 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006107 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006108 /*
6109 * TODO: Restrict the maximal value to Integer.
6110 */
6111 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006112 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006113 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6114 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006115 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006116 val, NULL, NULL, NULL);
6117 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006118 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006119 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006120}
6121
6122/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006123 * xmlSchemaPGetBoolNodeValue:
6124 * @ctxt: a schema validation context
6125 * @ownerDes: owner designation
6126 * @ownerItem: the owner as a schema item
6127 * @node: the node holding the value
6128 *
6129 * Converts a boolean string value into 1 or 0.
6130 *
6131 * Returns 0 or 1.
6132 */
6133static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006134xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006135 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006136 xmlNodePtr node)
6137{
6138 xmlChar *value = NULL;
6139 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006140
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006141 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006142 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006143 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006144 * An instance of a datatype that is defined as `boolean`
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006145 * can have the following legal literals {true, false, 1, 0}.
6146 */
6147 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6148 res = 1;
6149 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6150 res = 0;
6151 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6152 res = 1;
6153 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006154 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006155 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006156 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006157 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006158 ownerItem, node,
6159 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6160 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006161 NULL, NULL, NULL);
6162 }
6163 if (value != NULL)
6164 xmlFree(value);
6165 return (res);
6166}
6167
6168/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006169 * xmlGetBooleanProp:
6170 * @ctxt: a schema validation context
6171 * @node: a subtree containing XML Schema informations
6172 * @name: the attribute name
6173 * @def: the default value
6174 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006175 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006176 *
6177 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006178 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006179 */
6180static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006181xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006182 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006183 const char *name, int def)
6184{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006185 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006186
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006187 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006190 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006191 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006192 * An instance of a datatype that is defined as `boolean`
Daniel Veillardc0826a72004-08-10 14:17:33 +00006193 * can have the following legal literals {true, false, 1, 0}.
6194 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006195 if (xmlStrEqual(val, BAD_CAST "true"))
6196 def = 1;
6197 else if (xmlStrEqual(val, BAD_CAST "false"))
6198 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006199 else if (xmlStrEqual(val, BAD_CAST "1"))
6200 def = 1;
6201 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006202 def = 0;
6203 else {
6204 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006205 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006206 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006207 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006208 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6209 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006211 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006212}
6213
6214/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006215 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00006216 * Shema extraction from an Infoset *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006217 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00006218 ************************************************************************/
6219static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6220 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006221 xmlNodePtr node,
6222 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006223static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6224 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006225 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006226 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006227 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006228static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6229 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006230 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006231 xmlNodePtr node,
6232 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006233static xmlSchemaBasicItemPtr
6234xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6235 xmlSchemaPtr schema,
6236 xmlNodePtr node,
6237 xmlSchemaItemListPtr uses,
6238 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006239static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6240 xmlSchemaPtr schema,
6241 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006242static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006243xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6244 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006245
6246/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006247 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006248 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006249 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006250 * @ownerDes: the designation of the parent element
6251 * @ownerItem: the schema object owner if existent
6252 * @attr: the schema attribute node being validated
6253 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006254 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006255 *
6256 * Validates a value against the given built-in type.
6257 * This one is intended to be used internally for validation
6258 * of schema attribute values during parsing of the schema.
6259 *
6260 * Returns 0 if the value is valid, a positive error code
6261 * number otherwise and -1 in case of an internal or API error.
6262 */
6263static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006264xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006265 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 xmlAttrPtr attr,
6267 const xmlChar *value,
6268 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006269{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006270
6271 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006272
6273 /*
6274 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6275 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006276 */
6277 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006278 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006279 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6280 PERROR_INT("xmlSchemaPValAttrNodeValue",
6281 "the given type is not a built-in type");
6282 return (-1);
6283 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006284 switch (type->builtInType) {
6285 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006286 case XML_SCHEMAS_QNAME:
6287 case XML_SCHEMAS_ANYURI:
6288 case XML_SCHEMAS_TOKEN:
6289 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006290 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6291 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006292 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006293 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006295 "validation using the given type is not supported while "
6296 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006297 return (-1);
6298 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 /*
6301 * TODO: Should we use the S4S error codes instead?
6302 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006303 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304 PERROR_INT("xmlSchemaPValAttrNodeValue",
6305 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006306 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006307 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006308 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006309 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6310 else
6311 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +00006312 xmlSchemaPSimpleTypeErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 ret, ownerItem, (xmlNodePtr) attr,
6314 type, NULL, value, NULL, NULL, NULL);
6315 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006316 return (ret);
6317}
6318
6319/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006320 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006321 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 * @ctxt: a schema parser context
6323 * @ownerDes: the designation of the parent element
6324 * @ownerItem: the schema object owner if existent
6325 * @attr: the schema attribute node being validated
6326 * @type: the built-in type to be validated against
6327 * @value: the resulting value if any
6328 *
6329 * Extracts and validates a value against the given built-in type.
6330 * This one is intended to be used internally for validation
6331 * of schema attribute values during parsing of the schema.
6332 *
6333 * Returns 0 if the value is valid, a positive error code
6334 * number otherwise and -1 in case of an internal or API error.
6335 */
6336static int
6337xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006338 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006339 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006340 xmlSchemaTypePtr type,
6341 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006343 const xmlChar *val;
6344
6345 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 return (-1);
6347
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6349 if (value != NULL)
6350 *value = val;
6351
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006352 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354}
6355
6356/**
6357 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006359 * @ctxt: a schema parser context
6360 * @node: the element node of the attribute
6361 * @ownerDes: the designation of the parent element
6362 * @ownerItem: the schema object owner if existent
6363 * @ownerElem: the owner element node
6364 * @name: the name of the schema attribute node
6365 * @type: the built-in type to be validated against
6366 * @value: the resulting value if any
6367 *
6368 * Extracts and validates a value against the given built-in type.
6369 * This one is intended to be used internally for validation
6370 * of schema attribute values during parsing of the schema.
6371 *
6372 * Returns 0 if the value is valid, a positive error code
6373 * number otherwise and -1 in case of an internal or API error.
6374 */
6375static int
Daniel Veillarddee23482008-04-11 12:58:43 +00006376xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006377 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 xmlNodePtr ownerElem,
6379 const char *name,
6380 xmlSchemaTypePtr type,
6381 const xmlChar **value)
6382{
6383 xmlAttrPtr attr;
6384
6385 if ((ctxt == NULL) || (type == NULL)) {
6386 if (value != NULL)
6387 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006388 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 }
6390 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6391 if (value != NULL)
6392 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006393 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006394 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 "Internal error: xmlSchemaPValAttr, the given "
6396 "type '%s' is not a built-in type.\n",
6397 type->name, NULL);
6398 return (-1);
6399 }
6400 attr = xmlSchemaGetPropNode(ownerElem, name);
6401 if (attr == NULL) {
6402 if (value != NULL)
6403 *value = NULL;
6404 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006405 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006406 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 type, value));
6408}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006409
6410static int
6411xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006412 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006413 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006414 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006415 const xmlChar *namespaceName)
6416{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006417 /* TODO: Pointer comparison instead? */
6418 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006419 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006420 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006421 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006422 /*
6423 * Check if the referenced namespace was <import>ed.
6424 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006425 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006426 xmlSchemaSchemaRelationPtr rel;
6427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006428 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006429 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006430 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006431 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006432 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006433 rel = rel->next;
6434 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006435 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006436 /*
6437 * No matching <import>ed namespace found.
6438 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006439 {
6440 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6441
6442 if (namespaceName == NULL)
6443 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6444 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6445 "References from this schema to components in no "
6446 "namespace are not allowed, since not indicated by an "
6447 "import statement", NULL, NULL);
6448 else
6449 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6450 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6451 "References from this schema to components in the "
6452 "namespace '%s' are not allowed, since not indicated by an "
6453 "import statement", namespaceName, NULL);
6454 }
6455 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006456}
6457
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006459 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006460 * @ctxt: a schema validation context
6461 * @schema: the schema being built
6462 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006463 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006464 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006465 * Parses attribute uses and attribute declarations and
Daniel Veillarddee23482008-04-11 12:58:43 +00006466 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006467 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006468static int
6469xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6470 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6471 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006472{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006473 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006474
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006475 while ((IS_SCHEMA((*child), "attribute")) ||
6476 (IS_SCHEMA((*child), "attributeGroup"))) {
6477 if (IS_SCHEMA((*child), "attribute")) {
6478 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6479 *list, parentType);
6480 } else {
6481 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6482 if ((item != NULL) && (hasRefs != NULL))
6483 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006484 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006485 if (item != NULL) {
6486 if (*list == NULL) {
6487 /* TODO: Customize grow factor. */
6488 *list = xmlSchemaItemListCreate();
6489 if (*list == NULL)
6490 return(-1);
6491 }
6492 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6493 return(-1);
6494 }
6495 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006496 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006497 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006498}
6499
6500/**
6501 * xmlSchemaParseAnnotation:
6502 * @ctxt: a schema validation context
6503 * @schema: the schema being built
6504 * @node: a subtree containing XML Schema informations
6505 *
6506 * parse a XML schema Attrribute declaration
6507 * *WARNING* this interface is highly subject to change
6508 *
William M. Bracke7091952004-05-11 15:09:58 +00006509 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006510 * 1 in case of success.
6511 */
6512static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006513xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006514{
6515 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006516 xmlNodePtr child = NULL;
6517 xmlAttrPtr attr;
6518 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006519
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 /*
6521 * INFO: S4S completed.
6522 */
6523 /*
6524 * id = ID
6525 * {any attributes with non-schema namespace . . .}>
6526 * Content: (appinfo | documentation)*
6527 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006528 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006529 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006530 if (needed)
6531 ret = xmlSchemaNewAnnot(ctxt, node);
6532 else
6533 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 attr = node->properties;
6535 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006539 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540
6541 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006542 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 }
6544 attr = attr->next;
6545 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006546 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 /*
6548 * And now for the children...
6549 */
6550 child = node->children;
6551 while (child != NULL) {
6552 if (IS_SCHEMA(child, "appinfo")) {
6553 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006555 * source = anyURI
6556 * {any attributes with non-schema namespace . . .}>
6557 * Content: ({any})*
6558 */
6559 attr = child->properties;
6560 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006561 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006562 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006563 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006565
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006567 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 }
6569 attr = attr->next;
6570 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006571 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006572 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 child = child->next;
6574 } else if (IS_SCHEMA(child, "documentation")) {
6575 /* TODO: make available the content of "documentation". */
6576 /*
6577 * source = anyURI
6578 * {any attributes with non-schema namespace . . .}>
6579 * Content: ({any})*
6580 */
6581 attr = child->properties;
6582 while (attr != NULL) {
6583 if (attr->ns == NULL) {
6584 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006585 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006586 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006587 }
6588 } else {
6589 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6590 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6591 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006592
6593 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006594 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006595 }
6596 }
6597 attr = attr->next;
6598 }
6599 /*
6600 * Attribute "xml:lang".
6601 */
6602 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6603 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006604 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006605 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 child = child->next;
6607 } else {
6608 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006609 xmlSchemaPContentErr(ctxt,
6610 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006611 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006612 barked = 1;
6613 child = child->next;
6614 }
6615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006616
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 return (ret);
6618}
6619
6620/**
6621 * xmlSchemaParseFacet:
6622 * @ctxt: a schema validation context
6623 * @schema: the schema being built
6624 * @node: a subtree containing XML Schema informations
6625 *
6626 * parse a XML schema Facet declaration
6627 * *WARNING* this interface is highly subject to change
6628 *
6629 * Returns the new type structure or NULL in case of error
6630 */
6631static xmlSchemaFacetPtr
6632xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006633 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006634{
6635 xmlSchemaFacetPtr facet;
6636 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006637 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006638
6639 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6640 return (NULL);
6641
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006642 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006643 if (facet == NULL) {
6644 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6645 return (NULL);
6646 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006648 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006650 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6651 "Facet %s has no value\n", node->name, NULL);
6652 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006653 return (NULL);
6654 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006655 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006656 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006657 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006658 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006659 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006660 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006661 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006662 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006663 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006664 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006665 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006666 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006667 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006668 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006669 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006670 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006671 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006672 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006673 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006674 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006675 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006676 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6677 } else if (IS_SCHEMA(node, "minLength")) {
6678 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6679 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006680 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6681 "Unknown facet type %s\n", node->name, NULL);
6682 xmlSchemaFreeFacet(facet);
6683 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006684 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006685 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006686 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006687 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6688 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6689 const xmlChar *fixed;
6690
6691 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6692 if (fixed != NULL) {
6693 if (xmlStrEqual(fixed, BAD_CAST "true"))
6694 facet->fixed = 1;
6695 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 child = node->children;
6698
6699 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006700 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006701 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 }
6703 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006704 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6705 "Facet %s has unexpected child content\n",
6706 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006707 }
6708 return (facet);
6709}
6710
6711/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006712 * xmlSchemaParseWildcardNs:
6713 * @ctxt: a schema parser context
6714 * @wildc: the wildcard, already created
6715 * @node: a subtree containing XML Schema informations
6716 *
6717 * Parses the attribute "processContents" and "namespace"
6718 * of a xsd:anyAttribute and xsd:any.
6719 * *WARNING* this interface is highly subject to change
6720 *
6721 * Returns 0 if everything goes fine, a positive error code
6722 * if something is not valid and -1 if an internal error occurs.
6723 */
6724static int
6725xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006726 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006727 xmlSchemaWildcardPtr wildc,
6728 xmlNodePtr node)
6729{
6730 const xmlChar *pc, *ns, *dictnsItem;
6731 int ret = 0;
6732 xmlChar *nsItem;
6733 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6734 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006735
Daniel Veillardc0826a72004-08-10 14:17:33 +00006736 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6737 if ((pc == NULL)
6738 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6739 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6740 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6741 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6742 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6743 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6744 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006745 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006746 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006747 NULL, node,
6748 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 NULL, NULL, NULL);
6750 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006751 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006752 }
6753 /*
6754 * Build the namespace constraints.
6755 */
6756 attr = xmlSchemaGetPropNode(node, "namespace");
6757 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006758 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006759 wildc->any = 1;
6760 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6761 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006762 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006763 return (-1);
6764 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006765 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006767 const xmlChar *end, *cur;
6768
6769 cur = ns;
6770 do {
6771 while (IS_BLANK_CH(*cur))
6772 cur++;
6773 end = cur;
6774 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6775 end++;
6776 if (end == cur)
6777 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006778 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6780 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006781 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006782 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 NULL, (xmlNodePtr) attr,
6784 NULL,
6785 "((##any | ##other) | List of (xs:anyURI | "
6786 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006787 nsItem, NULL, NULL, NULL);
6788 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6789 } else {
6790 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006791 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6793 dictnsItem = NULL;
6794 } else {
6795 /*
6796 * Validate the item (anyURI).
6797 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006798 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006799 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6800 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6801 }
6802 /*
6803 * Avoid dublicate namespaces.
6804 */
6805 tmp = wildc->nsSet;
6806 while (tmp != NULL) {
6807 if (dictnsItem == tmp->value)
6808 break;
6809 tmp = tmp->next;
6810 }
6811 if (tmp == NULL) {
6812 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6813 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 return (-1);
6816 }
6817 tmp->value = dictnsItem;
6818 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006819 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006820 wildc->nsSet = tmp;
Daniel Veillard76d36452009-09-07 11:19:33 +02006821 else if (lastNs != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006822 lastNs->next = tmp;
6823 lastNs = tmp;
6824 }
6825
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006826 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 xmlFree(nsItem);
6828 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830 }
6831 return (ret);
6832}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006833
6834static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006835xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6836 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006837 xmlNodePtr node,
6838 int minOccurs,
6839 int maxOccurs) {
6840
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006841 if ((maxOccurs == 0) && ( minOccurs == 0))
6842 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006843 if (maxOccurs != UNBOUNDED) {
6844 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006845 * TODO: Maybe we should better not create the particle,
6846 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006847 * content model.
6848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006849 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006850 * 3.9.6 Schema Component Constraint: Particle Correct
6851 *
6852 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006853 if (maxOccurs < 1) {
6854 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006855 * 2.2 {max occurs} must be greater than or equal to 1.
6856 */
6857 xmlSchemaPCustomAttrErr(ctxt,
6858 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006859 NULL, NULL,
6860 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006861 "The value must be greater than or equal to 1");
6862 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6863 } else if (minOccurs > maxOccurs) {
6864 /*
6865 * 2.1 {min occurs} must not be greater than {max occurs}.
6866 */
6867 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006868 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006869 NULL, NULL,
6870 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006871 "The value must not be greater than the value of 'maxOccurs'");
6872 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6873 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006874 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006875 return (0);
6876}
6877
Daniel Veillardc0826a72004-08-10 14:17:33 +00006878/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006879 * xmlSchemaParseAny:
6880 * @ctxt: a schema validation context
6881 * @schema: the schema being built
6882 * @node: a subtree containing XML Schema informations
6883 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006884 * Parsea a XML schema <any> element. A particle and wildcard
6885 * will be created (except if minOccurs==maxOccurs==0, in this case
6886 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 * *WARNING* this interface is highly subject to change
6888 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006889 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006890 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006891static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006892xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6893 xmlNodePtr node)
6894{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006895 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006896 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006897 xmlSchemaWildcardPtr wild;
6898 int min, max;
6899 xmlAttrPtr attr;
6900 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006901
6902 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6903 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006904 /*
6905 * Check for illegal attributes.
6906 */
6907 attr = node->properties;
6908 while (attr != NULL) {
6909 if (attr->ns == NULL) {
6910 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6911 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6912 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6913 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6914 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006915 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006916 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006917 }
6918 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006919 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006920 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006921 }
6922 attr = attr->next;
6923 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006924 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006925 /*
6926 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006927 */
6928 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6929 "(xs:nonNegativeInteger | unbounded)");
6930 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6931 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006932 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6933 /*
6934 * Create & parse the wildcard.
6935 */
6936 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6937 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006938 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006939 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006940 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006941 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006942 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006943 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006944 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006945 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006946 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006947 }
6948 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006949 xmlSchemaPContentErr(ctxt,
6950 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006951 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006952 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006953 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006954 /*
6955 * No component if minOccurs==maxOccurs==0.
6956 */
6957 if ((min == 0) && (max == 0)) {
6958 /* Don't free the wildcard, since it's already on the list. */
6959 return (NULL);
6960 }
6961 /*
6962 * Create the particle.
6963 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00006964 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006965 if (particle == NULL)
6966 return (NULL);
6967 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006968 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006969
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006970 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006971}
6972
6973/**
6974 * xmlSchemaParseNotation:
6975 * @ctxt: a schema validation context
6976 * @schema: the schema being built
6977 * @node: a subtree containing XML Schema informations
6978 *
6979 * parse a XML schema Notation declaration
6980 *
6981 * Returns the new structure or NULL in case of error
6982 */
6983static xmlSchemaNotationPtr
6984xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006985 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006986{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006987 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006988 xmlSchemaNotationPtr ret;
6989 xmlNodePtr child = NULL;
6990
6991 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6992 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006993 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006994 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006995 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6996 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 return (NULL);
6998 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006999 ret = xmlSchemaAddNotation(ctxt, schema, name,
7000 ctxt->targetNamespace, node);
7001 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00007002 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007003 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007004
Daniel Veillard4255d502002-04-16 15:50:10 +00007005 child = node->children;
7006 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007007 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007008 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007009 }
7010 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007011 xmlSchemaPContentErr(ctxt,
7012 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007013 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007014 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007015 }
7016
7017 return (ret);
7018}
7019
7020/**
7021 * xmlSchemaParseAnyAttribute:
7022 * @ctxt: a schema validation context
7023 * @schema: the schema being built
7024 * @node: a subtree containing XML Schema informations
7025 *
7026 * parse a XML schema AnyAttrribute declaration
7027 * *WARNING* this interface is highly subject to change
7028 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007029 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00007030 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007031static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007032xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7033 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007034{
Daniel Veillard3646d642004-06-02 19:19:14 +00007035 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007037 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007038
7039 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7040 return (NULL);
7041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007042 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7043 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 if (ret == NULL) {
7045 return (NULL);
7046 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007047 /*
7048 * Check for illegal attributes.
7049 */
7050 attr = node->properties;
7051 while (attr != NULL) {
7052 if (attr->ns == NULL) {
7053 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7054 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7055 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007056 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007057 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007058 }
7059 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007060 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007061 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007062 }
7063 attr = attr->next;
7064 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007065 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007066 /*
7067 * Parse the namespace list.
7068 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007070 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007071 /*
7072 * And now for the children...
7073 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007074 child = node->children;
7075 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007076 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007077 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007078 }
7079 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007080 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007081 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007082 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007083 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007084 }
7085
7086 return (ret);
7087}
7088
7089
7090/**
7091 * xmlSchemaParseAttribute:
7092 * @ctxt: a schema validation context
7093 * @schema: the schema being built
7094 * @node: a subtree containing XML Schema informations
7095 *
7096 * parse a XML schema Attrribute declaration
7097 * *WARNING* this interface is highly subject to change
7098 *
William M. Bracke7091952004-05-11 15:09:58 +00007099 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007100 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007101static xmlSchemaBasicItemPtr
7102xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7103 xmlSchemaPtr schema,
7104 xmlNodePtr node,
7105 xmlSchemaItemListPtr uses,
7106 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007107{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007108 const xmlChar *attrValue, *name = NULL, *ns = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007109 xmlSchemaAttributeUsePtr use = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007110 xmlNodePtr child = NULL;
7111 xmlAttrPtr attr;
7112 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7113 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7114 int nberrors, hasForm = 0, defValueType = 0;
7115
7116#define WXS_ATTR_DEF_VAL_DEFAULT 1
7117#define WXS_ATTR_DEF_VAL_FIXED 2
7118
7119 /*
7120 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7121 */
7122
7123 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7124 return (NULL);
7125 attr = xmlSchemaGetPropNode(node, "ref");
7126 if (attr != NULL) {
7127 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7128 NULL, attr, &tmpNs, &tmpName) != 0) {
7129 return (NULL);
7130 }
7131 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7132 return(NULL);
7133 isRef = 1;
7134 }
7135 nberrors = pctxt->nberrors;
7136 /*
7137 * Check for illegal attributes.
7138 */
7139 attr = node->properties;
7140 while (attr != NULL) {
7141 if (attr->ns == NULL) {
7142 if (isRef) {
7143 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7144 xmlSchemaPValAttrNodeID(pctxt, attr);
7145 goto attr_next;
7146 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7147 goto attr_next;
7148 }
7149 } else {
7150 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7151 goto attr_next;
7152 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7153 xmlSchemaPValAttrNodeID(pctxt, attr);
7154 goto attr_next;
7155 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7156 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7157 attr, &tmpNs, &tmpName);
7158 goto attr_next;
7159 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7160 /*
7161 * Evaluate the target namespace
7162 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007163 hasForm = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007164 attrValue = xmlSchemaGetNodeContent(pctxt,
7165 (xmlNodePtr) attr);
7166 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7167 ns = pctxt->targetNamespace;
7168 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7169 {
7170 xmlSchemaPSimpleTypeErr(pctxt,
7171 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7172 NULL, (xmlNodePtr) attr,
7173 NULL, "(qualified | unqualified)",
7174 attrValue, NULL, NULL, NULL);
7175 }
7176 goto attr_next;
7177 }
7178 }
7179 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7180
7181 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7182 /* TODO: Maybe we need to normalize the value beforehand. */
7183 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7184 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7185 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7186 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7187 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7188 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7189 else {
7190 xmlSchemaPSimpleTypeErr(pctxt,
7191 XML_SCHEMAP_INVALID_ATTR_USE,
7192 NULL, (xmlNodePtr) attr,
7193 NULL, "(optional | prohibited | required)",
7194 attrValue, NULL, NULL, NULL);
7195 }
7196 goto attr_next;
7197 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7198 /*
7199 * 3.2.3 : 1
7200 * default and fixed must not both be present.
7201 */
7202 if (defValue) {
7203 xmlSchemaPMutualExclAttrErr(pctxt,
7204 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7205 NULL, attr, "default", "fixed");
7206 } else {
7207 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7208 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7209 }
7210 goto attr_next;
7211 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7212 /*
7213 * 3.2.3 : 1
7214 * default and fixed must not both be present.
7215 */
7216 if (defValue) {
7217 xmlSchemaPMutualExclAttrErr(pctxt,
7218 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7219 NULL, attr, "default", "fixed");
7220 } else {
7221 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7222 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7223 }
7224 goto attr_next;
7225 }
7226 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7227 goto attr_next;
7228
7229 xmlSchemaPIllegalAttrErr(pctxt,
7230 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7231
7232attr_next:
7233 attr = attr->next;
Daniel Veillarddee23482008-04-11 12:58:43 +00007234 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007235 /*
7236 * 3.2.3 : 2
7237 * If default and use are both present, use must have
7238 * the actual value optional.
7239 */
7240 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7241 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7242 xmlSchemaPSimpleTypeErr(pctxt,
7243 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7244 NULL, node, NULL,
7245 "(optional | prohibited | required)", NULL,
7246 "The value of the attribute 'use' must be 'optional' "
7247 "if the attribute 'default' is present",
7248 NULL, NULL);
7249 }
7250 /*
7251 * We want correct attributes.
7252 */
7253 if (nberrors != pctxt->nberrors)
7254 return(NULL);
7255 if (! isRef) {
7256 xmlSchemaAttributePtr attrDecl;
7257
7258 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7259 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
Daniel Veillarddee23482008-04-11 12:58:43 +00007260 ns = pctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007261 /*
7262 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7263 * TODO: Move this to the component layer.
7264 */
7265 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7266 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7267 XML_SCHEMAP_NO_XSI,
7268 node, NULL,
7269 "The target namespace must not match '%s'",
7270 xmlSchemaInstanceNs, NULL);
7271 }
7272 attr = xmlSchemaGetPropNode(node, "name");
7273 if (attr == NULL) {
7274 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7275 NULL, node, "name", NULL);
7276 return (NULL);
7277 }
7278 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7279 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7280 return (NULL);
7281 }
7282 /*
7283 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7284 * TODO: Move this to the component layer.
7285 */
7286 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7287 xmlSchemaPSimpleTypeErr(pctxt,
7288 XML_SCHEMAP_NO_XMLNS,
7289 NULL, (xmlNodePtr) attr,
7290 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7291 "The value of the attribute must not match 'xmlns'",
7292 NULL, NULL);
7293 return (NULL);
7294 }
7295 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7296 goto check_children;
7297 /*
7298 * Create the attribute use component.
7299 */
7300 use = xmlSchemaAddAttributeUse(pctxt, node);
7301 if (use == NULL)
7302 return(NULL);
7303 use->occurs = occurs;
7304 /*
7305 * Create the attribute declaration.
7306 */
7307 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7308 if (attrDecl == NULL)
7309 return (NULL);
7310 if (tmpName != NULL) {
7311 attrDecl->typeName = tmpName;
7312 attrDecl->typeNs = tmpNs;
7313 }
7314 use->attrDecl = attrDecl;
7315 /*
7316 * Value constraint.
Daniel Veillarddee23482008-04-11 12:58:43 +00007317 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007318 if (defValue != NULL) {
7319 attrDecl->defValue = defValue;
7320 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7321 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7322 }
7323 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7324 xmlSchemaQNameRefPtr ref;
7325
7326 /*
7327 * Create the attribute use component.
7328 */
7329 use = xmlSchemaAddAttributeUse(pctxt, node);
7330 if (use == NULL)
7331 return(NULL);
7332 /*
7333 * We need to resolve the reference at later stage.
7334 */
7335 WXS_ADD_PENDING(pctxt, use);
7336 use->occurs = occurs;
7337 /*
7338 * Create a QName reference to the attribute declaration.
7339 */
7340 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7341 tmpName, tmpNs);
7342 if (ref == NULL)
7343 return(NULL);
7344 /*
7345 * Assign the reference. This will be substituted for the
7346 * referenced attribute declaration when the QName is resolved.
7347 */
7348 use->attrDecl = WXS_ATTR_CAST ref;
7349 /*
7350 * Value constraint.
7351 */
7352 if (defValue != NULL)
7353 use->defValue = defValue;
7354 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7355 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7356 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007357
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007358check_children:
7359 /*
7360 * And now for the children...
7361 */
7362 child = node->children;
7363 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007364 xmlSchemaAttributeUseProhibPtr prohib;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007365
7366 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007367 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007368 child = child->next;
7369 }
7370 if (child != NULL) {
7371 xmlSchemaPContentErr(pctxt,
7372 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7373 NULL, node, child, NULL,
7374 "(annotation?)");
7375 }
7376 /*
7377 * Check for pointlessness of attribute prohibitions.
7378 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007379 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007380 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7381 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7382 node, NULL,
7383 "Skipping attribute use prohibition, since it is "
7384 "pointless inside an <attributeGroup>",
7385 NULL, NULL, NULL);
7386 return(NULL);
7387 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7388 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7389 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7390 node, NULL,
7391 "Skipping attribute use prohibition, since it is "
7392 "pointless when extending a type",
7393 NULL, NULL, NULL);
7394 return(NULL);
7395 }
7396 if (! isRef) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007397 tmpName = name;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007398 tmpNs = ns;
7399 }
7400 /*
7401 * Check for duplicate attribute prohibitions.
7402 */
7403 if (uses) {
7404 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00007405
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007406 for (i = 0; i < uses->nbItems; i++) {
7407 use = uses->items[i];
7408 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7409 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7410 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7411 {
7412 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007413
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007414 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7415 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7416 node, NULL,
7417 "Skipping duplicate attribute use prohibition '%s'",
7418 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7419 NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007420 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007421 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007422 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007423 }
7424 }
7425 /*
7426 * Create the attribute prohibition helper component.
7427 */
7428 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7429 if (prohib == NULL)
7430 return(NULL);
7431 prohib->node = node;
7432 prohib->name = tmpName;
7433 prohib->targetNamespace = tmpNs;
7434 if (isRef) {
7435 /*
7436 * We need at least to resolve to the attribute declaration.
7437 */
7438 WXS_ADD_PENDING(pctxt, prohib);
7439 }
7440 return(WXS_BASIC_CAST prohib);
Daniel Veillarddee23482008-04-11 12:58:43 +00007441 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007442 if (IS_SCHEMA(child, "annotation")) {
7443 /*
7444 * TODO: Should this go into the attr decl?
7445 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007446 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007447 child = child->next;
7448 }
7449 if (isRef) {
7450 if (child != NULL) {
7451 if (IS_SCHEMA(child, "simpleType"))
7452 /*
7453 * 3.2.3 : 3.2
7454 * If ref is present, then all of <simpleType>,
7455 * form and type must be absent.
7456 */
7457 xmlSchemaPContentErr(pctxt,
7458 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7459 NULL, node, child, NULL,
7460 "(annotation?)");
7461 else
7462 xmlSchemaPContentErr(pctxt,
7463 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, node, child, NULL,
7465 "(annotation?)");
7466 }
7467 } else {
7468 if (IS_SCHEMA(child, "simpleType")) {
7469 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7470 /*
7471 * 3.2.3 : 4
7472 * type and <simpleType> must not both be present.
7473 */
7474 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7475 NULL, node, child,
7476 "The attribute 'type' and the <simpleType> child "
7477 "are mutually exclusive", NULL);
7478 } else
7479 WXS_ATTRUSE_TYPEDEF(use) =
7480 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7481 child = child->next;
7482 }
7483 if (child != NULL)
7484 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7485 NULL, node, child, NULL,
7486 "(annotation?, simpleType?)");
7487 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007488 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007489 return (WXS_BASIC_CAST use);
7490}
7491
7492
7493static xmlSchemaAttributePtr
7494xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7495 xmlSchemaPtr schema,
7496 xmlNodePtr node)
7497{
7498 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007499 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007500 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007501 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007502
7503 /*
7504 * Note that the w3c spec assumes the schema to be validated with schema
7505 * for schemas beforehand.
7506 *
7507 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007508 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007509 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00007510 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007511 /*
7512 * 3.2.3 : 3.1
7513 * One of ref or name must be present, but not both
7514 */
7515 attr = xmlSchemaGetPropNode(node, "name");
7516 if (attr == NULL) {
7517 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7518 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 return (NULL);
7520 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007521 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7522 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7523 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007525 /*
7526 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7527 * TODO: Move this to the component layer.
7528 */
7529 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7530 xmlSchemaPSimpleTypeErr(pctxt,
7531 XML_SCHEMAP_NO_XMLNS,
7532 NULL, (xmlNodePtr) attr,
7533 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7534 "The value of the attribute must not match 'xmlns'",
7535 NULL, NULL);
7536 return (NULL);
7537 }
7538 /*
7539 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7540 * TODO: Move this to the component layer.
7541 * Or better leave it here and add it to the component layer
7542 * if we have a schema construction API.
7543 */
7544 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7545 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7546 XML_SCHEMAP_NO_XSI, node, NULL,
7547 "The target namespace must not match '%s'",
7548 xmlSchemaInstanceNs, NULL);
7549 }
7550
7551 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7552 pctxt->targetNamespace, node, 1);
7553 if (ret == NULL)
7554 return (NULL);
7555 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007556
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007557 /*
7558 * Check for illegal attributes.
7559 */
7560 attr = node->properties;
7561 while (attr != NULL) {
7562 if (attr->ns == NULL) {
7563 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7564 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7565 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7566 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7567 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7568 {
7569 xmlSchemaPIllegalAttrErr(pctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00007570 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007571 }
7572 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7573 xmlSchemaPIllegalAttrErr(pctxt,
7574 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7575 }
7576 attr = attr->next;
7577 }
7578 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7579 node, "type", &ret->typeNs, &ret->typeName);
Daniel Veillarddee23482008-04-11 12:58:43 +00007580
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007581 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007582 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007584 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007585 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007586 if (ret->defValue != NULL)
7587 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 * Attribute "default".
7590 */
7591 attr = xmlSchemaGetPropNode(node, "default");
7592 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007593 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007594 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007595 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007596 */
7597 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007598 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7599 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007600 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007601 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007602 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007603 /*
7604 * And now for the children...
7605 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007606 child = node->children;
7607 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007608 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007609 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007610 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007611 if (IS_SCHEMA(child, "simpleType")) {
7612 if (ret->typeName != NULL) {
7613 /*
7614 * 3.2.3 : 4
7615 * type and <simpleType> must not both be present.
7616 */
7617 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7618 NULL, node, child,
7619 "The attribute 'type' and the <simpleType> child "
7620 "are mutually exclusive", NULL);
7621 } else
7622 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7623 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007624 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007625 if (child != NULL)
7626 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7627 NULL, node, child, NULL,
7628 "(annotation?, simpleType?)");
7629
Daniel Veillard4255d502002-04-16 15:50:10 +00007630 return (ret);
7631}
7632
7633/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007634 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007635 * @ctxt: a schema validation context
7636 * @schema: the schema being built
7637 * @node: a subtree containing XML Schema informations
7638 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007639 * Parse an attribute group definition reference.
7640 * Note that a reference to an attribute group does not
7641 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007642 * *WARNING* this interface is highly subject to change
7643 *
7644 * Returns the attribute group or NULL in case of error.
7645 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007646static xmlSchemaQNameRefPtr
7647xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7648 xmlSchemaPtr schema,
7649 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007650{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007651 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007652 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007653 xmlAttrPtr attr;
7654 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007655
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007656 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007657 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007658
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007659 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007660 if (attr == NULL) {
7661 xmlSchemaPMissingAttrErr(pctxt,
7662 XML_SCHEMAP_S4S_ATTR_MISSING,
7663 NULL, node, "ref", NULL);
7664 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007665 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007666 xmlSchemaPValAttrNodeQName(pctxt, schema,
7667 NULL, attr, &refNs, &ref);
7668 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7669 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007670
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007671 /*
7672 * Check for illegal attributes.
7673 */
7674 attr = node->properties;
7675 while (attr != NULL) {
7676 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007677 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007678 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007679 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007680 xmlSchemaPIllegalAttrErr(pctxt,
7681 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007682 }
7683 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007684 xmlSchemaPIllegalAttrErr(pctxt,
7685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007686 }
7687 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007688 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007689 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007690 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7691
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007692 /*
7693 * And now for the children...
7694 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007695 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007696 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007697 /*
7698 * TODO: We do not have a place to store the annotation, do we?
7699 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007700 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007701 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007702 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007703 if (child != NULL) {
7704 xmlSchemaPContentErr(pctxt,
7705 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7706 NULL, node, child, NULL,
7707 "(annotation?)");
7708 }
7709
7710 /*
7711 * Handle attribute group redefinitions.
7712 */
7713 if (pctxt->isRedefine && pctxt->redef &&
7714 (pctxt->redef->item->type ==
7715 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7716 (ref == pctxt->redef->refName) &&
7717 (refNs == pctxt->redef->refTargetNs))
7718 {
7719 /*
7720 * SPEC src-redefine:
7721 * (7.1) "If it has an <attributeGroup> among its contents
Jan Pokorný761c9e92013-11-29 23:26:27 +01007722 * the `actual value` of whose ref [attribute] is the same
7723 * as the `actual value` of its own name attribute plus
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007724 * target namespace, then it must have exactly one such group."
7725 */
7726 if (pctxt->redefCounter != 0) {
7727 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007728
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007729 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7730 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7731 "The redefining attribute group definition "
7732 "'%s' must not contain more than one "
7733 "reference to the redefined definition",
7734 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7735 FREE_AND_NULL(str);
7736 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007737 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007738 pctxt->redefCounter++;
7739 /*
7740 * URGENT TODO: How to ensure that the reference will not be
7741 * handled by the normal component resolution mechanism?
7742 */
7743 ret = xmlSchemaNewQNameRef(pctxt,
7744 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7745 if (ret == NULL)
7746 return(NULL);
7747 ret->node = node;
7748 pctxt->redef->reference = WXS_BASIC_CAST ret;
7749 } else {
7750 /*
7751 * Create a QName-reference helper component. We will substitute this
7752 * component for the attribute uses of the referenced attribute group
7753 * definition.
7754 */
7755 ret = xmlSchemaNewQNameRef(pctxt,
7756 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7757 if (ret == NULL)
7758 return(NULL);
7759 ret->node = node;
7760 /* Add to pending items, to be able to resolve the reference. */
7761 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00007762 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007763 return (ret);
7764}
7765
7766/**
7767 * xmlSchemaParseAttributeGroupDefinition:
7768 * @pctxt: a schema validation context
7769 * @schema: the schema being built
7770 * @node: a subtree containing XML Schema informations
7771 *
7772 * parse a XML schema Attribute Group declaration
7773 * *WARNING* this interface is highly subject to change
7774 *
7775 * Returns the attribute group definition or NULL in case of error.
7776 */
7777static xmlSchemaAttributeGroupPtr
7778xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7779 xmlSchemaPtr schema,
7780 xmlNodePtr node)
7781{
7782 const xmlChar *name;
7783 xmlSchemaAttributeGroupPtr ret;
7784 xmlNodePtr child = NULL;
7785 xmlAttrPtr attr;
7786 int hasRefs = 0;
7787
7788 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7789 return (NULL);
7790
7791 attr = xmlSchemaGetPropNode(node, "name");
7792 if (attr == NULL) {
7793 xmlSchemaPMissingAttrErr(pctxt,
7794 XML_SCHEMAP_S4S_ATTR_MISSING,
7795 NULL, node, "name", NULL);
7796 return (NULL);
7797 }
7798 /*
7799 * The name is crucial, exit if invalid.
7800 */
7801 if (xmlSchemaPValAttrNode(pctxt,
7802 NULL, attr,
7803 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7804 return (NULL);
7805 }
7806 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7807 name, pctxt->targetNamespace, node);
7808 if (ret == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00007809 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007810 /*
7811 * Check for illegal attributes.
7812 */
7813 attr = node->properties;
7814 while (attr != NULL) {
7815 if (attr->ns == NULL) {
7816 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7817 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7818 {
7819 xmlSchemaPIllegalAttrErr(pctxt,
7820 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7821 }
7822 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7823 xmlSchemaPIllegalAttrErr(pctxt,
7824 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7825 }
7826 attr = attr->next;
7827 }
7828 /* Attribute ID */
7829 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7830 /*
7831 * And now for the children...
7832 */
7833 child = node->children;
7834 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007835 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007836 child = child->next;
7837 }
7838 /*
7839 * Parse contained attribute decls/refs.
7840 */
7841 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7842 (xmlSchemaItemListPtr *) &(ret->attrUses),
7843 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7844 return(NULL);
7845 if (hasRefs)
7846 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7847 /*
7848 * Parse the attribute wildcard.
7849 */
7850 if (IS_SCHEMA(child, "anyAttribute")) {
7851 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7852 schema, child);
7853 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007854 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007855 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007856 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007857 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007858 NULL, node, child, NULL,
7859 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007860 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007861 return (ret);
7862}
7863
7864/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007865 * xmlSchemaPValAttrFormDefault:
7866 * @value: the value
7867 * @flags: the flags to be modified
7868 * @flagQualified: the specific flag for "qualified"
7869 *
7870 * Returns 0 if the value is valid, 1 otherwise.
7871 */
7872static int
7873xmlSchemaPValAttrFormDefault(const xmlChar *value,
7874 int *flags,
7875 int flagQualified)
7876{
7877 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7878 if ((*flags & flagQualified) == 0)
7879 *flags |= flagQualified;
7880 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007881 return (1);
7882
William M. Brack2f2a6632004-08-20 23:09:47 +00007883 return (0);
7884}
7885
7886/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007887 * xmlSchemaPValAttrBlockFinal:
7888 * @value: the value
7889 * @flags: the flags to be modified
7890 * @flagAll: the specific flag for "#all"
7891 * @flagExtension: the specific flag for "extension"
7892 * @flagRestriction: the specific flag for "restriction"
7893 * @flagSubstitution: the specific flag for "substitution"
7894 * @flagList: the specific flag for "list"
7895 * @flagUnion: the specific flag for "union"
7896 *
7897 * Validates the value of the attribute "final" and "block". The value
7898 * is converted into the specified flag values and returned in @flags.
7899 *
7900 * Returns 0 if the value is valid, 1 otherwise.
7901 */
7902
7903static int
7904xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007906 int flagAll,
7907 int flagExtension,
7908 int flagRestriction,
7909 int flagSubstitution,
7910 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007911 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007912{
7913 int ret = 0;
7914
7915 /*
7916 * TODO: This does not check for dublicate entries.
7917 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007918 if ((flags == NULL) || (value == NULL))
7919 return (-1);
7920 if (value[0] == 0)
7921 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007922 if (xmlStrEqual(value, BAD_CAST "#all")) {
7923 if (flagAll != -1)
7924 *flags |= flagAll;
7925 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007926 if (flagExtension != -1)
7927 *flags |= flagExtension;
7928 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007929 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007930 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007931 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007933 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007934 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007935 *flags |= flagUnion;
7936 }
7937 } else {
7938 const xmlChar *end, *cur = value;
7939 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007940
Daniel Veillardc0826a72004-08-10 14:17:33 +00007941 do {
7942 while (IS_BLANK_CH(*cur))
7943 cur++;
7944 end = cur;
7945 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7946 end++;
7947 if (end == cur)
7948 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007950 if (xmlStrEqual(item, BAD_CAST "extension")) {
7951 if (flagExtension != -1) {
7952 if ((*flags & flagExtension) == 0)
7953 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007954 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007955 ret = 1;
7956 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7957 if (flagRestriction != -1) {
7958 if ((*flags & flagRestriction) == 0)
7959 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007960 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007961 ret = 1;
7962 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7963 if (flagSubstitution != -1) {
7964 if ((*flags & flagSubstitution) == 0)
7965 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007966 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007967 ret = 1;
7968 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7969 if (flagList != -1) {
7970 if ((*flags & flagList) == 0)
7971 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007973 ret = 1;
7974 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7975 if (flagUnion != -1) {
7976 if ((*flags & flagUnion) == 0)
7977 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007978 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007979 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007980 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007981 ret = 1;
7982 if (item != NULL)
7983 xmlFree(item);
7984 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007985 } while ((ret == 0) && (*cur != 0));
7986 }
7987
Daniel Veillardc0826a72004-08-10 14:17:33 +00007988 return (ret);
7989}
7990
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007991static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007992xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007993 xmlSchemaIDCPtr idc,
7994 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007995 xmlAttrPtr attr,
7996 int isField)
7997{
7998 xmlNodePtr node;
7999
8000 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008001 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008002 * Schema Component Constraint: Selector Value OK
8003 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008004 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008005 * in [XPath].
8006 */
8007 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008009 XML_SCHEMAP_INTERNAL,
8010 "Internal error: xmlSchemaCheckCSelectorXPath, "
8011 "the selector is not specified.\n", NULL, NULL);
8012 return (-1);
8013 }
8014 if (attr == NULL)
8015 node = idc->node;
8016 else
8017 node = (xmlNodePtr) attr;
8018 if (selector->xpath == NULL) {
8019 xmlSchemaPCustomErr(ctxt,
8020 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008021 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008022 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008023 "The XPath expression of the selector is not valid", NULL);
8024 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8025 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008026 const xmlChar **nsArray = NULL;
8027 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008028 /*
8029 * Compile the XPath expression.
8030 */
8031 /*
8032 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008033 * TODO: Call xmlPatterncompile with different options for selector/
8034 * field.
8035 */
Daniel Veillard14b56432006-03-09 18:41:40 +00008036 if (attr == NULL)
Daniel Veillardaac7c682006-03-10 13:40:16 +00008037 nsList = NULL;
Daniel Veillard14b56432006-03-09 18:41:40 +00008038 else
8039 nsList = xmlGetNsList(attr->doc, attr->parent);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008040 /*
8041 * Build an array of prefixes and namespaces.
8042 */
8043 if (nsList != NULL) {
8044 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008045
8046 for (i = 0; nsList[i] != NULL; i++)
8047 count++;
8048
8049 nsArray = (const xmlChar **) xmlMalloc(
8050 (count * 2 + 1) * sizeof(const xmlChar *));
8051 if (nsArray == NULL) {
8052 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8053 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008054 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008055 return (-1);
8056 }
8057 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008058 nsArray[2 * i] = nsList[i]->href;
8059 nsArray[2 * i + 1] = nsList[i]->prefix;
8060 }
8061 nsArray[count * 2] = NULL;
8062 xmlFree(nsList);
8063 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008064 /*
8065 * TODO: Differentiate between "selector" and "field".
8066 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008067 if (isField)
8068 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008069 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008070 else
8071 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008072 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008073 if (nsArray != NULL)
8074 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008075
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008076 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008077 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008078 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008079 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008080 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008081 "The XPath expression '%s' could not be "
8082 "compiled", selector->xpath);
8083 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008084 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008085 }
8086 return (0);
8087}
8088
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008089#define ADD_ANNOTATION(annot) \
8090 xmlSchemaAnnotPtr cur = item->annot; \
8091 if (item->annot == NULL) { \
8092 item->annot = annot; \
8093 return (annot); \
8094 } \
8095 cur = item->annot; \
8096 if (cur->next != NULL) { \
8097 cur = cur->next; \
8098 } \
8099 cur->next = annot;
8100
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008101/**
8102 * xmlSchemaAssignAnnotation:
8103 * @item: the schema component
8104 * @annot: the annotation
8105 *
8106 * Adds the annotation to the given schema component.
8107 *
8108 * Returns the given annotaion.
8109 */
8110static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008111xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8112 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008113{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008114 if ((annItem == NULL) || (annot == NULL))
8115 return (NULL);
8116 switch (annItem->type) {
8117 case XML_SCHEMA_TYPE_ELEMENT: {
8118 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8119 ADD_ANNOTATION(annot)
8120 }
8121 break;
8122 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8123 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8124 ADD_ANNOTATION(annot)
8125 }
8126 break;
8127 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8128 case XML_SCHEMA_TYPE_ANY: {
8129 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8130 ADD_ANNOTATION(annot)
8131 }
8132 break;
8133 case XML_SCHEMA_TYPE_PARTICLE:
8134 case XML_SCHEMA_TYPE_IDC_KEY:
8135 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008136 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008137 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8138 ADD_ANNOTATION(annot)
8139 }
8140 break;
8141 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8142 xmlSchemaAttributeGroupPtr item =
8143 (xmlSchemaAttributeGroupPtr) annItem;
8144 ADD_ANNOTATION(annot)
8145 }
8146 break;
8147 case XML_SCHEMA_TYPE_NOTATION: {
8148 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8149 ADD_ANNOTATION(annot)
8150 }
8151 break;
8152 case XML_SCHEMA_FACET_MININCLUSIVE:
8153 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8154 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8155 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8156 case XML_SCHEMA_FACET_TOTALDIGITS:
8157 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8158 case XML_SCHEMA_FACET_PATTERN:
8159 case XML_SCHEMA_FACET_ENUMERATION:
8160 case XML_SCHEMA_FACET_WHITESPACE:
8161 case XML_SCHEMA_FACET_LENGTH:
8162 case XML_SCHEMA_FACET_MAXLENGTH:
8163 case XML_SCHEMA_FACET_MINLENGTH: {
8164 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8165 ADD_ANNOTATION(annot)
8166 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008167 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008168 case XML_SCHEMA_TYPE_SIMPLE:
8169 case XML_SCHEMA_TYPE_COMPLEX: {
8170 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8171 ADD_ANNOTATION(annot)
8172 }
8173 break;
8174 case XML_SCHEMA_TYPE_GROUP: {
8175 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8176 ADD_ANNOTATION(annot)
8177 }
8178 break;
8179 case XML_SCHEMA_TYPE_SEQUENCE:
8180 case XML_SCHEMA_TYPE_CHOICE:
8181 case XML_SCHEMA_TYPE_ALL: {
8182 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8183 ADD_ANNOTATION(annot)
8184 }
8185 break;
8186 default:
8187 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008189 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008190 "Internal error: xmlSchemaAddAnnotation, "
8191 "The item is not a annotated schema component", NULL);
8192 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008193 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008194 return (annot);
8195}
8196
8197/**
8198 * xmlSchemaParseIDCSelectorAndField:
8199 * @ctxt: a schema validation context
8200 * @schema: the schema being built
8201 * @node: a subtree containing XML Schema informations
8202 *
8203 * Parses a XML Schema identity-contraint definition's
8204 * <selector> and <field> elements.
8205 *
8206 * Returns the parsed identity-constraint definition.
8207 */
8208static xmlSchemaIDCSelectPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00008209xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008210 xmlSchemaIDCPtr idc,
8211 xmlNodePtr node,
8212 int isField)
8213{
8214 xmlSchemaIDCSelectPtr item;
8215 xmlNodePtr child = NULL;
8216 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008217
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008218 /*
8219 * Check for illegal attributes.
8220 */
8221 attr = node->properties;
8222 while (attr != NULL) {
8223 if (attr->ns == NULL) {
8224 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8225 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008228 }
8229 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008230 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008231 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008232 }
8233 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008234 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008235 /*
8236 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008238 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8239 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008240 xmlSchemaPErrMemory(ctxt,
8241 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008242 NULL);
8243 return (NULL);
8244 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008246 /*
8247 * Attribute "xpath" (mandatory).
8248 */
8249 attr = xmlSchemaGetPropNode(node, "xpath");
8250 if (attr == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08008251 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252 XML_SCHEMAP_S4S_ATTR_MISSING,
8253 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008254 "name", NULL);
8255 } else {
8256 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8257 /*
8258 * URGENT TODO: "field"s have an other syntax than "selector"s.
8259 */
8260
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008261 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8262 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008263 xmlSchemaPErr(ctxt,
8264 (xmlNodePtr) attr,
8265 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008266 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008267 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008268 NULL, NULL);
8269 }
8270
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008271 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008272 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008273 /*
8274 * And now for the children...
8275 */
8276 child = node->children;
8277 if (IS_SCHEMA(child, "annotation")) {
8278 /*
8279 * Add the annotation to the parent IDC.
8280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008281 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008282 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008283 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008284 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008285 if (child != NULL) {
8286 xmlSchemaPContentErr(ctxt,
8287 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008288 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008289 NULL, "(annotation?)");
8290 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008292 return (item);
8293}
8294
8295/**
8296 * xmlSchemaParseIDC:
8297 * @ctxt: a schema validation context
8298 * @schema: the schema being built
8299 * @node: a subtree containing XML Schema informations
8300 *
8301 * Parses a XML Schema identity-contraint definition.
8302 *
8303 * Returns the parsed identity-constraint definition.
8304 */
8305static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008306xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008307 xmlSchemaPtr schema,
8308 xmlNodePtr node,
8309 xmlSchemaTypeType idcCategory,
8310 const xmlChar *targetNamespace)
8311{
8312 xmlSchemaIDCPtr item = NULL;
8313 xmlNodePtr child = NULL;
8314 xmlAttrPtr attr;
8315 const xmlChar *name = NULL;
8316 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008318 /*
8319 * Check for illegal attributes.
8320 */
8321 attr = node->properties;
8322 while (attr != NULL) {
8323 if (attr->ns == NULL) {
8324 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8325 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8326 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8327 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008328 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008329 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008330 }
8331 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008332 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008333 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008334 }
8335 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008336 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008337 /*
8338 * Attribute "name" (mandatory).
8339 */
8340 attr = xmlSchemaGetPropNode(node, "name");
8341 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008342 xmlSchemaPMissingAttrErr(ctxt,
8343 XML_SCHEMAP_S4S_ATTR_MISSING,
8344 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008345 "name", NULL);
8346 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008348 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008349 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8350 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008352 /* Create the component. */
8353 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8354 idcCategory, node);
8355 if (item == NULL)
8356 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008357
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008358 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008359 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8360 /*
8361 * Attribute "refer" (mandatory).
8362 */
8363 attr = xmlSchemaGetPropNode(node, "refer");
8364 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008365 xmlSchemaPMissingAttrErr(ctxt,
8366 XML_SCHEMAP_S4S_ATTR_MISSING,
8367 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008368 "refer", NULL);
8369 } else {
8370 /*
8371 * Create a reference item.
8372 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008373 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374 NULL, NULL);
8375 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008376 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008377 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008378 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008379 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008380 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008381 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008382 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008383 }
8384 }
8385 /*
8386 * And now for the children...
8387 */
8388 child = node->children;
8389 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008390 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008391 child = child->next;
8392 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008393 if (child == NULL) {
8394 xmlSchemaPContentErr(ctxt,
8395 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008396 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008397 "A child element is missing",
8398 "(annotation?, (selector, field+))");
8399 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008400 /*
8401 * Child element <selector>.
8402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008403 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008404 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008405 item, child, 0);
8406 child = child->next;
8407 /*
8408 * Child elements <field>.
8409 */
8410 if (IS_SCHEMA(child, "field")) {
8411 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008412 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008413 item, child, 1);
8414 if (field != NULL) {
8415 field->index = item->nbFields;
8416 item->nbFields++;
8417 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008418 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008419 else
8420 item->fields = field;
8421 lastField = field;
8422 }
8423 child = child->next;
8424 } while (IS_SCHEMA(child, "field"));
8425 } else {
8426 xmlSchemaPContentErr(ctxt,
8427 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008428 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008429 NULL, "(annotation?, (selector, field+))");
8430 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008431 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008432 if (child != NULL) {
8433 xmlSchemaPContentErr(ctxt,
8434 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008435 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008436 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008437 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008438
8439 return (item);
8440}
8441
Daniel Veillardc0826a72004-08-10 14:17:33 +00008442/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008443 * xmlSchemaParseElement:
8444 * @ctxt: a schema validation context
8445 * @schema: the schema being built
8446 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008447 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008448 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008449 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008450 * *WARNING* this interface is highly subject to change
8451 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008452 * Returns the element declaration or a particle; NULL in case
8453 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008454 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008455static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008456xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008457 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008458{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008459 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008460 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008461 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008462 xmlNodePtr child = NULL;
8463 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 int min, max, isRef = 0;
8465 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008466
8467 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8468 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008469
Daniel Veillard4255d502002-04-16 15:50:10 +00008470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008471 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008472
8473 if (isElemRef != NULL)
8474 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008475 /*
8476 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008477 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008478 * robust.
8479 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008480 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008482 if ((topLevel) || (attr == NULL)) {
8483 if (nameAttr == NULL) {
8484 xmlSchemaPMissingAttrErr(ctxt,
8485 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008486 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008487 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008488 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008489 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008490 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008491
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008492 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008493 child = node->children;
8494 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008495 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008496 child = child->next;
8497 }
8498 /*
8499 * Skip particle part if a global declaration.
8500 */
8501 if (topLevel)
8502 goto declaration_part;
8503 /*
8504 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008505 */
8506 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8507 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8508 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00008509 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008510 if (particle == NULL)
8511 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008512
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008513 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8514
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008515 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008516 const xmlChar *refNs = NULL, *ref = NULL;
8517 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008518 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008520 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008521 if (isElemRef != NULL)
8522 *isElemRef = 1;
8523
Daniel Veillardc0826a72004-08-10 14:17:33 +00008524 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008525 NULL, attr, &refNs, &ref);
8526 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008527 /*
8528 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008529 */
8530 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008531 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008532 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008533 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008534 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008535 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008536 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008537 attr = node->properties;
8538 while (attr != NULL) {
8539 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008540 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8541 xmlStrEqual(attr->name, BAD_CAST "name") ||
8542 xmlStrEqual(attr->name, BAD_CAST "id") ||
8543 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8544 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8545 {
8546 attr = attr->next;
8547 continue;
8548 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008549 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008550 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008551 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008552 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008553 "Only the attributes 'minOccurs', 'maxOccurs' and "
8554 "'id' are allowed in addition to 'ref'");
8555 break;
8556 }
8557 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8558 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008560 }
8561 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008562 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008563 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008564 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008565 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008566 if (child != NULL) {
8567 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008568 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008569 }
8570 if ((min == 0) && (max == 0))
8571 goto return_null;
8572 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008573 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008574 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008575 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008576 ref, refNs);
8577 if (refer == NULL)
8578 goto return_null;
8579 particle->children = (xmlSchemaTreeItemPtr) refer;
8580 particle->annot = annot;
8581 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008582 * Add the particle to pending components, since the reference
8583 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008584 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008585 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008586 return ((xmlSchemaBasicItemPtr) particle);
8587 }
8588 /*
8589 * The declaration part ===============================================
8590 */
8591declaration_part:
8592 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008593 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008594 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8595
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008596 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008597 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008598 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008600 * Evaluate the target namespace.
8601 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008602 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008603 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008604 } else {
8605 attr = xmlSchemaGetPropNode(node, "form");
8606 if (attr != NULL) {
8607 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8608 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008609 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008610 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611 xmlSchemaPSimpleTypeErr(ctxt,
8612 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8613 NULL, (xmlNodePtr) attr,
8614 NULL, "(qualified | unqualified)",
8615 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008616 }
8617 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008618 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008619 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008620 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008622 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008624 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008625 * Check for illegal attributes.
8626 */
William M. Bracke7091952004-05-11 15:09:58 +00008627 attr = node->properties;
8628 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008629 if (attr->ns == NULL) {
8630 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8631 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008632 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008633 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008634 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008635 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8637 {
8638 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008639 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008640 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008642 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008643 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008644 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008646 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8647 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008648 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8649
8650 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008651 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008652 }
8653 }
8654 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008655
Daniel Veillardc0826a72004-08-10 14:17:33 +00008656 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008658 }
8659 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008660 }
William M. Bracke7091952004-05-11 15:09:58 +00008661 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008662 * Extract/validate attributes.
8663 */
8664 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008665 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008666 * Process top attributes of global element declarations here.
8667 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008668 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8669 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008670 xmlSchemaPValAttrQName(ctxt, schema,
8671 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008672 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008673 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008674 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008675 /*
8676 * Attribute "final".
8677 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008678 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008679 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008680 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8681 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8682 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8683 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008684 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008685 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8686 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008687 -1,
8688 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8689 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008690 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008692 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008693 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008694 attrValue, NULL, NULL, NULL);
8695 }
8696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008697 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008698 /*
8699 * Attribute "block".
8700 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008701 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008702 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008703 /*
8704 * Apply default "block" values.
8705 */
8706 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8707 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8708 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8709 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8710 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8711 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008712 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008713 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8714 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008715 -1,
8716 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008717 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008718 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8719 xmlSchemaPSimpleTypeErr(ctxt,
8720 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008721 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008722 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008723 "restriction | substitution))", attrValue,
8724 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008725 }
8726 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008727 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008728 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008729
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008730 attr = xmlSchemaGetPropNode(node, "type");
8731 if (attr != NULL) {
8732 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008733 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008734 &(decl->namedTypeNs), &(decl->namedType));
8735 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008736 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008737 }
8738 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8739 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008740 if (attr != NULL) {
8741 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008742 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008743 /*
8744 * 3.3.3 : 1
8745 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008746 */
8747 xmlSchemaPMutualExclAttrErr(ctxt,
8748 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008749 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008750 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008751 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8752 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008753 }
William M. Bracke7091952004-05-11 15:09:58 +00008754 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008755 /*
8756 * And now for the children...
8757 */
William M. Bracke7091952004-05-11 15:09:58 +00008758 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759 /*
8760 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008761 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008762 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008763 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008764 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008765 xmlSchemaPContentErr(ctxt,
8766 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008767 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008768 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008769 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008770 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008771 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008772 child = child->next;
8773 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008774 /*
8775 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008776 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008777 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008778 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008779 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008780 xmlSchemaPContentErr(ctxt,
8781 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008782 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008783 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008784 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008785 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008786 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008787 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008788 }
William M. Bracke7091952004-05-11 15:09:58 +00008789 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008790 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008791 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008792 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008793 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008794 } else if (IS_SCHEMA(child, "key")) {
8795 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008796 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008797 } else if (IS_SCHEMA(child, "keyref")) {
8798 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008799 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008800 }
8801 if (lastIDC != NULL)
8802 lastIDC->next = curIDC;
8803 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008804 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008805 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008806 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008807 }
8808 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008809 xmlSchemaPContentErr(ctxt,
8810 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008811 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008812 NULL, "(annotation?, ((simpleType | complexType)?, "
8813 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008814 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008815 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008816 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008817 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008818 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008819 * different layer.
8820 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008821 FREE_AND_NULL(des)
8822 if (topLevel)
8823 return ((xmlSchemaBasicItemPtr) decl);
8824 else {
8825 particle->children = (xmlSchemaTreeItemPtr) decl;
8826 return ((xmlSchemaBasicItemPtr) particle);
8827 }
8828
8829return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008830 FREE_AND_NULL(des);
8831 if (annot != NULL) {
8832 if (particle != NULL)
8833 particle->annot = NULL;
8834 if (decl != NULL)
8835 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008836 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008837 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008838 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008839}
8840
8841/**
8842 * xmlSchemaParseUnion:
8843 * @ctxt: a schema validation context
8844 * @schema: the schema being built
8845 * @node: a subtree containing XML Schema informations
8846 *
8847 * parse a XML schema Union definition
8848 * *WARNING* this interface is highly subject to change
8849 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008850 * Returns -1 in case of internal error, 0 in case of success and a positive
8851 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008852 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008853static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008854xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008855 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008856{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008857 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008858 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008859 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008860 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008861
8862 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008863 return (-1);
8864 /* Not a component, don't create it. */
8865 type = ctxt->ctxtType;
8866 /*
8867 * Mark the simple type as being of variety "union".
8868 */
8869 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008870 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008871 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01008872 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008873 */
8874 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008875 /*
8876 * Check for illegal attributes.
8877 */
8878 attr = node->properties;
8879 while (attr != NULL) {
8880 if (attr->ns == NULL) {
8881 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8882 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008885 }
8886 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008888 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008889 }
8890 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008891 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008892 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008893 /*
8894 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008895 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008897 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008898 if (attr != NULL) {
8899 const xmlChar *end;
8900 xmlChar *tmp;
8901 const xmlChar *localName, *nsName;
8902 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8903 xmlSchemaQNameRefPtr ref;
8904
8905 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008906 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008907 do {
8908 while (IS_BLANK_CH(*cur))
8909 cur++;
8910 end = cur;
8911 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8912 end++;
8913 if (end == cur)
8914 break;
8915 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008916 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008917 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008918 /*
8919 * Create the member type link.
8920 */
8921 link = (xmlSchemaTypeLinkPtr)
8922 xmlMalloc(sizeof(xmlSchemaTypeLink));
8923 if (link == NULL) {
8924 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8925 "allocating a type link", NULL);
8926 return (-1);
8927 }
8928 link->type = NULL;
8929 link->next = NULL;
8930 if (lastLink == NULL)
8931 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008933 lastLink->next = link;
8934 lastLink = link;
8935 /*
8936 * Create a reference item.
8937 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008938 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008939 localName, nsName);
8940 if (ref == NULL) {
8941 FREE_AND_NULL(tmp)
8942 return (-1);
8943 }
8944 /*
8945 * Assign the reference to the link, it will be resolved
8946 * later during fixup of the union simple type.
8947 */
8948 link->type = (xmlSchemaTypePtr) ref;
8949 }
8950 FREE_AND_NULL(tmp)
8951 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008952 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008953
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008954 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008955 /*
8956 * And now for the children...
8957 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008958 child = node->children;
8959 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008960 /*
8961 * Add the annotation to the simple type ancestor.
8962 */
8963 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008964 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008965 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008966 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008967 if (IS_SCHEMA(child, "simpleType")) {
8968 xmlSchemaTypePtr subtype, last = NULL;
8969
8970 /*
8971 * Anchor the member types in the "subtypes" field of the
8972 * simple type.
8973 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008975 subtype = (xmlSchemaTypePtr)
8976 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8977 if (subtype != NULL) {
8978 if (last == NULL) {
8979 type->subtypes = subtype;
8980 last = subtype;
8981 } else {
8982 last->next = subtype;
8983 last = subtype;
8984 }
8985 last->next = NULL;
8986 }
8987 child = child->next;
8988 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008989 }
8990 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008991 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008993 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008995 if ((attr == NULL) && (type->subtypes == NULL)) {
8996 /*
8997 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008998 * Either the memberTypes [attribute] of the <union> element must
8999 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009000 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009001 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009002 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009003 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009004 "Either the attribute 'memberTypes' or "
9005 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009006 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009007 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009008}
9009
9010/**
9011 * xmlSchemaParseList:
9012 * @ctxt: a schema validation context
9013 * @schema: the schema being built
9014 * @node: a subtree containing XML Schema informations
9015 *
9016 * parse a XML schema List definition
9017 * *WARNING* this interface is highly subject to change
9018 *
William M. Bracke7091952004-05-11 15:09:58 +00009019 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009020 * 1 in case of success.
9021 */
9022static xmlSchemaTypePtr
9023xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009024 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009025{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009026 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009027 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009028 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009029
9030 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9031 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009032 /* Not a component, don't create it. */
9033 type = ctxt->ctxtType;
9034 /*
9035 * Mark the type as being of variety "list".
9036 */
9037 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009039 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009040 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009041 */
9042 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00009043 /*
9044 * Check for illegal attributes.
9045 */
9046 attr = node->properties;
9047 while (attr != NULL) {
9048 if (attr->ns == NULL) {
9049 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9050 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009052 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009053 }
9054 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009056 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009057 }
9058 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009060
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009061 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009062
William M. Brack2f2a6632004-08-20 23:09:47 +00009063 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009064 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9065 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009066 *
9067 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9068 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009069 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009070 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9071 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009072 /*
9073 * And now for the children...
9074 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009075 child = node->children;
9076 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009077 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009078 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009079 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009080 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009081 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009082 /*
9083 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009084 * Either the itemType [attribute] or the <simpleType> [child] of
9085 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009086 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009087 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009088 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009089 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009090 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009091 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009092 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009093 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009094 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009095 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009096 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009097 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009098 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009099 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009100 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009101 "Either the attribute 'itemType' or the <simpleType> child "
9102 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009103 }
9104 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009105 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009106 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009107 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009108 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009109 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009110 (type->subtypes == NULL) &&
9111 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009113 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009114 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009115 "Either the attribute 'itemType' or the <simpleType> child "
9116 "must be present", NULL);
9117 }
9118 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009119}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009120
Daniel Veillard4255d502002-04-16 15:50:10 +00009121/**
9122 * xmlSchemaParseSimpleType:
9123 * @ctxt: a schema validation context
9124 * @schema: the schema being built
9125 * @node: a subtree containing XML Schema informations
9126 *
9127 * parse a XML schema Simple Type definition
9128 * *WARNING* this interface is highly subject to change
9129 *
William M. Bracke7091952004-05-11 15:09:58 +00009130 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009131 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009132 */
9133static xmlSchemaTypePtr
9134xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009135 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009136{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009137 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009138 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009139 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009140 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009141 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009142
9143 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9144 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009145
Daniel Veillardc0826a72004-08-10 14:17:33 +00009146 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009147 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009148 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009149 xmlSchemaPMissingAttrErr(ctxt,
9150 XML_SCHEMAP_S4S_ATTR_MISSING,
9151 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009152 "name", NULL);
9153 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009154 } else {
9155 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009156 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009157 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9158 return (NULL);
9159 /*
9160 * Skip built-in types.
9161 */
9162 if (ctxt->isS4S) {
9163 xmlSchemaTypePtr biType;
9164
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009165 if (ctxt->isRedefine) {
9166 /*
9167 * REDEFINE: Disallow redefinition of built-in-types.
9168 * TODO: It seems that the spec does not say anything
9169 * about this case.
9170 */
9171 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009172 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009173 "Redefinition of built-in simple types is not "
9174 "supported", NULL);
9175 return(NULL);
9176 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009177 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9178 if (biType != NULL)
9179 return (biType);
9180 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009181 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009182 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009183 /*
9184 * TargetNamespace:
Jan Pokorný761c9e92013-11-29 23:26:27 +01009185 * SPEC "The `actual value` of the targetNamespace [attribute]
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009186 * of the <schema> ancestor element information item if present,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009187 * otherwise `absent`.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009188 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009189 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009190#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009191 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009192#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009193 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009194 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009195 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009196#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009197 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009198 type = xmlSchemaAddType(ctxt, schema,
9199 XML_SCHEMA_TYPE_SIMPLE,
9200 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009201 ctxt->targetNamespace, node, 0);
9202#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009203 type = xmlSchemaAddType(ctxt, schema,
9204 XML_SCHEMA_TYPE_SIMPLE,
9205 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009206#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207 if (type == NULL)
9208 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009209 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009211 /*
9212 * Check for illegal attributes.
9213 */
9214 attr = node->properties;
9215 while (attr != NULL) {
9216 if (attr->ns == NULL) {
9217 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00009219 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009220 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009221 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009222 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009224 }
9225 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009226 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009227 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009228 /*
9229 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009230 *
9231 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009233 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9234 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009235 if (type == NULL)
9236 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009237 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009238 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009239 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9240 /*
9241 * Check for illegal attributes.
9242 */
9243 attr = node->properties;
9244 while (attr != NULL) {
9245 if (attr->ns == NULL) {
9246 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9247 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009248 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009249 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009250 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009251 }
9252 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009253 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009255 }
9256 attr = attr->next;
9257 }
9258 /*
9259 * Attribute "final".
9260 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009261 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009262 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009263 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9264 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9265 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9266 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9267 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9268 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009269 } else {
9270 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009271 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9272 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009273 XML_SCHEMAS_TYPE_FINAL_LIST,
9274 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9275
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009276 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009277 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009278 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009279 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009280 attrValue, NULL, NULL, NULL);
9281 }
9282 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009283 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009284 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009285 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009286 /*
9287 * And now for the children...
9288 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009289 oldCtxtType = ctxt->ctxtType;
Daniel Veillarddee23482008-04-11 12:58:43 +00009290
Daniel Veillardc0826a72004-08-10 14:17:33 +00009291 ctxt->ctxtType = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00009292
Daniel Veillard4255d502002-04-16 15:50:10 +00009293 child = node->children;
9294 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009295 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009296 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009297 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009298 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009300 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009301 "(annotation?, (restriction | list | union))");
Daniel Veillarddee23482008-04-11 12:58:43 +00009302 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009303 xmlSchemaParseRestriction(ctxt, schema, child,
Daniel Veillarddee23482008-04-11 12:58:43 +00009304 XML_SCHEMA_TYPE_SIMPLE);
9305 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009306 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009307 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009308 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009309 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009310 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009311 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009312 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009313 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009314 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009315 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009316 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009317 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009318 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009319 /*
9320 * REDEFINE: SPEC src-redefine (5)
9321 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +01009322 * <restriction> among its [children] ... the `actual value` of whose
9323 * base [attribute] must be the same as the `actual value` of its own
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009324 * name attribute plus target namespace;"
9325 */
9326 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9327 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009328 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009329 "<simpleType> must have a <restriction> child", NULL);
9330 }
Daniel Veillarddee23482008-04-11 12:58:43 +00009331
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009332 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009333 return (type);
9334}
9335
Daniel Veillard4255d502002-04-16 15:50:10 +00009336/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009337 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009338 * @ctxt: the parser context
9339 * @schema: the schema being built
9340 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009341 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009342 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009343 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009344 * We will return a particle component with a qname-component or
9345 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009346 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009347static xmlSchemaTreeItemPtr
9348xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9349 xmlSchemaPtr schema,
9350 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009351{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009352 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009353 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009354 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009355 const xmlChar *ref = NULL, *refNs = NULL;
9356 int min, max;
9357
9358 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009359 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009360
9361 attr = xmlSchemaGetPropNode(node, "ref");
9362 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009363 xmlSchemaPMissingAttrErr(ctxt,
9364 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009365 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009366 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009367 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009368 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009369 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009370 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009371 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009372 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009373 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009374 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009375 /*
9376 * Check for illegal attributes.
9377 */
9378 attr = node->properties;
9379 while (attr != NULL) {
9380 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009381 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009382 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9383 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9384 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009385 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009386 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009387 }
9388 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009389 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009390 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009391 }
9392 attr = attr->next;
9393 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009394 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00009395 item = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009396 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00009397 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009398 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009399 * Create a qname-reference and set as the term; it will be substituted
9400 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401 */
9402 item->children = (xmlSchemaTreeItemPtr)
Daniel Veillarddee23482008-04-11 12:58:43 +00009403 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009404 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9405 /*
9406 * And now for the children...
9407 */
9408 child = node->children;
9409 /* TODO: Is annotation even allowed for a model group reference? */
9410 if (IS_SCHEMA(child, "annotation")) {
9411 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009412 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009413 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009414 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009415 child = child->next;
9416 }
9417 if (child != NULL) {
9418 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009419 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009420 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009421 "(annotation?)");
9422 }
9423 /*
9424 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9425 */
9426 if ((min == 0) && (max == 0))
9427 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009428
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009429 return ((xmlSchemaTreeItemPtr) item);
9430}
9431
9432/**
9433 * xmlSchemaParseModelGroupDefinition:
9434 * @ctxt: a schema validation context
9435 * @schema: the schema being built
9436 * @node: a subtree containing XML Schema informations
9437 *
9438 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009439 *
9440 * Note that the contraint src-redefine (6.2) can't be applied until
9441 * references have been resolved. So we will do this at the
9442 * component fixup level.
Daniel Veillarddee23482008-04-11 12:58:43 +00009443 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009444 * *WARNING* this interface is highly subject to change
9445 *
9446 * Returns -1 in case of error, 0 if the declaration is improper and
9447 * 1 in case of success.
9448 */
9449static xmlSchemaModelGroupDefPtr
9450xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9451 xmlSchemaPtr schema,
9452 xmlNodePtr node)
9453{
9454 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009455 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009456 xmlAttrPtr attr;
9457 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009458
9459 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009460 return (NULL);
9461
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009462 attr = xmlSchemaGetPropNode(node, "name");
9463 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009464 xmlSchemaPMissingAttrErr(ctxt,
9465 XML_SCHEMAP_S4S_ATTR_MISSING,
9466 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009467 "name", NULL);
9468 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009469 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009470 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9471 return (NULL);
9472 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009473 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9474 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009475 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009476 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009477 /*
9478 * Check for illegal attributes.
9479 */
9480 attr = node->properties;
9481 while (attr != NULL) {
9482 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009483 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009484 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009485 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009486 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009487 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009488 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009489 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009490 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009491 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009492 attr = attr->next;
9493 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009494 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009495 /*
9496 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009497 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009498 child = node->children;
9499 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009500 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009501 child = child->next;
9502 }
9503 if (IS_SCHEMA(child, "all")) {
9504 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9505 XML_SCHEMA_TYPE_ALL, 0);
9506 child = child->next;
9507 } else if (IS_SCHEMA(child, "choice")) {
9508 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9509 XML_SCHEMA_TYPE_CHOICE, 0);
9510 child = child->next;
9511 } else if (IS_SCHEMA(child, "sequence")) {
9512 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9513 XML_SCHEMA_TYPE_SEQUENCE, 0);
9514 child = child->next;
9515 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009516
Daniel Veillarddee23482008-04-11 12:58:43 +00009517
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009518
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009519 if (child != NULL) {
9520 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009521 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009522 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009523 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009524 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009525 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009526}
9527
9528/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009529 * xmlSchemaCleanupDoc:
9530 * @ctxt: a schema validation context
9531 * @node: the root of the document.
9532 *
9533 * removes unwanted nodes in a schemas document tree
9534 */
9535static void
9536xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9537{
9538 xmlNodePtr delete, cur;
9539
9540 if ((ctxt == NULL) || (root == NULL)) return;
9541
9542 /*
9543 * Remove all the blank text nodes
9544 */
9545 delete = NULL;
9546 cur = root;
9547 while (cur != NULL) {
9548 if (delete != NULL) {
9549 xmlUnlinkNode(delete);
9550 xmlFreeNode(delete);
9551 delete = NULL;
9552 }
9553 if (cur->type == XML_TEXT_NODE) {
9554 if (IS_BLANK_NODE(cur)) {
9555 if (xmlNodeGetSpacePreserve(cur) != 1) {
9556 delete = cur;
9557 }
9558 }
9559 } else if ((cur->type != XML_ELEMENT_NODE) &&
9560 (cur->type != XML_CDATA_SECTION_NODE)) {
9561 delete = cur;
9562 goto skip_children;
9563 }
9564
9565 /*
9566 * Skip to next node
9567 */
9568 if (cur->children != NULL) {
9569 if ((cur->children->type != XML_ENTITY_DECL) &&
9570 (cur->children->type != XML_ENTITY_REF_NODE) &&
9571 (cur->children->type != XML_ENTITY_NODE)) {
9572 cur = cur->children;
9573 continue;
9574 }
9575 }
9576 skip_children:
9577 if (cur->next != NULL) {
9578 cur = cur->next;
9579 continue;
9580 }
9581
9582 do {
9583 cur = cur->parent;
9584 if (cur == NULL)
9585 break;
9586 if (cur == root) {
9587 cur = NULL;
9588 break;
9589 }
9590 if (cur->next != NULL) {
9591 cur = cur->next;
9592 break;
9593 }
9594 } while (cur != NULL);
9595 }
9596 if (delete != NULL) {
9597 xmlUnlinkNode(delete);
9598 xmlFreeNode(delete);
9599 delete = NULL;
9600 }
9601}
9602
William M. Brack2f2a6632004-08-20 23:09:47 +00009603
William M. Brack2f2a6632004-08-20 23:09:47 +00009604static void
9605xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9606{
9607 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9608 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9609
9610 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9611 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9612
9613 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9614 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9615 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9616 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9617 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9618 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9619 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9620 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9621
9622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9623 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9625 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9626 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9627 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9628}
9629
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009630static int
9631xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 xmlSchemaPtr schema,
9633 xmlNodePtr node)
9634{
9635 xmlAttrPtr attr;
9636 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009637 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009638
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009639 /*
9640 * Those flags should be moved to the parser context flags,
9641 * since they are not visible at the component level. I.e.
9642 * they are used if processing schema *documents* only.
9643 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009644 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009645 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009646
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009647 /*
9648 * Since the version is of type xs:token, we won't bother to
9649 * check it.
9650 */
9651 /* REMOVED:
9652 attr = xmlSchemaGetPropNode(node, "version");
9653 if (attr != NULL) {
9654 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillarddee23482008-04-11 12:58:43 +00009655 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009656 HFAILURE;
9657 }
9658 */
9659 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9660 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009661 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009662 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9663 HFAILURE;
9664 if (res != 0) {
9665 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9666 goto exit;
9667 }
9668 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009670 if (attr != NULL) {
9671 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009672 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9673 XML_SCHEMAS_QUALIF_ELEM);
9674 HFAILURE;
9675 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009676 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009677 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009679 "(qualified | unqualified)", val, NULL, NULL, NULL);
9680 }
9681 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009683 if (attr != NULL) {
9684 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009685 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9686 XML_SCHEMAS_QUALIF_ATTR);
9687 HFAILURE;
9688 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009689 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009690 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009691 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009692 "(qualified | unqualified)", val, NULL, NULL, NULL);
9693 }
9694 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009695 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009696 if (attr != NULL) {
9697 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009698 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009699 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9700 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9701 -1,
9702 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009703 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9704 HFAILURE;
9705 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009706 xmlSchemaPSimpleTypeErr(ctxt,
9707 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009708 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009709 "(#all | List of (extension | restriction | list | union))",
9710 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009711 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009712 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009714 if (attr != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00009715 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009716 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009717 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9718 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009719 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9720 HFAILURE;
9721 if (res != 0) {
9722 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009723 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009724 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009725 "(#all | List of (extension | restriction | substitution))",
9726 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009728 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009729
9730exit:
9731 if (oldErrs != ctxt->nberrors)
9732 res = ctxt->err;
9733 return(res);
9734exit_failure:
9735 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009736}
9737
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009738/**
9739 * xmlSchemaParseSchemaTopLevel:
9740 * @ctxt: a schema validation context
9741 * @schema: the schemas
9742 * @nodes: the list of top level nodes
9743 *
9744 * Returns the internal XML Schema structure built from the resource or
9745 * NULL in case of error
9746 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009747static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009748xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9749 xmlSchemaPtr schema, xmlNodePtr nodes)
9750{
9751 xmlNodePtr child;
9752 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009753 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009754
9755 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009756 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009757
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009758 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009759 child = nodes;
9760 while ((IS_SCHEMA(child, "include")) ||
9761 (IS_SCHEMA(child, "import")) ||
9762 (IS_SCHEMA(child, "redefine")) ||
9763 (IS_SCHEMA(child, "annotation"))) {
9764 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009765 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009766 if (schema->annot == NULL)
9767 schema->annot = annot;
9768 else
9769 xmlSchemaFreeAnnot(annot);
9770 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009771 tmpOldErrs = ctxt->nberrors;
9772 res = xmlSchemaParseImport(ctxt, schema, child);
9773 HFAILURE;
9774 HSTOP(ctxt);
9775 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009776 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009777 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009778 tmpOldErrs = ctxt->nberrors;
9779 res = xmlSchemaParseInclude(ctxt, schema, child);
9780 HFAILURE;
9781 HSTOP(ctxt);
9782 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009783 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009784 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009785 tmpOldErrs = ctxt->nberrors;
9786 res = xmlSchemaParseRedefine(ctxt, schema, child);
9787 HFAILURE;
9788 HSTOP(ctxt);
9789 if (tmpOldErrs != ctxt->nberrors)
9790 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009791 }
9792 child = child->next;
9793 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009794 /*
9795 * URGENT TODO: Change the functions to return int results.
9796 * We need especially to catch internal errors.
9797 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009798 while (child != NULL) {
9799 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009800 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009801 child = child->next;
9802 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009803 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009804 child = child->next;
9805 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009806 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009807 child = child->next;
9808 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009809 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009810 child = child->next;
9811 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009812 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009813 child = child->next;
9814 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009815 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009816 child = child->next;
9817 } else if (IS_SCHEMA(child, "notation")) {
9818 xmlSchemaParseNotation(ctxt, schema, child);
9819 child = child->next;
9820 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009821 xmlSchemaPContentErr(ctxt,
9822 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009823 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009824 NULL, "((include | import | redefine | annotation)*, "
9825 "(((simpleType | complexType | group | attributeGroup) "
9826 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009827 child = child->next;
9828 }
9829 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009830 /*
9831 * TODO: We should add all annotations.
9832 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009833 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009834 if (schema->annot == NULL)
9835 schema->annot = annot;
9836 else
9837 xmlSchemaFreeAnnot(annot);
9838 child = child->next;
9839 }
9840 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009841exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009842 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009843 if (oldErrs != ctxt->nberrors)
9844 res = ctxt->err;
9845 return(res);
9846exit_failure:
9847 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009848}
9849
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009850static xmlSchemaSchemaRelationPtr
9851xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009852{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009853 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009854
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009855 ret = (xmlSchemaSchemaRelationPtr)
9856 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009857 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009858 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009859 return(NULL);
9860 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009861 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009862 return(ret);
9863}
9864
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009865#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009866static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009867xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009868{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009869 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009870}
9871#endif
9872
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009873static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009874xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9875{
9876 xmlSchemaRedefPtr prev;
9877
9878 while (redef != NULL) {
9879 prev = redef;
9880 redef = redef->next;
9881 xmlFree(prev);
9882 }
9883}
9884
9885static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009886xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9887{
9888 /*
9889 * After the construction context has been freed, there will be
9890 * no schema graph available any more. Only the schema buckets
9891 * will stay alive, which are put into the "schemasImports" and
9892 * "includes" slots of the xmlSchema.
9893 */
9894 if (con->buckets != NULL)
9895 xmlSchemaItemListFree(con->buckets);
9896 if (con->pending != NULL)
9897 xmlSchemaItemListFree(con->pending);
9898 if (con->substGroups != NULL)
9899 xmlHashFree(con->substGroups,
9900 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009901 if (con->redefs != NULL)
9902 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009903 if (con->dict != NULL)
9904 xmlDictFree(con->dict);
9905 xmlFree(con);
9906}
9907
Daniel Veillarddee23482008-04-11 12:58:43 +00009908static xmlSchemaConstructionCtxtPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009909xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9910{
9911 xmlSchemaConstructionCtxtPtr ret;
9912
9913 ret = (xmlSchemaConstructionCtxtPtr)
9914 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9915 if (ret == NULL) {
9916 xmlSchemaPErrMemory(NULL,
9917 "allocating schema construction context", NULL);
9918 return (NULL);
9919 }
9920 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9921
9922 ret->buckets = xmlSchemaItemListCreate();
9923 if (ret->buckets == NULL) {
9924 xmlSchemaPErrMemory(NULL,
9925 "allocating list of schema buckets", NULL);
9926 xmlFree(ret);
9927 return (NULL);
9928 }
9929 ret->pending = xmlSchemaItemListCreate();
9930 if (ret->pending == NULL) {
9931 xmlSchemaPErrMemory(NULL,
9932 "allocating list of pending global components", NULL);
9933 xmlSchemaConstructionCtxtFree(ret);
9934 return (NULL);
9935 }
9936 ret->dict = dict;
9937 xmlDictReference(dict);
9938 return(ret);
9939}
9940
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009941static xmlSchemaParserCtxtPtr
9942xmlSchemaParserCtxtCreate(void)
9943{
9944 xmlSchemaParserCtxtPtr ret;
9945
9946 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9947 if (ret == NULL) {
9948 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9949 NULL);
9950 return (NULL);
9951 }
9952 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9953 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009954 ret->attrProhibs = xmlSchemaItemListCreate();
9955 if (ret->attrProhibs == NULL) {
9956 xmlFree(ret);
9957 return(NULL);
9958 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009959 return(ret);
9960}
9961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962/**
9963 * xmlSchemaNewParserCtxtUseDict:
9964 * @URL: the location of the schema
9965 * @dict: the dictionary to be used
9966 *
9967 * Create an XML Schemas parse context for that file/resource expected
9968 * to contain an XML Schemas file.
9969 *
9970 * Returns the parser context or NULL in case of error
9971 */
9972static xmlSchemaParserCtxtPtr
9973xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9974{
9975 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009976
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009977 ret = xmlSchemaParserCtxtCreate();
Daniel Veillarddee23482008-04-11 12:58:43 +00009978 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009979 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009980 ret->dict = dict;
Daniel Veillarddee23482008-04-11 12:58:43 +00009981 xmlDictReference(dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009982 if (URL != NULL)
9983 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009984 return (ret);
9985}
9986
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009987static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009988xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9989{
9990 if (vctxt->pctxt == NULL) {
9991 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009992 vctxt->pctxt =
9993 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009994 else
9995 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9996 if (vctxt->pctxt == NULL) {
9997 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9998 "failed to create a temp. parser context");
9999 return (-1);
10000 }
10001 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010002 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010003 vctxt->warning, vctxt->errCtxt);
10004 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10005 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010006 }
10007 return (0);
10008}
10009
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010010/**
10011 * xmlSchemaGetSchemaBucket:
10012 * @pctxt: the schema parser context
10013 * @schemaLocation: the URI of the schema document
10014 *
10015 * Returns a schema bucket if it was already parsed.
10016 *
10017 * Returns a schema bucket if it was already parsed from
10018 * @schemaLocation, NULL otherwise.
10019 */
10020static xmlSchemaBucketPtr
10021xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10022 const xmlChar *schemaLocation)
10023{
10024 xmlSchemaBucketPtr cur;
10025 xmlSchemaItemListPtr list;
10026
10027 list = pctxt->constructor->buckets;
10028 if (list->nbItems == 0)
10029 return(NULL);
10030 else {
10031 int i;
10032 for (i = 0; i < list->nbItems; i++) {
10033 cur = (xmlSchemaBucketPtr) list->items[i];
10034 /* Pointer comparison! */
10035 if (cur->schemaLocation == schemaLocation)
10036 return(cur);
10037 }
10038 }
10039 return(NULL);
10040}
10041
10042static xmlSchemaBucketPtr
10043xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10044 const xmlChar *schemaLocation,
10045 const xmlChar *targetNamespace)
10046{
10047 xmlSchemaBucketPtr cur;
10048 xmlSchemaItemListPtr list;
10049
10050 list = pctxt->constructor->buckets;
10051 if (list->nbItems == 0)
10052 return(NULL);
10053 else {
10054 int i;
10055 for (i = 0; i < list->nbItems; i++) {
10056 cur = (xmlSchemaBucketPtr) list->items[i];
10057 /* Pointer comparison! */
10058 if ((cur->origTargetNamespace == NULL) &&
10059 (cur->schemaLocation == schemaLocation) &&
10060 (cur->targetNamespace == targetNamespace))
10061 return(cur);
10062 }
10063 }
10064 return(NULL);
10065}
10066
10067
10068#define IS_BAD_SCHEMA_DOC(b) \
10069 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10070
10071static xmlSchemaBucketPtr
10072xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10073 const xmlChar *targetNamespace,
10074 int imported)
10075{
10076 xmlSchemaBucketPtr cur;
10077 xmlSchemaItemListPtr list;
10078
10079 list = pctxt->constructor->buckets;
10080 if (list->nbItems == 0)
10081 return(NULL);
10082 else {
10083 int i;
10084 for (i = 0; i < list->nbItems; i++) {
10085 cur = (xmlSchemaBucketPtr) list->items[i];
10086 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10087 (cur->origTargetNamespace == targetNamespace) &&
10088 ((imported && cur->imported) ||
10089 ((!imported) && (!cur->imported))))
10090 return(cur);
10091 }
10092 }
10093 return(NULL);
10094}
10095
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010096static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010097xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10098 xmlSchemaPtr schema,
10099 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010100{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010101 int oldFlags;
10102 xmlDocPtr oldDoc;
10103 xmlNodePtr node;
10104 int ret, oldErrs;
10105 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000010106
10107 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010108 * Save old values; reset the *main* schema.
10109 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010110 * to the parser. Get rid of passing the main schema to the
10111 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010112 */
10113 oldFlags = schema->flags;
10114 oldDoc = schema->doc;
10115 if (schema->flags != 0)
10116 xmlSchemaClearSchemaDefaults(schema);
Daniel Veillarddee23482008-04-11 12:58:43 +000010117 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010118 pctxt->schema = schema;
Daniel Veillarddee23482008-04-11 12:58:43 +000010119 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010120 * Keep the current target namespace on the parser *not* on the
10121 * main schema.
10122 */
10123 pctxt->targetNamespace = bucket->targetNamespace;
10124 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010125
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010126 if ((bucket->targetNamespace != NULL) &&
10127 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010128 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010129 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010130 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010131 pctxt->isS4S = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000010132 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010133 /* Mark it as parsed, even if parsing fails. */
10134 bucket->parsed++;
10135 /* Compile the schema doc. */
10136 node = xmlDocGetRootElement(bucket->doc);
10137 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10138 if (ret != 0)
10139 goto exit;
10140 /* An empty schema; just get out. */
10141 if (node->children == NULL)
10142 goto exit;
10143 oldErrs = pctxt->nberrors;
10144 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10145 if (ret != 0)
10146 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010147 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010148 * TODO: Not nice, but I'm not 100% sure we will get always an error
10149 * as a result of the obove functions; so better rely on pctxt->err
10150 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010151 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010152 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10153 ret = pctxt->err;
10154 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010155 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010156
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010157exit:
10158 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10159 /* Restore schema values. */
10160 schema->doc = oldDoc;
10161 schema->flags = oldFlags;
10162 return(ret);
10163}
10164
10165static int
10166xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10167 xmlSchemaPtr schema,
10168 xmlSchemaBucketPtr bucket)
10169{
10170 xmlSchemaParserCtxtPtr newpctxt;
10171 int res = 0;
10172
10173 if (bucket == NULL)
10174 return(0);
10175 if (bucket->parsed) {
10176 PERROR_INT("xmlSchemaParseNewDoc",
10177 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010178 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010179 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010180 if (bucket->doc == NULL) {
10181 PERROR_INT("xmlSchemaParseNewDoc",
10182 "parsing a schema doc, but there's no doc");
10183 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010184 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010185 if (pctxt->constructor == NULL) {
10186 PERROR_INT("xmlSchemaParseNewDoc",
10187 "no constructor");
10188 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000010189 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010190 /* Create and init the temporary parser context. */
10191 newpctxt = xmlSchemaNewParserCtxtUseDict(
10192 (const char *) bucket->schemaLocation, pctxt->dict);
10193 if (newpctxt == NULL)
10194 return(-1);
10195 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010196 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000010197 * TODO: Can we avoid that the parser knows about the main schema?
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010198 * It would be better if he knows about the current schema bucket
10199 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010201 newpctxt->schema = schema;
10202 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010203 pctxt->errCtxt);
10204 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10205 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010206 newpctxt->counter = pctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010207
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010208
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010209 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
Daniel Veillarddee23482008-04-11 12:58:43 +000010210
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010211 /* Channel back errors and cleanup the temporary parser context. */
10212 if (res != 0)
10213 pctxt->err = res;
10214 pctxt->nberrors += newpctxt->nberrors;
10215 pctxt->counter = newpctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010216 newpctxt->constructor = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010217 /* Free the parser context. */
10218 xmlSchemaFreeParserCtxt(newpctxt);
10219 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010220}
William M. Brack2f2a6632004-08-20 23:09:47 +000010221
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010222static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010223xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10224 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010225{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010226 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010227
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010228 if (cur == NULL) {
10229 bucket->relations = rel;
10230 return;
10231 }
10232 while (cur->next != NULL)
10233 cur = cur->next;
10234 cur->next = rel;
10235}
10236
10237
10238static const xmlChar *
10239xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10240 xmlNodePtr ctxtNode)
Daniel Veillarddee23482008-04-11 12:58:43 +000010241{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010242 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010243 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010244 */
Daniel Veillarddee23482008-04-11 12:58:43 +000010245 if (location != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010246 if (ctxtNode == NULL)
10247 return(location);
10248 else {
10249 xmlChar *base, *URI;
10250 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010251
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010252 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10253 if (base == NULL) {
10254 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10255 } else {
10256 URI = xmlBuildURI(location, base);
10257 xmlFree(base);
10258 }
10259 if (URI != NULL) {
10260 ret = xmlDictLookup(dict, URI, -1);
10261 xmlFree(URI);
10262 return(ret);
10263 }
10264 }
10265 }
10266 return(NULL);
10267}
Daniel Veillarddee23482008-04-11 12:58:43 +000010268
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010269
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010270
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010271/**
10272 * xmlSchemaAddSchemaDoc:
10273 * @pctxt: a schema validation context
10274 * @schema: the schema being built
10275 * @node: a subtree containing XML Schema informations
10276 *
10277 * Parse an included (and to-be-redefined) XML schema document.
10278 *
10279 * Returns 0 on success, a positive error code on errors and
10280 * -1 in case of an internal or API error.
10281 */
10282
10283static int
10284xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10285 int type, /* import or include or redefine */
10286 const xmlChar *schemaLocation,
10287 xmlDocPtr schemaDoc,
10288 const char *schemaBuffer,
10289 int schemaBufferLen,
10290 xmlNodePtr invokingNode,
Daniel Veillarddee23482008-04-11 12:58:43 +000010291 const xmlChar *sourceTargetNamespace,
10292 const xmlChar *importNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010293 xmlSchemaBucketPtr *bucket)
10294{
10295 const xmlChar *targetNamespace = NULL;
10296 xmlSchemaSchemaRelationPtr relation = NULL;
10297 xmlDocPtr doc = NULL;
10298 int res = 0, err = 0, located = 0, preserveDoc = 0;
10299 xmlSchemaBucketPtr bkt = NULL;
10300
10301 if (bucket != NULL)
10302 *bucket = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010303
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010304 switch (type) {
10305 case XML_SCHEMA_SCHEMA_IMPORT:
10306 case XML_SCHEMA_SCHEMA_MAIN:
10307 err = XML_SCHEMAP_SRC_IMPORT;
10308 break;
10309 case XML_SCHEMA_SCHEMA_INCLUDE:
10310 err = XML_SCHEMAP_SRC_INCLUDE;
10311 break;
10312 case XML_SCHEMA_SCHEMA_REDEFINE:
10313 err = XML_SCHEMAP_SRC_REDEFINE;
10314 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000010315 }
10316
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010317
10318 /* Special handling for the main schema:
10319 * skip the location and relation logic and just parse the doc.
10320 * We need just a bucket to be returned in this case.
Daniel Veillarddee23482008-04-11 12:58:43 +000010321 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010322 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
Daniel Veillarddee23482008-04-11 12:58:43 +000010323 goto doc_load;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010324
Daniel Veillarddee23482008-04-11 12:58:43 +000010325 /* Note that we expect the location to be an absulute URI. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010326 if (schemaLocation != NULL) {
10327 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10328 if ((bkt != NULL) &&
10329 (pctxt->constructor->bucket == bkt)) {
10330 /* Report self-imports/inclusions/redefinitions. */
Daniel Veillarddee23482008-04-11 12:58:43 +000010331
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010332 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10333 invokingNode, NULL,
10334 "The schema must not import/include/redefine itself",
10335 NULL, NULL);
10336 goto exit;
10337 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010338 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010339 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010340 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010342 relation = xmlSchemaSchemaRelationCreate();
10343 if (relation == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010344 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010345 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10346 relation);
10347 relation->type = type;
10348
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010349 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010350 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010351 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010352 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010353 relation->importNamespace = importNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010354 if (schemaLocation == NULL) {
10355 /*
10356 * No location; this is just an import of the namespace.
10357 * Note that we don't assign a bucket to the relation
10358 * in this case.
10359 */
10360 goto exit;
10361 }
10362 targetNamespace = importNamespace;
10363 }
10364
10365 /* Did we already fetch the doc? */
Daniel Veillarddee23482008-04-11 12:58:43 +000010366 if (bkt != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010367 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010368 /*
10369 * We included/redefined and then try to import a schema,
10370 * but the new location provided for import was different.
10371 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010372 if (schemaLocation == NULL)
10373 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010374 if (!xmlStrEqual(schemaLocation,
10375 bkt->schemaLocation)) {
10376 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10377 invokingNode, NULL,
10378 "The schema document '%s' cannot be imported, since "
10379 "it was already included or redefined",
10380 schemaLocation, NULL);
10381 goto exit;
10382 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010383 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010384 /*
10385 * We imported and then try to include/redefine a schema,
10386 * but the new location provided for the include/redefine
10387 * was different.
10388 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010389 if (schemaLocation == NULL)
10390 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010391 if (!xmlStrEqual(schemaLocation,
10392 bkt->schemaLocation)) {
10393 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10394 invokingNode, NULL,
10395 "The schema document '%s' cannot be included or "
10396 "redefined, since it was already imported",
10397 schemaLocation, NULL);
10398 goto exit;
10399 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010400 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010401 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010402
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010403 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010404 /*
10405 * Given that the schemaLocation [attribute] is only a hint, it is open
10406 * to applications to ignore all but the first <import> for a given
Jan Pokorný761c9e92013-11-29 23:26:27 +010010407 * namespace, regardless of the `actual value` of schemaLocation, but
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010408 * such a strategy risks missing useful information when new
10409 * schemaLocations are offered.
10410 *
10411 * We will use the first <import> that comes with a location.
10412 * Further <import>s *with* a location, will result in an error.
10413 * TODO: Better would be to just report a warning here, but
10414 * we'll try it this way until someone complains.
10415 *
10416 * Schema Document Location Strategy:
10417 * 3 Based on the namespace name, identify an existing schema document,
10418 * either as a resource which is an XML document or a <schema> element
10419 * information item, in some local schema repository;
10420 * 5 Attempt to resolve the namespace name to locate such a resource.
10421 *
10422 * NOTE: (3) and (5) are not supported.
Daniel Veillarddee23482008-04-11 12:58:43 +000010423 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010424 if (bkt != NULL) {
10425 relation->bucket = bkt;
10426 goto exit;
10427 }
10428 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10429 importNamespace, 1);
10430
Daniel Veillarddee23482008-04-11 12:58:43 +000010431 if (bkt != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010432 relation->bucket = bkt;
10433 if (bkt->schemaLocation == NULL) {
10434 /* First given location of the schema; load the doc. */
10435 bkt->schemaLocation = schemaLocation;
10436 } else {
10437 if (!xmlStrEqual(schemaLocation,
10438 bkt->schemaLocation)) {
10439 /*
10440 * Additional location given; just skip it.
10441 * URGENT TODO: We should report a warning here.
10442 * res = XML_SCHEMAP_SRC_IMPORT;
10443 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010444 if (schemaLocation == NULL)
10445 schemaLocation = BAD_CAST "in_memory_buffer";
10446
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010447 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10448 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10449 invokingNode, NULL,
10450 "Skipping import of schema located at '%s' for the "
10451 "namespace '%s', since this namespace was already "
10452 "imported with the schema located at '%s'",
10453 schemaLocation, importNamespace, bkt->schemaLocation);
10454 }
10455 goto exit;
10456 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010457 }
10458 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010459 * No bucket + first location: load the doc and create a
10460 * bucket.
10461 */
10462 } else {
10463 /* <include> and <redefine> */
10464 if (bkt != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010465
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010466 if ((bkt->origTargetNamespace == NULL) &&
10467 (bkt->targetNamespace != sourceTargetNamespace)) {
10468 xmlSchemaBucketPtr chamel;
Daniel Veillarddee23482008-04-11 12:58:43 +000010469
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010470 /*
10471 * Chameleon include/redefine: skip loading only if it was
10472 * aleady build for the targetNamespace of the including
10473 * schema.
10474 */
10475 /*
10476 * URGENT TODO: If the schema is a chameleon-include then copy
10477 * the components into the including schema and modify the
10478 * targetNamespace of those components, do nothing otherwise.
10479 * NOTE: This is currently worked-around by compiling the
10480 * chameleon for every destinct including targetNamespace; thus
10481 * not performant at the moment.
10482 * TODO: Check when the namespace in wildcards for chameleons
10483 * needs to be converted: before we built wildcard intersections
10484 * or after.
10485 * Answer: after!
10486 */
10487 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10488 schemaLocation, sourceTargetNamespace);
10489 if (chamel != NULL) {
10490 /* A fitting chameleon was already parsed; NOP. */
10491 relation->bucket = chamel;
10492 goto exit;
10493 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010494 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010495 * We need to parse the chameleon again for a different
10496 * targetNamespace.
10497 * CHAMELEON TODO: Optimize this by only parsing the
10498 * chameleon once, and then copying the components to
10499 * the new targetNamespace.
10500 */
10501 bkt = NULL;
10502 } else {
10503 relation->bucket = bkt;
10504 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000010505 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010506 }
10507 }
10508 if ((bkt != NULL) && (bkt->doc != NULL)) {
10509 PERROR_INT("xmlSchemaAddSchemaDoc",
10510 "trying to load a schema doc, but a doc is already "
10511 "assigned to the schema bucket");
10512 goto exit_failure;
10513 }
10514
10515doc_load:
10516 /*
10517 * Load the document.
10518 */
10519 if (schemaDoc != NULL) {
10520 doc = schemaDoc;
10521 /* Don' free this one, since it was provided by the caller. */
10522 preserveDoc = 1;
10523 /* TODO: Does the context or the doc hold the location? */
10524 if (schemaDoc->URL != NULL)
10525 schemaLocation = xmlDictLookup(pctxt->dict,
10526 schemaDoc->URL, -1);
Daniel Veillard734e7662007-06-26 11:30:31 +000010527 else
10528 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010529 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10530 xmlParserCtxtPtr parserCtxt;
10531
10532 parserCtxt = xmlNewParserCtxt();
10533 if (parserCtxt == NULL) {
10534 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10535 "allocating a parser context", NULL);
10536 goto exit_failure;
10537 }
10538 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10539 /*
10540 * TODO: Do we have to burden the schema parser dict with all
10541 * the content of the schema doc?
10542 */
10543 xmlDictFree(parserCtxt->dict);
10544 parserCtxt->dict = pctxt->dict;
10545 xmlDictReference(parserCtxt->dict);
10546 }
10547 if (schemaLocation != NULL) {
10548 /* Parse from file. */
10549 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10550 NULL, SCHEMAS_PARSE_OPTIONS);
10551 } else if (schemaBuffer != NULL) {
10552 /* Parse from memory buffer. */
10553 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10554 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
Rob Richards410d2c42009-09-24 11:00:16 -040010555 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010556 if (doc != NULL)
Rob Richards410d2c42009-09-24 11:00:16 -040010557 doc->URL = xmlStrdup(schemaLocation);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010558 }
10559 /*
10560 * For <import>:
10561 * 2.1 The referent is (a fragment of) a resource which is an
10562 * XML document (see clause 1.1), which in turn corresponds to
10563 * a <schema> element information item in a well-formed information
10564 * set, which in turn corresponds to a valid schema.
10565 * TODO: (2.1) fragments of XML documents are not supported.
10566 *
10567 * 2.2 The referent is a <schema> element information item in
10568 * a well-formed information set, which in turn corresponds
10569 * to a valid schema.
10570 * TODO: (2.2) is not supported.
10571 */
10572 if (doc == NULL) {
10573 xmlErrorPtr lerr;
10574 lerr = xmlGetLastError();
10575 /*
10576 * Check if this a parser error, or if the document could
10577 * just not be located.
10578 * TODO: Try to find specific error codes to react only on
10579 * localisation failures.
10580 */
10581 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10582 /*
10583 * We assume a parser error here.
10584 */
10585 located = 1;
10586 /* TODO: Error code ?? */
10587 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10588 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10589 invokingNode, NULL,
10590 "Failed to parse the XML resource '%s'",
Daniel Veillard734e7662007-06-26 11:30:31 +000010591 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010592 }
10593 }
10594 xmlFreeParserCtxt(parserCtxt);
10595 if ((doc == NULL) && located)
10596 goto exit_error;
10597 } else {
10598 xmlSchemaPErr(pctxt, NULL,
10599 XML_SCHEMAP_NOTHING_TO_PARSE,
10600 "No information for parsing was provided with the "
10601 "given schema parser context.\n",
10602 NULL, NULL);
10603 goto exit_failure;
10604 }
10605 /*
10606 * Preprocess the document.
10607 */
10608 if (doc != NULL) {
10609 xmlNodePtr docElem = NULL;
10610
Daniel Veillarddee23482008-04-11 12:58:43 +000010611 located = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010612 docElem = xmlDocGetRootElement(doc);
10613 if (docElem == NULL) {
10614 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
Daniel Veillarddee23482008-04-11 12:58:43 +000010615 invokingNode, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010616 "The document '%s' has no document element",
10617 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010618 goto exit_error;
10619 }
10620 /*
10621 * Remove all the blank text nodes.
10622 */
10623 xmlSchemaCleanupDoc(pctxt, docElem);
10624 /*
10625 * Check the schema's top level element.
10626 */
10627 if (!IS_SCHEMA(docElem, "schema")) {
10628 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10629 invokingNode, NULL,
10630 "The XML document '%s' is not a schema document",
10631 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010632 goto exit_error;
10633 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010634 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010635 * Note that we don't apply a type check for the
10636 * targetNamespace value here.
10637 */
10638 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10639 "targetNamespace");
10640 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010641
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010642/* after_doc_loading: */
10643 if ((bkt == NULL) && located) {
10644 /* Only create a bucket if the schema was located. */
10645 bkt = xmlSchemaBucketCreate(pctxt, type,
10646 targetNamespace);
10647 if (bkt == NULL)
10648 goto exit_failure;
10649 }
10650 if (bkt != NULL) {
10651 bkt->schemaLocation = schemaLocation;
10652 bkt->located = located;
10653 if (doc != NULL) {
10654 bkt->doc = doc;
10655 bkt->targetNamespace = targetNamespace;
10656 bkt->origTargetNamespace = targetNamespace;
10657 if (preserveDoc)
10658 bkt->preserveDoc = 1;
10659 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010660 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010661 bkt->imported++;
10662 /*
10663 * Add it to the graph of schemas.
10664 */
10665 if (relation != NULL)
10666 relation->bucket = bkt;
10667 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010668
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010669exit:
10670 /*
10671 * Return the bucket explicitely; this is needed for the
10672 * main schema.
10673 */
10674 if (bucket != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010675 *bucket = bkt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010676 return (0);
10677
10678exit_error:
10679 if ((doc != NULL) && (! preserveDoc)) {
10680 xmlFreeDoc(doc);
10681 if (bkt != NULL)
10682 bkt->doc = NULL;
10683 }
10684 return(pctxt->err);
10685
10686exit_failure:
10687 if ((doc != NULL) && (! preserveDoc)) {
10688 xmlFreeDoc(doc);
10689 if (bkt != NULL)
10690 bkt->doc = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010691 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010692 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010693}
10694
William M. Brack2f2a6632004-08-20 23:09:47 +000010695/**
10696 * xmlSchemaParseImport:
10697 * @ctxt: a schema validation context
10698 * @schema: the schema being built
10699 * @node: a subtree containing XML Schema informations
10700 *
10701 * parse a XML schema Import definition
10702 * *WARNING* this interface is highly subject to change
10703 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010704 * Returns 0 in case of success, a positive error code if
10705 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010706 */
10707static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010708xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010709 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010710{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010711 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010712 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10713 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010714 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010715 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010716 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010717
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010718 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010719 return (-1);
10720
10721 /*
10722 * Check for illegal attributes.
10723 */
10724 attr = node->properties;
10725 while (attr != NULL) {
10726 if (attr->ns == NULL) {
10727 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10728 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10729 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010730 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010731 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010732 }
10733 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010734 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010736 }
10737 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010738 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010739 /*
10740 * Extract and validate attributes.
10741 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010742 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010743 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010744 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010745 xmlSchemaPSimpleTypeErr(pctxt,
10746 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010747 NULL, node,
10748 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010749 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010750 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010751 }
10752
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010753 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010754 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010755 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010756 xmlSchemaPSimpleTypeErr(pctxt,
10757 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010758 NULL, node,
10759 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Gauravf3d79412013-11-28 22:53:54 +080010760 NULL, schemaLocation, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010761 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010762 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010763 /*
10764 * And now for the children...
10765 */
10766 child = node->children;
10767 if (IS_SCHEMA(child, "annotation")) {
10768 /*
10769 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010770 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010771 */
10772 child = child->next;
10773 }
10774 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010775 xmlSchemaPContentErr(pctxt,
10776 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010777 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010778 "(annotation?)");
10779 }
10780 /*
10781 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010782 *
10783 * Note that it is important to use the original @targetNamespace
10784 * (or none at all), to rule out imports of schemas _with_ a
10785 * @targetNamespace if the importing schema is a chameleon schema
10786 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010787 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010788 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010789 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010790 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010010791 * 1.1 If the namespace [attribute] is present, then its `actual value`
10792 * must not match the `actual value` of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010793 * targetNamespace [attribute].
10794 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010795 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010796 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010797 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010798 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010799 "The value of the attribute 'namespace' must not match "
10800 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010801 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010802 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010803 }
10804 } else {
10805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010806 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010807 * <schema> must have a targetNamespace [attribute].
10808 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010809 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010810 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010811 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010812 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010813 "The attribute 'namespace' must be existent if "
10814 "the importing schema has no target namespace",
10815 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010816 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010817 }
10818 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010819 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010820 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010821 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010822 if (schemaLocation != NULL)
10823 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10824 schemaLocation, node);
10825 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010826 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010827 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010828
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010829 if (ret != 0)
10830 return(ret);
10831
10832 /*
10833 * For <import>: "It is *not* an error for the application
10834 * schema reference strategy to fail."
10835 * So just don't parse if no schema document was found.
10836 * Note that we will get no bucket if the schema could not be
10837 * located or if there was no schemaLocation.
10838 */
10839 if ((bucket == NULL) && (schemaLocation != NULL)) {
10840 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10841 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10842 node, NULL,
10843 "Failed to locate a schema at location '%s'. "
10844 "Skipping the import", schemaLocation, NULL, NULL);
10845 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010846
10847 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010848 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10849 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010850
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010851 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010852}
10853
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010854static int
10855xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10856 xmlSchemaPtr schema,
10857 xmlNodePtr node,
10858 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010859 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010860{
10861 xmlAttrPtr attr;
10862
10863 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10864 (schemaLocation == NULL))
10865 return (-1);
10866
10867 *schemaLocation = NULL;
10868 /*
10869 * Check for illegal attributes.
10870 * Applies for both <include> and <redefine>.
10871 */
10872 attr = node->properties;
10873 while (attr != NULL) {
10874 if (attr->ns == NULL) {
10875 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10876 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10877 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010879 }
10880 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10881 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010883 }
10884 attr = attr->next;
10885 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010886 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010887 /*
10888 * Preliminary step, extract the URI-Reference and make an URI
10889 * from the base.
10890 */
10891 /*
10892 * Attribute "schemaLocation" is mandatory.
10893 */
10894 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10895 if (attr != NULL) {
10896 xmlChar *base = NULL;
10897 xmlChar *uri = NULL;
10898
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010899 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10901 (const xmlChar **) schemaLocation) != 0)
10902 goto exit_error;
10903 base = xmlNodeGetBase(node->doc, node);
10904 if (base == NULL) {
10905 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10906 } else {
10907 uri = xmlBuildURI(*schemaLocation, base);
10908 xmlFree(base);
10909 }
10910 if (uri == NULL) {
10911 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10912 "could not build an URI from the schemaLocation")
10913 goto exit_failure;
10914 }
10915 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10916 xmlFree(uri);
10917 } else {
10918 xmlSchemaPMissingAttrErr(pctxt,
10919 XML_SCHEMAP_S4S_ATTR_MISSING,
10920 NULL, node, "schemaLocation", NULL);
10921 goto exit_error;
10922 }
10923 /*
10924 * Report self-inclusion and self-redefinition.
10925 */
10926 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010927 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010928 xmlSchemaPCustomErr(pctxt,
10929 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010930 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010931 "The schema document '%s' cannot redefine itself.",
Daniel Veillarddee23482008-04-11 12:58:43 +000010932 *schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010933 } else {
10934 xmlSchemaPCustomErr(pctxt,
10935 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010936 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010937 "The schema document '%s' cannot include itself.",
10938 *schemaLocation);
10939 }
10940 goto exit_error;
10941 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010942
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010943 return(0);
10944exit_error:
10945 return(pctxt->err);
10946exit_failure:
10947 return(-1);
10948}
10949
10950static int
10951xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10952 xmlSchemaPtr schema,
10953 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010954 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010955{
10956 xmlNodePtr child = NULL;
10957 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010958 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010959 int isChameleon = 0, wasChameleon = 0;
10960 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010961
10962 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10963 return (-1);
10964
10965 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010966 * Parse attributes. Note that the returned schemaLocation will
10967 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010968 */
10969 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010970 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010971 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000010972 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010973 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010974 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010975 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010976 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10977 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010978 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000010979 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010980 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010981 * If we get no schema bucket back, then this means that the schema
10982 * document could not be located or was broken XML or was not
10983 * a schema document.
Daniel Veillarddee23482008-04-11 12:58:43 +000010984 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010985 if ((bucket == NULL) || (bucket->doc == NULL)) {
10986 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10987 /*
10988 * WARNING for <include>:
10989 * We will raise an error if the schema cannot be located
10990 * for inclusions, since the that was the feedback from the
10991 * schema people. I.e. the following spec piece will *not* be
10992 * satisfied:
Jan Pokorný761c9e92013-11-29 23:26:27 +010010993 * SPEC src-include: "It is not an error for the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010994 * schemaLocation [attribute] to fail to resolve it all, in which
10995 * case no corresponding inclusion is performed.
10996 * So do we need a warning report here?"
10997 */
10998 res = XML_SCHEMAP_SRC_INCLUDE;
10999 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11000 node, NULL,
11001 "Failed to load the document '%s' for inclusion",
11002 schemaLocation, NULL);
11003 } else {
11004 /*
11005 * NOTE: This was changed to raise an error even if no redefinitions
11006 * are specified.
11007 *
11008 * SPEC src-redefine (1)
11009 * "If there are any element information items among the [children]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011010 * other than <annotation> then the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011011 * schemaLocation [attribute] must successfully resolve."
11012 * TODO: Ask the WG if a the location has always to resolve
11013 * here as well!
11014 */
11015 res = XML_SCHEMAP_SRC_REDEFINE;
11016 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11017 node, NULL,
11018 "Failed to load the document '%s' for redefinition",
11019 schemaLocation, NULL);
11020 }
11021 } else {
11022 /*
11023 * Check targetNamespace sanity before parsing the new schema.
11024 * TODO: Note that we won't check further content if the
11025 * targetNamespace was bad.
Daniel Veillarddee23482008-04-11 12:58:43 +000011026 */
11027 if (bucket->origTargetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011028 /*
11029 * SPEC src-include (2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010011030 * "SII has a targetNamespace [attribute], and its `actual
11031 * value` is identical to the `actual value` of the targetNamespace
11032 * [attribute] of SII' (which must have such an [attribute])."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011033 */
11034 if (pctxt->targetNamespace == NULL) {
11035 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11036 XML_SCHEMAP_SRC_INCLUDE,
11037 node, NULL,
11038 "The target namespace of the included/redefined schema "
11039 "'%s' has to be absent, since the including/redefining "
11040 "schema has no target namespace",
11041 schemaLocation, NULL);
11042 goto exit_error;
11043 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11044 pctxt->targetNamespace)) {
11045 /* TODO: Change error function. */
11046 xmlSchemaPCustomErrExt(pctxt,
11047 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011048 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011049 "The target namespace '%s' of the included/redefined "
11050 "schema '%s' differs from '%s' of the "
11051 "including/redefining schema",
11052 bucket->origTargetNamespace, schemaLocation,
11053 pctxt->targetNamespace);
11054 goto exit_error;
11055 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011056 } else if (pctxt->targetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011057 /*
11058 * Chameleons: the original target namespace will
11059 * differ from the resulting namespace.
11060 */
11061 isChameleon = 1;
11062 if (bucket->parsed &&
Jason Childsedc68aa2009-08-07 20:29:33 +020011063 bucket->origTargetNamespace != NULL) {
11064 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11065 XML_SCHEMAP_SRC_INCLUDE,
11066 node, NULL,
11067 "The target namespace of the included/redefined schema "
11068 "'%s' has to be absent or the same as the "
11069 "including/redefining schema's target namespace",
11070 schemaLocation, NULL);
11071 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011072 }
11073 bucket->targetNamespace = pctxt->targetNamespace;
11074 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011075 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011076 /*
11077 * Parse the schema.
Daniel Veillarddee23482008-04-11 12:58:43 +000011078 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011079 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11080 if (isChameleon) {
11081 /* TODO: Get rid of this flag on the schema itself. */
11082 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11083 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11084 } else
11085 wasChameleon = 1;
11086 }
11087 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11088 /* Restore chameleon flag. */
11089 if (isChameleon && (!wasChameleon))
11090 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11091 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011092 /*
11093 * And now for the children...
11094 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011095 child = node->children;
11096 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011097 /*
11098 * Parse (simpleType | complexType | group | attributeGroup))*
11099 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011100 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011101 /*
11102 * How to proceed if the redefined schema was not located?
11103 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011104 pctxt->isRedefine = 1;
11105 while (IS_SCHEMA(child, "annotation") ||
11106 IS_SCHEMA(child, "simpleType") ||
11107 IS_SCHEMA(child, "complexType") ||
11108 IS_SCHEMA(child, "group") ||
11109 IS_SCHEMA(child, "attributeGroup")) {
11110 if (IS_SCHEMA(child, "annotation")) {
11111 /*
11112 * TODO: discard or not?
11113 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011114 } else if (IS_SCHEMA(child, "simpleType")) {
11115 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11116 } else if (IS_SCHEMA(child, "complexType")) {
11117 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011118 /* hasRedefinitions = 1; */
Daniel Veillarddee23482008-04-11 12:58:43 +000011119 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011120 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011121 xmlSchemaParseModelGroupDefinition(pctxt,
11122 schema, child);
11123 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011124 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011125 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11126 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011127 }
11128 child = child->next;
11129 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011130 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011131 pctxt->isRedefine = 0;
11132 } else {
11133 if (IS_SCHEMA(child, "annotation")) {
11134 /*
11135 * TODO: discard or not?
11136 */
11137 child = child->next;
11138 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011139 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011140 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011141 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011142 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11143 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011144 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011145 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11146 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011147 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011148 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011149 "(annotation?)");
Daniel Veillarddee23482008-04-11 12:58:43 +000011150 }
11151 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011152 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011153
11154exit_error:
11155 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011156}
11157
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011158static int
11159xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11160 xmlNodePtr node)
11161{
11162 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011163#ifndef ENABLE_REDEFINE
11164 TODO
11165 return(0);
11166#endif
11167 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11168 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011169 if (res != 0)
11170 return(res);
11171 return(0);
11172}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011173
11174static int
11175xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11176 xmlNodePtr node)
11177{
11178 int res;
11179
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011180 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11181 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011182 if (res != 0)
11183 return(res);
11184 return(0);
11185}
11186
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011187/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011188 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011189 * @ctxt: a schema validation context
11190 * @schema: the schema being built
11191 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011192 * @type: the "compositor" type
11193 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011194 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011195 * parse a XML schema Sequence definition.
11196 * Applies parts of:
11197 * Schema Representation Constraint:
11198 * Redefinition Constraints and Semantics (src-redefine)
11199 * (6.1), (6.1.1), (6.1.2)
11200 *
Daniel Veillarddee23482008-04-11 12:58:43 +000011201 * Schema Component Constraint:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011202 * All Group Limited (cos-all-limited) (2)
11203 * TODO: Actually this should go to component-level checks,
11204 * but is done here due to performance. Move it to an other layer
11205 * is schema construction via an API is implemented.
11206 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011207 * *WARNING* this interface is highly subject to change
11208 *
William M. Bracke7091952004-05-11 15:09:58 +000011209 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011210 * 1 in case of success.
11211 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212static xmlSchemaTreeItemPtr
11213xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11214 xmlNodePtr node, xmlSchemaTypeType type,
11215 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011216{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011217 xmlSchemaModelGroupPtr item;
11218 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011219 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011220 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011221 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011222
11223 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011224 return (NULL);
11225 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011226 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011227 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011228 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 if (item == NULL)
11230 return (NULL);
11231
11232 if (withParticle) {
11233 if (type == XML_SCHEMA_TYPE_ALL) {
11234 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011235 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011236 } else {
11237 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011238 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11239 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11240 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011242 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11243 /*
11244 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011245 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000011246 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011248 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 particle->children = (xmlSchemaTreeItemPtr) item;
11250 /*
11251 * Check for illegal attributes.
11252 */
11253 attr = node->properties;
11254 while (attr != NULL) {
11255 if (attr->ns == NULL) {
11256 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11257 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11258 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011259 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011261 }
11262 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011263 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011265 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011267 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 } else {
11269 /*
11270 * Check for illegal attributes.
11271 */
11272 attr = node->properties;
11273 while (attr != NULL) {
11274 if (attr->ns == NULL) {
11275 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011276 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 }
11279 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011280 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 }
11283 attr = attr->next;
11284 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011285 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011286
William M. Brack2f2a6632004-08-20 23:09:47 +000011287 /*
11288 * Extract and validate attributes.
11289 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011290 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011291 /*
11292 * And now for the children...
11293 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011294 child = node->children;
11295 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011296 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011297 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011298 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 if (type == XML_SCHEMA_TYPE_ALL) {
11300 xmlSchemaParticlePtr part, last = NULL;
11301
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011302 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011303 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011304 schema, child, &isElemRef, 0);
11305 /*
11306 * SPEC cos-all-limited (2)
11307 * "The {max occurs} of all the particles in the {particles}
11308 * of the ('all') group must be 0 or 1.
11309 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011311 if (isElemRef)
11312 hasRefs++;
11313 if (part->minOccurs > 1) {
11314 xmlSchemaPCustomErr(ctxt,
11315 XML_SCHEMAP_COS_ALL_LIMITED,
11316 NULL, child,
11317 "Invalid value for minOccurs (must be 0 or 1)",
11318 NULL);
11319 /* Reset to 1. */
11320 part->minOccurs = 1;
11321 }
11322 if (part->maxOccurs > 1) {
11323 xmlSchemaPCustomErr(ctxt,
11324 XML_SCHEMAP_COS_ALL_LIMITED,
11325 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011326 "Invalid value for maxOccurs (must be 0 or 1)",
11327 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011328 /* Reset to 1. */
11329 part->maxOccurs = 1;
11330 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011331 if (last == NULL)
11332 item->children = (xmlSchemaTreeItemPtr) part;
11333 else
11334 last->next = (xmlSchemaTreeItemPtr) part;
11335 last = part;
11336 }
11337 child = child->next;
11338 }
11339 if (child != NULL) {
11340 xmlSchemaPContentErr(ctxt,
11341 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011342 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011343 "(annotation?, (annotation?, element*)");
11344 }
11345 } else {
11346 /* choice + sequence */
11347 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11348
11349 while ((IS_SCHEMA(child, "element")) ||
11350 (IS_SCHEMA(child, "group")) ||
11351 (IS_SCHEMA(child, "any")) ||
11352 (IS_SCHEMA(child, "choice")) ||
11353 (IS_SCHEMA(child, "sequence"))) {
11354
11355 if (IS_SCHEMA(child, "element")) {
11356 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011357 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11358 if (part && isElemRef)
11359 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011360 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011361 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011363 if (part != NULL)
11364 hasRefs++;
11365 /*
11366 * Handle redefinitions.
11367 */
11368 if (ctxt->isRedefine && ctxt->redef &&
11369 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11370 part && part->children)
11371 {
11372 if ((xmlSchemaGetQNameRefName(part->children) ==
11373 ctxt->redef->refName) &&
11374 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11375 ctxt->redef->refTargetNs))
11376 {
11377 /*
11378 * SPEC src-redefine:
11379 * (6.1) "If it has a <group> among its contents at
Jan Pokorný761c9e92013-11-29 23:26:27 +010011380 * some level the `actual value` of whose ref
11381 * [attribute] is the same as the `actual value` of
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011382 * its own name attribute plus target namespace, then
11383 * all of the following must be true:"
11384 * (6.1.1) "It must have exactly one such group."
11385 */
11386 if (ctxt->redefCounter != 0) {
11387 xmlChar *str = NULL;
11388
11389 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391 "The redefining model group definition "
11392 "'%s' must not contain more than one "
11393 "reference to the redefined definition",
11394 xmlSchemaFormatQName(&str,
11395 ctxt->redef->refTargetNs,
11396 ctxt->redef->refName),
11397 NULL);
11398 FREE_AND_NULL(str)
11399 part = NULL;
11400 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11401 ((WXS_PARTICLE(part))->maxOccurs != 1))
11402 {
11403 xmlChar *str = NULL;
11404 /*
11405 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010011406 * (6.1.2) "The `actual value` of both that
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011407 * group's minOccurs and maxOccurs [attribute]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011408 * must be 1 (or `absent`).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011409 */
11410 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11411 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11412 "The redefining model group definition "
11413 "'%s' must not contain a reference to the "
11414 "redefined definition with a "
11415 "maxOccurs/minOccurs other than 1",
11416 xmlSchemaFormatQName(&str,
11417 ctxt->redef->refTargetNs,
11418 ctxt->redef->refName),
11419 NULL);
11420 FREE_AND_NULL(str)
11421 part = NULL;
11422 }
11423 ctxt->redef->reference = WXS_BASIC_CAST part;
11424 ctxt->redefCounter++;
Daniel Veillarddee23482008-04-11 12:58:43 +000011425 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011426 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011427 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011428 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011429 xmlSchemaParseAny(ctxt, schema, child);
11430 } else if (IS_SCHEMA(child, "choice")) {
11431 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11432 XML_SCHEMA_TYPE_CHOICE, 1);
11433 } else if (IS_SCHEMA(child, "sequence")) {
11434 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11435 XML_SCHEMA_TYPE_SEQUENCE, 1);
11436 }
11437 if (part != NULL) {
11438 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011439 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011440 else
11441 last->next = part;
11442 last = part;
11443 }
11444 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011445 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011446 if (child != NULL) {
11447 xmlSchemaPContentErr(ctxt,
11448 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011449 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011450 "(annotation?, (element | group | choice | sequence | any)*)");
11451 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011452 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011453 if ((max == 0) && (min == 0))
11454 return (NULL);
11455 if (hasRefs) {
11456 /*
11457 * We need to resolve references.
11458 */
11459 WXS_ADD_PENDING(ctxt, item);
11460 }
11461 if (withParticle)
Daniel Veillarddee23482008-04-11 12:58:43 +000011462 return ((xmlSchemaTreeItemPtr) particle);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011463 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011464 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011465}
11466
11467/**
11468 * xmlSchemaParseRestriction:
11469 * @ctxt: a schema validation context
11470 * @schema: the schema being built
11471 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011472 *
11473 * parse a XML schema Restriction definition
11474 * *WARNING* this interface is highly subject to change
11475 *
11476 * Returns the type definition or NULL in case of error
11477 */
11478static xmlSchemaTypePtr
11479xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011480 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011481{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011482 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011483 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011484 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011485
11486 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11487 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011488 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011489 type = ctxt->ctxtType;
11490 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011491
11492 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011493 * Check for illegal attributes.
11494 */
11495 attr = node->properties;
11496 while (attr != NULL) {
11497 if (attr->ns == NULL) {
11498 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11499 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011500 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011501 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011502 }
11503 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011504 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011505 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011506 }
11507 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011508 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011509 /*
11510 * Extract and validate attributes.
11511 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011512 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011513 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000011514 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011515 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011516 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011517 * Extract the base type. The "base" attribute is mandatory if inside
11518 * a complex type or if redefining.
11519 *
11520 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521 * among its [children]), the simple type definition which is
Jan Pokorný761c9e92013-11-29 23:26:27 +010011522 * the {content type} of the type definition `resolved` to by
11523 * the `actual value` of the base [attribute]"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011525 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011526 &(type->baseNs), &(type->base)) == 0)
11527 {
11528 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11529 xmlSchemaPMissingAttrErr(ctxt,
11530 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011531 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011532 } else if ((ctxt->isRedefine) &&
11533 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11534 {
11535 if (type->base == NULL) {
11536 xmlSchemaPMissingAttrErr(ctxt,
11537 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011538 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011539 } else if ((! xmlStrEqual(type->base, type->name)) ||
11540 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11541 {
11542 xmlChar *str1 = NULL, *str2 = NULL;
11543 /*
11544 * REDEFINE: SPEC src-redefine (5)
11545 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +010011546 * <restriction> among its [children] ... the `actual value` of
11547 * whose base [attribute] must be the same as the `actual value`
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011548 * of its own name attribute plus target namespace;"
11549 */
11550 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011551 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011552 "value '%s' of the 'base' attribute does not match the "
11553 "type's designation '%s'",
11554 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
Daniel Veillardfef73a52006-03-27 09:38:57 +000011555 xmlSchemaFormatQName(&str2, type->targetNamespace,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011556 type->name), NULL);
11557 FREE_AND_NULL(str1);
11558 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011559 /* Avoid confusion and erase the values. */
11560 type->base = NULL;
11561 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011562 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011564 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011565 /*
11566 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011567 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011568 child = node->children;
11569 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011570 /*
11571 * Add the annotation to the simple type ancestor.
11572 */
11573 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011574 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011575 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011577 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11578 /*
11579 * Corresponds to <simpleType><restriction><simpleType>.
11580 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011581 if (IS_SCHEMA(child, "simpleType")) {
11582 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011583 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011584 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585 * Either the base [attribute] or the simpleType [child] of the
11586 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011589 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011590 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011591 "The attribute 'base' and the <simpleType> child are "
11592 "mutually exclusive", NULL);
11593 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011594 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011595 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011596 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011597 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011601 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011602 "Either the attribute 'base' or a <simpleType> child "
11603 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011605 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11606 /*
11607 * Corresponds to <complexType><complexContent><restriction>...
11608 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011609 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011610 * Model groups <all>, <choice> and <sequence>.
11611 */
11612 if (IS_SCHEMA(child, "all")) {
11613 type->subtypes = (xmlSchemaTypePtr)
11614 xmlSchemaParseModelGroup(ctxt, schema, child,
11615 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011616 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011617 } else if (IS_SCHEMA(child, "choice")) {
11618 type->subtypes = (xmlSchemaTypePtr)
11619 xmlSchemaParseModelGroup(ctxt,
11620 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11621 child = child->next;
11622 } else if (IS_SCHEMA(child, "sequence")) {
11623 type->subtypes = (xmlSchemaTypePtr)
11624 xmlSchemaParseModelGroup(ctxt, schema, child,
11625 XML_SCHEMA_TYPE_SEQUENCE, 1);
11626 child = child->next;
11627 /*
11628 * Model group reference <group>.
11629 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011630 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011631 type->subtypes = (xmlSchemaTypePtr)
11632 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011633 /*
11634 * Note that the reference will be resolved in
11635 * xmlSchemaResolveTypeReferences();
11636 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011637 child = child->next;
11638 }
11639 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011640 /*
11641 * Corresponds to <complexType><simpleContent><restriction>...
11642 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011643 * "1.1 the simple type definition corresponding to the <simpleType>
11644 * among the [children] of <restriction> if there is one;"
11645 */
11646 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011647 /*
11648 * We will store the to-be-restricted simple type in
11649 * type->contentTypeDef *temporarily*.
11650 */
11651 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011652 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011653 if ( type->contentTypeDef == NULL)
11654 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011655 child = child->next;
11656 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011657 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011658
11659 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011660 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011661 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011662 /*
11663 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011664 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011665 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011666
Daniel Veillard01fa6152004-06-29 17:04:39 +000011667 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011668 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011669 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011670 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011671 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11672 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011673 * *Single Facet Value*
11674 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011675 while ((IS_SCHEMA(child, "minInclusive")) ||
11676 (IS_SCHEMA(child, "minExclusive")) ||
11677 (IS_SCHEMA(child, "maxInclusive")) ||
11678 (IS_SCHEMA(child, "maxExclusive")) ||
11679 (IS_SCHEMA(child, "totalDigits")) ||
11680 (IS_SCHEMA(child, "fractionDigits")) ||
11681 (IS_SCHEMA(child, "pattern")) ||
11682 (IS_SCHEMA(child, "enumeration")) ||
11683 (IS_SCHEMA(child, "whiteSpace")) ||
11684 (IS_SCHEMA(child, "length")) ||
11685 (IS_SCHEMA(child, "maxLength")) ||
11686 (IS_SCHEMA(child, "minLength"))) {
11687 facet = xmlSchemaParseFacet(ctxt, schema, child);
11688 if (facet != NULL) {
11689 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011690 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011691 else
11692 lastfacet->next = facet;
11693 lastfacet = facet;
11694 lastfacet->next = NULL;
11695 }
11696 child = child->next;
11697 }
11698 /*
11699 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011700 */
11701 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011702 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11703
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011704 facet = type->facets;
11705 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011706 facetLink = (xmlSchemaFacetLinkPtr)
11707 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011708 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011709 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011710 xmlFree(facetLink);
11711 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011712 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011713 facetLink->facet = facet;
11714 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011715 if (lastFacetLink == NULL)
11716 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011717 else
11718 lastFacetLink->next = facetLink;
11719 lastFacetLink = facetLink;
11720 facet = facet->next;
11721 } while (facet != NULL);
11722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011723 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11725 /*
11726 * Attribute uses/declarations.
11727 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011728 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11729 (xmlSchemaItemListPtr *) &(type->attrUses),
11730 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11731 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011732 /*
11733 * Attribute wildcard.
11734 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011735 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011736 type->attributeWildcard =
11737 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011738 child = child->next;
11739 }
11740 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011741 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11743 xmlSchemaPContentErr(ctxt,
11744 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011745 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011746 "annotation?, (group | all | choice | sequence)?, "
11747 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011748 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 xmlSchemaPContentErr(ctxt,
11750 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011751 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011752 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11753 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11754 "length | minLength | maxLength | enumeration | whiteSpace | "
11755 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11756 } else {
11757 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011758 xmlSchemaPContentErr(ctxt,
11759 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011760 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011761 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11762 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11763 "length | minLength | maxLength | enumeration | whiteSpace | "
11764 "pattern)*))");
11765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011766 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011767 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011768}
11769
11770/**
11771 * xmlSchemaParseExtension:
11772 * @ctxt: a schema validation context
11773 * @schema: the schema being built
11774 * @node: a subtree containing XML Schema informations
11775 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011776 * Parses an <extension>, which is found inside a
11777 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011778 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011779 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011780 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011781 */
11782static xmlSchemaTypePtr
11783xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011784 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011785{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011786 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011787 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011788 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011789
11790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11791 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011792 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011793 type = ctxt->ctxtType;
11794 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011795
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011796 /*
11797 * Check for illegal attributes.
11798 */
11799 attr = node->properties;
11800 while (attr != NULL) {
11801 if (attr->ns == NULL) {
11802 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11803 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011804 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011806 }
11807 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011808 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011809 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011810 }
11811 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011812 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011813
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011814 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011815
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011816 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011817 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011818 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011819 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11820 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011821 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011822 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011823 XML_SCHEMAP_S4S_ATTR_MISSING,
11824 NULL, node, "base", NULL);
11825 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011826 /*
11827 * And now for the children...
11828 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011829 child = node->children;
11830 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011831 /*
11832 * Add the annotation to the type ancestor.
11833 */
11834 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011835 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011836 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011837 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011838 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11839 /*
11840 * Corresponds to <complexType><complexContent><extension>... and:
11841 *
11842 * Model groups <all>, <choice>, <sequence> and <group>.
11843 */
11844 if (IS_SCHEMA(child, "all")) {
11845 type->subtypes = (xmlSchemaTypePtr)
11846 xmlSchemaParseModelGroup(ctxt, schema,
11847 child, XML_SCHEMA_TYPE_ALL, 1);
11848 child = child->next;
11849 } else if (IS_SCHEMA(child, "choice")) {
11850 type->subtypes = (xmlSchemaTypePtr)
11851 xmlSchemaParseModelGroup(ctxt, schema,
11852 child, XML_SCHEMA_TYPE_CHOICE, 1);
11853 child = child->next;
11854 } else if (IS_SCHEMA(child, "sequence")) {
11855 type->subtypes = (xmlSchemaTypePtr)
11856 xmlSchemaParseModelGroup(ctxt, schema,
11857 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11858 child = child->next;
11859 } else if (IS_SCHEMA(child, "group")) {
11860 type->subtypes = (xmlSchemaTypePtr)
11861 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011862 /*
11863 * Note that the reference will be resolved in
11864 * xmlSchemaResolveTypeReferences();
11865 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011866 child = child->next;
11867 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011868 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011869 if (child != NULL) {
11870 /*
11871 * Attribute uses/declarations.
11872 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011873 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11874 (xmlSchemaItemListPtr *) &(type->attrUses),
11875 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11876 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011877 /*
11878 * Attribute wildcard.
11879 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011880 if (IS_SCHEMA(child, "anyAttribute")) {
11881 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011882 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11883 child = child->next;
11884 }
11885 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011886 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011887 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11888 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011889 xmlSchemaPContentErr(ctxt,
11890 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011891 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011892 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011893 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011894 } else {
11895 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011896 xmlSchemaPContentErr(ctxt,
11897 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011898 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011899 "(annotation?, ((attribute | attributeGroup)*, "
11900 "anyAttribute?))");
11901 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011902 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011903 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011904}
11905
11906/**
11907 * xmlSchemaParseSimpleContent:
11908 * @ctxt: a schema validation context
11909 * @schema: the schema being built
11910 * @node: a subtree containing XML Schema informations
11911 *
11912 * parse a XML schema SimpleContent definition
11913 * *WARNING* this interface is highly subject to change
11914 *
11915 * Returns the type definition or NULL in case of error
11916 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011917static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011918xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011919 xmlSchemaPtr schema, xmlNodePtr node,
11920 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011921{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011922 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011923 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011924 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011925
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011926 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11927 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011928 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011929 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011930 /* Not a component, don't create it. */
11931 type = ctxt->ctxtType;
11932 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11933 /*
11934 * Check for illegal attributes.
11935 */
11936 attr = node->properties;
11937 while (attr != NULL) {
11938 if (attr->ns == NULL) {
11939 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011940 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011941 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011942 }
11943 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011945 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011946 }
11947 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011948 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011949
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011950 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011951
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011952 /*
11953 * And now for the children...
11954 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011955 child = node->children;
11956 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011957 /*
11958 * Add the annotation to the complex type ancestor.
11959 */
11960 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011961 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011962 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011963 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011964 if (child == NULL) {
11965 xmlSchemaPContentErr(ctxt,
11966 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011967 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000011968 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011969 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011970 if (child == NULL) {
11971 xmlSchemaPContentErr(ctxt,
11972 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011973 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000011974 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011975 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011976 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011977 xmlSchemaParseRestriction(ctxt, schema, child,
11978 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011979 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011980 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011981 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011982 xmlSchemaParseExtension(ctxt, schema, child,
11983 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011984 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011985 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011986 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 if (child != NULL) {
11988 xmlSchemaPContentErr(ctxt,
11989 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011990 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011991 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011992 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011993 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011994}
11995
11996/**
11997 * xmlSchemaParseComplexContent:
11998 * @ctxt: a schema validation context
11999 * @schema: the schema being built
12000 * @node: a subtree containing XML Schema informations
12001 *
12002 * parse a XML schema ComplexContent definition
12003 * *WARNING* this interface is highly subject to change
12004 *
12005 * Returns the type definition or NULL in case of error
12006 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012007static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012008xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012009 xmlSchemaPtr schema, xmlNodePtr node,
12010 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000012011{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012012 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012013 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012014 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000012015
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012016 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012018 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012019 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012020 /* Not a component, don't create it. */
12021 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012022 /*
12023 * Check for illegal attributes.
12024 */
12025 attr = node->properties;
12026 while (attr != NULL) {
12027 if (attr->ns == NULL) {
12028 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012030 {
12031 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012032 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012033 }
12034 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12035 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012036 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012037 }
12038 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012039 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012040
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012041 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012042
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012043 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012044 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012045 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012046 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012047 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12048 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012049 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012050 child = node->children;
12051 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012052 /*
12053 * Add the annotation to the complex type ancestor.
12054 */
12055 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012056 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012057 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012058 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012059 if (child == NULL) {
12060 xmlSchemaPContentErr(ctxt,
12061 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012062 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012063 NULL, "(annotation?, (restriction | extension))");
12064 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012065 if (child == NULL) {
12066 xmlSchemaPContentErr(ctxt,
12067 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012068 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012069 NULL, "(annotation?, (restriction | extension))");
12070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012071 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012072 xmlSchemaParseRestriction(ctxt, schema, child,
12073 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012074 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012075 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012076 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012077 xmlSchemaParseExtension(ctxt, schema, child,
12078 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012079 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012080 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012081 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012082 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012083 xmlSchemaPContentErr(ctxt,
12084 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012085 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012086 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012088 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012089}
12090
12091/**
12092 * xmlSchemaParseComplexType:
12093 * @ctxt: a schema validation context
12094 * @schema: the schema being built
12095 * @node: a subtree containing XML Schema informations
12096 *
12097 * parse a XML schema Complex Type definition
12098 * *WARNING* this interface is highly subject to change
12099 *
12100 * Returns the type definition or NULL in case of error
12101 */
12102static xmlSchemaTypePtr
12103xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012104 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012105{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012106 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012107 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012108 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012109 xmlAttrPtr attr;
12110 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012111#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012112 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012113#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012114 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012115
Daniel Veillard4255d502002-04-16 15:50:10 +000012116
12117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12118 return (NULL);
12119
Daniel Veillard01fa6152004-06-29 17:04:39 +000012120 ctxtType = ctxt->ctxtType;
12121
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012122 if (topLevel) {
12123 attr = xmlSchemaGetPropNode(node, "name");
12124 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012125 xmlSchemaPMissingAttrErr(ctxt,
12126 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012127 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012128 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012129 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12130 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012131 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012132 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012133
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012134 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012135 /*
12136 * Parse as local complex type definition.
12137 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012138#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012139 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012140 type = xmlSchemaAddType(ctxt, schema,
12141 XML_SCHEMA_TYPE_COMPLEX,
12142 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012143 ctxt->targetNamespace, node, 0);
12144#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012145 type = xmlSchemaAddType(ctxt, schema,
12146 XML_SCHEMA_TYPE_COMPLEX,
12147 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012148#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012149 if (type == NULL)
12150 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012151 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012152 type->node = node;
12153 type->type = XML_SCHEMA_TYPE_COMPLEX;
12154 /*
12155 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012156 */
12157 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012158 /*
12159 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012160 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012161 type = xmlSchemaAddType(ctxt, schema,
12162 XML_SCHEMA_TYPE_COMPLEX,
12163 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012164 if (type == NULL)
12165 return (NULL);
12166 type->node = node;
12167 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012168 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012169 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012170 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012171 /*
12172 * Handle attributes.
12173 */
12174 attr = node->properties;
12175 while (attr != NULL) {
12176 if (attr->ns == NULL) {
12177 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12178 /*
12179 * Attribute "id".
12180 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012181 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012182 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12183 /*
12184 * Attribute "mixed".
12185 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012186 if (xmlSchemaPGetBoolNodeValue(ctxt,
12187 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12189 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012190 /*
12191 * Attributes of global complex type definitions.
12192 */
12193 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12194 /* Pass. */
12195 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12196 /*
12197 * Attribute "abstract".
12198 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012199 if (xmlSchemaPGetBoolNodeValue(ctxt,
12200 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012201 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12202 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12203 /*
12204 * Attribute "final".
12205 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012206 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012207 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012208 if (xmlSchemaPValAttrBlockFinal(attrValue,
12209 &(type->flags),
12210 -1,
12211 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12212 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12213 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012214 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012215 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012216 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012217 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012218 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012219 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012220 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012221 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012222 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12223 /*
12224 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012225 */
12226 attrValue = xmlSchemaGetNodeContent(ctxt,
12227 (xmlNodePtr) attr);
12228 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012229 -1,
12230 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012231 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012232 -1, -1, -1) != 0) {
12233 xmlSchemaPSimpleTypeErr(ctxt,
12234 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012235 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012237 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012238 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012239 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012240 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012243 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012244 } else {
12245 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012247 }
12248 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012249 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012250 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012251 }
12252 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012253 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012254 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012255 /*
12256 * Apply default "block" values.
12257 */
12258 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12259 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12260 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12261 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12262 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012263 if (! final) {
12264 /*
12265 * Apply default "block" values.
12266 */
12267 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12268 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12269 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12270 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12271 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012272 /*
12273 * And now for the children...
12274 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012275 child = node->children;
12276 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012277 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012278 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012279 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012280 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012281 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012282 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012283 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012285 * Specifying mixed='true' when the <simpleContent>
12286 * alternative is chosen has no effect
12287 */
William M. Bracke7091952004-05-11 15:09:58 +000012288 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12289 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012290 xmlSchemaParseSimpleContent(ctxt, schema, child,
12291 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012293 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012294 /*
12295 * <complexType><complexContent>...
12296 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012297 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012298 xmlSchemaParseComplexContent(ctxt, schema, child,
12299 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012301 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012302 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012303 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12304 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012305 * SPEC
12306 * "...the third alternative (neither <simpleContent> nor
12307 * <complexContent>) is chosen. This case is understood as shorthand
Jan Pokorný761c9e92013-11-29 23:26:27 +010012308 * for complex content restricting the `ur-type definition`, and the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012309 * details of the mappings should be modified as necessary.
12310 */
12311 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12312 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012313 /*
12314 * Parse model groups.
12315 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012316 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012317 type->subtypes = (xmlSchemaTypePtr)
12318 xmlSchemaParseModelGroup(ctxt, schema, child,
12319 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012320 child = child->next;
12321 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012322 type->subtypes = (xmlSchemaTypePtr)
12323 xmlSchemaParseModelGroup(ctxt, schema, child,
12324 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012325 child = child->next;
12326 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012327 type->subtypes = (xmlSchemaTypePtr)
12328 xmlSchemaParseModelGroup(ctxt, schema, child,
12329 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012330 child = child->next;
12331 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012332 type->subtypes = (xmlSchemaTypePtr)
12333 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012334 /*
12335 * Note that the reference will be resolved in
12336 * xmlSchemaResolveTypeReferences();
12337 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012338 child = child->next;
12339 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012340 /*
12341 * Parse attribute decls/refs.
12342 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012343 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12344 (xmlSchemaItemListPtr *) &(type->attrUses),
12345 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12346 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012347 /*
12348 * Parse attribute wildcard.
12349 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012350 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012351 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12352 child = child->next;
12353 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012354 }
12355 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012356 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012357 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012358 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012359 NULL, "(annotation?, (simpleContent | complexContent | "
12360 "((group | all | choice | sequence)?, ((attribute | "
12361 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012362 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012363 /*
12364 * REDEFINE: SPEC src-redefine (5)
12365 */
12366 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12367 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012368 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012369 "<complexType> must have a <restriction> or <extension> "
12370 "grand-child", NULL);
12371 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012372 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012373 return (type);
12374}
12375
Daniel Veillard4255d502002-04-16 15:50:10 +000012376/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012377 * *
12378 * Validating using Schemas *
12379 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012380 ************************************************************************/
12381
12382/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012383 * *
12384 * Reading/Writing Schemas *
12385 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012386 ************************************************************************/
12387
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012388#if 0 /* Will be enabled if it is clear what options are needed. */
12389/**
12390 * xmlSchemaParserCtxtSetOptions:
12391 * @ctxt: a schema parser context
12392 * @options: a combination of xmlSchemaParserOption
12393 *
12394 * Sets the options to be used during the parse.
12395 *
12396 * Returns 0 in case of success, -1 in case of an
12397 * API error.
12398 */
12399static int
12400xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12401 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012403{
12404 int i;
12405
12406 if (ctxt == NULL)
12407 return (-1);
12408 /*
12409 * WARNING: Change the start value if adding to the
12410 * xmlSchemaParseOption.
12411 */
12412 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12413 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414 return (-1);
12415 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 }
12417 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012418 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012419}
12420
12421/**
12422 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012423 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012424 *
12425 * Returns the option combination of the parser context.
12426 */
12427static int
12428xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012429
12430{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012431 if (ctxt == NULL)
12432 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012433 else
12434 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012436#endif
12437
Daniel Veillard4255d502002-04-16 15:50:10 +000012438/**
12439 * xmlSchemaNewParserCtxt:
12440 * @URL: the location of the schema
12441 *
12442 * Create an XML Schemas parse context for that file/resource expected
12443 * to contain an XML Schemas file.
12444 *
12445 * Returns the parser context or NULL in case of error
12446 */
12447xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012448xmlSchemaNewParserCtxt(const char *URL)
12449{
Daniel Veillard4255d502002-04-16 15:50:10 +000012450 xmlSchemaParserCtxtPtr ret;
12451
12452 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012453 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012454
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012455 ret = xmlSchemaParserCtxtCreate();
12456 if (ret == NULL)
12457 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012458 ret->dict = xmlDictCreate();
12459 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012460 return (ret);
12461}
12462
12463/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012464 * xmlSchemaNewMemParserCtxt:
12465 * @buffer: a pointer to a char array containing the schemas
12466 * @size: the size of the array
12467 *
12468 * Create an XML Schemas parse context for that memory buffer expected
12469 * to contain an XML Schemas file.
12470 *
12471 * Returns the parser context or NULL in case of error
12472 */
12473xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012474xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12475{
Daniel Veillard6045c902002-10-09 21:13:59 +000012476 xmlSchemaParserCtxtPtr ret;
12477
12478 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012479 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012480 ret = xmlSchemaParserCtxtCreate();
12481 if (ret == NULL)
12482 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012483 ret->buffer = buffer;
12484 ret->size = size;
Daniel Veillarddee23482008-04-11 12:58:43 +000012485 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012486 return (ret);
12487}
12488
12489/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012490 * xmlSchemaNewDocParserCtxt:
12491 * @doc: a preparsed document tree
12492 *
12493 * Create an XML Schemas parse context for that document.
12494 * NB. The document may be modified during the parsing process.
12495 *
12496 * Returns the parser context or NULL in case of error
12497 */
12498xmlSchemaParserCtxtPtr
12499xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12500{
12501 xmlSchemaParserCtxtPtr ret;
12502
12503 if (doc == NULL)
12504 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012505 ret = xmlSchemaParserCtxtCreate();
12506 if (ret == NULL)
12507 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012508 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012509 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012510 /* The application has responsibility for the document */
12511 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012512
12513 return (ret);
12514}
12515
12516/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012517 * xmlSchemaFreeParserCtxt:
12518 * @ctxt: the schema parser context
12519 *
12520 * Free the resources associated to the schema parser context
12521 */
12522void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012523xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12524{
Daniel Veillard4255d502002-04-16 15:50:10 +000012525 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012526 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012527 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillarddee23482008-04-11 12:58:43 +000012528 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012529 if (ctxt->vctxt != NULL) {
12530 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12531 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012532 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12533 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12534 ctxt->constructor = NULL;
12535 ctxt->ownsConstructor = 0;
12536 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012537 if (ctxt->attrProhibs != NULL)
12538 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012539 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012540 xmlFree(ctxt);
12541}
12542
12543/************************************************************************
12544 * *
12545 * Building the content models *
12546 * *
12547 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012548
Daniel Veillard4013e832009-08-26 17:24:31 +020012549/**
12550 * xmlSchemaBuildContentModelForSubstGroup:
12551 *
12552 * Returns 1 if nillable, 0 otherwise
12553 */
12554static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012555xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012556 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012557{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012558 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012559 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012560 xmlSchemaSubstGroupPtr substGroup;
12561 int i;
Daniel Veillard4013e832009-08-26 17:24:31 +020012562 int ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012563
12564 elemDecl = (xmlSchemaElementPtr) particle->children;
12565 /*
12566 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012568 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012569 if (end == NULL)
12570 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012571 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012572 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012573 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012574 XML_SCHEMAP_INTERNAL,
12575 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12576 "declaration is marked having a subst. group but none "
12577 "available.\n", elemDecl->name, NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020012578 return(0);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012579 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012580 if (counter >= 0) {
12581 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012582 * NOTE that we put the declaration in, even if it's abstract.
12583 * However, an error will be raised during *validation* if an element
12584 * information item shall be validated against an abstract element
12585 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012586 */
12587 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12588 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12589 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12590 /*
12591 * Add subst. group members.
12592 */
12593 for (i = 0; i < substGroup->members->nbItems; i++) {
12594 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12595 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12596 member->name, member->targetNamespace, member);
12597 }
12598 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012599 /*
12600 * NOTE that we put the declaration in, even if it's abstract,
12601 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012603 xmlAutomataNewTransition2(pctxt->am,
12604 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012605 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12606 /*
12607 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012609 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012610 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012611 /*
12612 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12613 * was incorrectly used instead of xmlAutomataNewTransition2()
12614 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12615 * section in xmlSchemaBuildAContentModel() ).
Daniel Veillarddee23482008-04-11 12:58:43 +000012616 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012617 * intended for the above "counter" section originally. I.e.,
12618 * check xs:all with subst-groups.
12619 *
12620 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12621 * member->name, member->targetNamespace,
12622 * 1, 1, member);
12623 */
12624 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012625 member->name, member->targetNamespace, member);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012626 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012627 }
12628 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012629 xmlAutomataStatePtr hop;
12630 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12631 UNBOUNDED : particle->maxOccurs - 1;
12632 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12633
12634 counter =
12635 xmlAutomataNewCounter(pctxt->am, minOccurs,
12636 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012638
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012639 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012640 xmlAutomataNewTransition2(pctxt->am,
12641 start, NULL,
12642 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012643 hop);
12644 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012645 * Add subst. group members.
12646 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012647 for (i = 0; i < substGroup->members->nbItems; i++) {
12648 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12649 xmlAutomataNewEpsilon(pctxt->am,
12650 xmlAutomataNewTransition2(pctxt->am,
12651 start, NULL,
12652 member->name, member->targetNamespace, member),
12653 hop);
12654 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012655 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12656 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12657 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012658 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012659 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012660 ret = 1;
12661 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 pctxt->state = end;
Daniel Veillard4013e832009-08-26 17:24:31 +020012663 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012664}
12665
Daniel Veillard4013e832009-08-26 17:24:31 +020012666/**
12667 * xmlSchemaBuildContentModelForElement:
12668 *
12669 * Returns 1 if nillable, 0 otherwise
12670 */
12671static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012672xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12673 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674{
Daniel Veillard4013e832009-08-26 17:24:31 +020012675 int ret = 0;
12676
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012677 if (((xmlSchemaElementPtr) particle->children)->flags &
12678 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012679 /*
12680 * Substitution groups.
12681 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012682 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012683 } else {
12684 xmlSchemaElementPtr elemDecl;
12685 xmlAutomataStatePtr start;
12686
12687 elemDecl = (xmlSchemaElementPtr) particle->children;
12688
12689 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillard4013e832009-08-26 17:24:31 +020012690 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012691 if (particle->maxOccurs == 1) {
12692 start = ctxt->state;
12693 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012694 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12695 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12696 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012697 /* Special case. */
Daniel Veillarddee23482008-04-11 12:58:43 +000012698 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012699 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012700 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012701 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
Daniel Veillarddee23482008-04-11 12:58:43 +000012702 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012703 } else {
12704 int counter;
12705 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12706 UNBOUNDED : particle->maxOccurs - 1;
12707 int minOccurs = particle->minOccurs < 1 ?
12708 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012709
12710 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012711 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12712 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12713 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12714 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12715 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12716 NULL, counter);
12717 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012718 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012719 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
Daniel Veillard4013e832009-08-26 17:24:31 +020012720 ret = 1;
12721 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012722 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012723 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012724}
12725
Daniel Veillard4255d502002-04-16 15:50:10 +000012726/**
12727 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012728 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012729 * @particle: the particle component
12730 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012731 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012732 * Create the automaton for the {content type} of a complex type.
12733 *
Daniel Veillard4013e832009-08-26 17:24:31 +020012734 * Returns 1 if the content is nillable, 0 otherwise
Daniel Veillard4255d502002-04-16 15:50:10 +000012735 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012736static int
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012738 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012739{
Daniel Veillard4013e832009-08-26 17:24:31 +020012740 int ret = 0, tmp2;
12741
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012742 if (particle == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012743 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Daniel Veillard4013e832009-08-26 17:24:31 +020012744 return(1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012745 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012746 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012747 /*
12748 * Just return in this case. A missing "term" of the particle
12749 * might arise due to an invalid "term" component.
12750 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012751 return(1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012752 }
12753
12754 switch (particle->children->type) {
12755 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012756 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012757 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012758 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012759
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012760 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012761
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012762 start = pctxt->state;
12763 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012764
12765 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012766 if (wild->any == 1) {
12767 /*
12768 * We need to add both transitions:
12769 *
12770 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012771 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012772 pctxt->state =
12773 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012774 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012775 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012776 /*
12777 * 2. the {"*"} for elements in no namespace.
12778 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012779 pctxt->state =
12780 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012781 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012782 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012783
12784 } else if (wild->nsSet != NULL) {
12785 ns = wild->nsSet;
12786 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012787 pctxt->state = start;
12788 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12789 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12790 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012791 ns = ns->next;
12792 } while (ns != NULL);
12793
12794 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012795 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12796 start, end, BAD_CAST "*", wild->negNsSet->value,
12797 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012798 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012799 } else {
12800 int counter;
12801 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012802 int maxOccurs =
Daniel Veillard4013e832009-08-26 17:24:31 +020012803 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12804 particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012805 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012806 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012807
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012808 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12809 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012810 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012811 pctxt->state =
12812 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012813 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012814 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12815 pctxt->state =
12816 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012817 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012818 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012819 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012820 ns = wild->nsSet;
12821 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012822 pctxt->state =
12823 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012824 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012825 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012826 ns = ns->next;
12827 } while (ns != NULL);
12828
12829 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012830 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012831 start, hop, BAD_CAST "*", wild->negNsSet->value,
12832 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012833 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012834 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12835 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012836 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012837 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012838 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012839 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012840 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012841 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012842 break;
12843 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012844 case XML_SCHEMA_TYPE_ELEMENT:
Daniel Veillard4013e832009-08-26 17:24:31 +020012845 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012846 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012847 case XML_SCHEMA_TYPE_SEQUENCE:{
Daniel Veillard4013e832009-08-26 17:24:31 +020012848 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012849
Daniel Veillard4013e832009-08-26 17:24:31 +020012850 ret = 1;
12851 /*
12852 * If max and min occurances are default (1) then
12853 * simply iterate over the particles of the <sequence>.
12854 */
12855 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12856 sub = particle->children->children;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012857
Daniel Veillard4013e832009-08-26 17:24:31 +020012858 while (sub != NULL) {
12859 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12860 (xmlSchemaParticlePtr) sub);
12861 if (tmp2 != 1) ret = 0;
12862 sub = sub->next;
12863 }
12864 } else {
12865 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012866
Daniel Veillard4013e832009-08-26 17:24:31 +020012867 if (particle->maxOccurs >= UNBOUNDED) {
12868 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012869 xmlAutomataStatePtr tmp;
12870 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012871
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012872 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012873 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012874 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012875
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012876 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012877 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillard4255d502002-04-16 15:50:10 +000012878
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012879 sub = particle->children->children;
12880 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012881 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12882 (xmlSchemaParticlePtr) sub);
12883 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012884 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012885 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012886 tmp = pctxt->state;
Daniel Veillard4013e832009-08-26 17:24:31 +020012887 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12888 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012889 pctxt->state =
Daniel Veillard4013e832009-08-26 17:24:31 +020012890 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12891 NULL, counter);
12892 if (ret == 1)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012893 xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012894 oldstate, pctxt->state);
12895
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012896 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020012897 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12898 oldstate, NULL);
12899 oldstate = pctxt->state;
12900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012901 sub = particle->children->children;
12902 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012903 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12904 (xmlSchemaParticlePtr) sub);
12905 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012906 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012907 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012908 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12909 oldstate);
12910 /*
12911 * epsilon needed to block previous trans from
12912 * being allowed to enter back from another
12913 * construct
12914 */
12915 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12916 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012917 if (particle->minOccurs == 0) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012918 xmlAutomataNewEpsilon(pctxt->am,
12919 oldstate, pctxt->state);
12920 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012921 }
12922 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012923 } else if ((particle->maxOccurs > 1)
12924 || (particle->minOccurs > 1)) {
12925 xmlAutomataStatePtr tmp;
12926 int counter;
Daniel Veillardb509f152002-04-17 16:28:10 +000012927
Daniel Veillard4013e832009-08-26 17:24:31 +020012928 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12929 oldstate, NULL);
12930 oldstate = pctxt->state;
Daniel Veillard7646b182002-04-20 06:41:40 +000012931
Daniel Veillard4013e832009-08-26 17:24:31 +020012932 counter = xmlAutomataNewCounter(pctxt->am,
12933 particle->minOccurs - 1,
12934 particle->maxOccurs - 1);
12935
12936 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012937 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012938 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12939 (xmlSchemaParticlePtr) sub);
12940 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012941 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012942 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012943 tmp = pctxt->state;
12944 xmlAutomataNewCountedTrans(pctxt->am,
12945 tmp, oldstate, counter);
12946 pctxt->state =
12947 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12948 counter);
12949 if ((particle->minOccurs == 0) || (ret == 1)) {
12950 xmlAutomataNewEpsilon(pctxt->am,
12951 oldstate, pctxt->state);
12952 ret = 1;
12953 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012954 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020012955 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012956 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012957 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12958 (xmlSchemaParticlePtr) sub);
12959 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012960 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012961 }
Daniel Veillardc70d1852012-08-23 23:28:04 +080012962
12963 /*
12964 * epsilon needed to block previous trans from
12965 * being allowed to enter back from another
12966 * construct
12967 */
12968 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12969 pctxt->state, NULL);
12970
Daniel Veillard4013e832009-08-26 17:24:31 +020012971 if (particle->minOccurs == 0) {
12972 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12973 pctxt->state);
12974 ret = 1;
12975 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012976 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012977 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012978 break;
12979 }
12980 case XML_SCHEMA_TYPE_CHOICE:{
12981 xmlSchemaTreeItemPtr sub;
12982 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012983
Daniel Veillard4013e832009-08-26 17:24:31 +020012984 ret = 0;
12985 start = pctxt->state;
12986 end = xmlAutomataNewState(pctxt->am);
12987
12988 /*
12989 * iterate over the subtypes and remerge the end with an
12990 * epsilon transition
12991 */
12992 if (particle->maxOccurs == 1) {
12993 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012994 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012995 pctxt->state = start;
12996 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12997 (xmlSchemaParticlePtr) sub);
12998 if (tmp2 == 1) ret = 1;
12999 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13000 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013001 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013002 } else {
13003 int counter;
13004 xmlAutomataStatePtr hop, base;
13005 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13006 UNBOUNDED : particle->maxOccurs - 1;
13007 int minOccurs =
13008 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13009
13010 /*
13011 * use a counter to keep track of the number of transtions
13012 * which went through the choice.
13013 */
13014 counter =
13015 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13016 hop = xmlAutomataNewState(pctxt->am);
13017 base = xmlAutomataNewState(pctxt->am);
13018
13019 sub = particle->children->children;
13020 while (sub != NULL) {
13021 pctxt->state = base;
13022 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13023 (xmlSchemaParticlePtr) sub);
13024 if (tmp2 == 1) ret = 1;
13025 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13026 sub = sub->next;
Daniel Veillardbd56c442009-08-12 15:39:23 +020013027 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013028 xmlAutomataNewEpsilon(pctxt->am, start, base);
13029 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13030 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13031 if (ret == 1)
13032 xmlAutomataNewEpsilon(pctxt->am, base, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013033 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013034 if (particle->minOccurs == 0) {
13035 xmlAutomataNewEpsilon(pctxt->am, start, end);
13036 ret = 1;
13037 }
13038 pctxt->state = end;
13039 break;
13040 }
13041 case XML_SCHEMA_TYPE_ALL:{
13042 xmlAutomataStatePtr start, tmp;
13043 xmlSchemaParticlePtr sub;
13044 xmlSchemaElementPtr elemDecl;
13045
13046 ret = 1;
13047
13048 sub = (xmlSchemaParticlePtr) particle->children->children;
13049 if (sub == NULL)
13050 break;
13051
13052 ret = 0;
13053
13054 start = pctxt->state;
13055 tmp = xmlAutomataNewState(pctxt->am);
13056 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13057 pctxt->state = tmp;
13058 while (sub != NULL) {
13059 pctxt->state = tmp;
13060
13061 elemDecl = (xmlSchemaElementPtr) sub->children;
13062 if (elemDecl == NULL) {
13063 PERROR_INT("xmlSchemaBuildAContentModel",
13064 "<element> particle has no term");
13065 return(ret);
13066 };
13067 /*
13068 * NOTE: The {max occurs} of all the particles in the
13069 * {particles} of the group must be 0 or 1; this is
13070 * already ensured during the parse of the content of
13071 * <all>.
13072 */
13073 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13074 int counter;
13075
13076 /*
13077 * This is an abstract group, we need to share
13078 * the same counter for all the element transitions
13079 * derived from the group
13080 */
13081 counter = xmlAutomataNewCounter(pctxt->am,
13082 sub->minOccurs, sub->maxOccurs);
13083 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13084 sub, counter, pctxt->state);
13085 } else {
13086 if ((sub->minOccurs == 1) &&
13087 (sub->maxOccurs == 1)) {
13088 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13089 pctxt->state,
13090 elemDecl->name,
13091 elemDecl->targetNamespace,
13092 1, 1, elemDecl);
13093 } else if ((sub->minOccurs == 0) &&
13094 (sub->maxOccurs == 1)) {
13095
13096 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13097 pctxt->state,
13098 elemDecl->name,
13099 elemDecl->targetNamespace,
13100 0,
13101 1,
13102 elemDecl);
13103 }
13104 }
13105 sub = (xmlSchemaParticlePtr) sub->next;
13106 }
13107 pctxt->state =
13108 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13109 if (particle->minOccurs == 0) {
13110 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13111 ret = 1;
13112 }
13113 break;
13114 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013115 case XML_SCHEMA_TYPE_GROUP:
13116 /*
13117 * If we hit a model group definition, then this means that
13118 * it was empty, thus was not substituted for the containing
13119 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013120 * TODO: But the group should be substituted and not occur at
13121 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013122 */
Daniel Veillard4013e832009-08-26 17:24:31 +020013123 ret = 1;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013124 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013125 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013126 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13127 "xmlSchemaBuildAContentModel",
13128 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013129 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020013130 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013131 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013132 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013133}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013134
Daniel Veillard4255d502002-04-16 15:50:10 +000013135/**
13136 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000013137 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013138 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013139 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013140 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013141 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013142 */
13143static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013144xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013145 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013146{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013147 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13148 (type->contModel != NULL) ||
13149 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13150 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013151 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013152
13153#ifdef DEBUG_CONTENT
13154 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013155 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013156#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013157 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013158 ctxt->am = xmlNewAutomata();
13159 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013160 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013161 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013162 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013163 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013164 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013165 /*
13166 * Build the automaton.
13167 */
13168 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013169 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013170 type->contModel = xmlAutomataCompile(ctxt->am);
13171 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013172 xmlSchemaPCustomErr(ctxt,
13173 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013174 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013175 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013176 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013178 XML_SCHEMAP_NOT_DETERMINISTIC,
13179 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013180 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013181 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013182 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013183#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013184 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013185 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013186 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013187#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013188 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013189 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013190 xmlFreeAutomata(ctxt->am);
13191 ctxt->am = NULL;
13192}
13193
13194/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013195 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013196 * @elem: the schema element context
13197 * @ctxt: the schema parser context
13198 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013199 * Resolves the references of an element declaration
13200 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013202 */
13203static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013204xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13205 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013206{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013207 if ((ctxt == NULL) || (elemDecl == NULL) ||
13208 ((elemDecl != NULL) &&
13209 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013210 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013211 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013212
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013213 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013214 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215
Jan Pokorný761c9e92013-11-29 23:26:27 +010013216 /* (type definition) ... otherwise the type definition `resolved`
13217 * to by the `actual value` of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013218 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013219 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013220 elemDecl->namedTypeNs);
13221 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013222 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013224 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013225 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013226 XML_SCHEMA_TYPE_BASIC, "type definition");
13227 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013228 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013229 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013230 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013231 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013232
Daniel Veillardc0826a72004-08-10 14:17:33 +000013233 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013234 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013235 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013236 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013237 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13238 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013239 if (substHead == NULL) {
13240 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013241 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013242 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013243 "substitutionGroup", elemDecl->substGroup,
13244 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013245 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013246 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013247 /*
13248 * Set the "substitution group affiliation".
13249 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013250 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013251 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013252 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013253 * The type definitions is set to:
13254 * SPEC "...the {type definition} of the element
Jan Pokorný761c9e92013-11-29 23:26:27 +010013255 * declaration `resolved` to by the `actual value`
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013256 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013257 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013258 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013259 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013260 }
13261 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013262 /*
13263 * SPEC "The definition of anyType serves as the default type definition
13264 * for element declarations whose XML representation does not specify one."
13265 */
13266 if ((elemDecl->subtypes == NULL) &&
13267 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013268 (elemDecl->substGroup == NULL))
13269 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013270}
13271
13272/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013273 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013274 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013275 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013276 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013277 * Checks and builds the "member type definitions" property of the union
13278 * simple type. This handles part (1), part (2) is done in
13279 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13280 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013281 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013282 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013284xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13285 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013286{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013288 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013289 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013290
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013291 /*
13292 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Jan Pokorný761c9e92013-11-29 23:26:27 +010013293 * define the explicit members as the type definitions `resolved`
13294 * to by the items in the `actual value` of the memberTypes [attribute],
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013295 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013296 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013297 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013298 /*
13299 * Resolve references.
13300 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013301 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013302 lastLink = NULL;
13303 while (link != NULL) {
13304 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013305
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013306 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13307 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13308
13309 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013310 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013311 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013312 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013313 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13314 /*
13315 * Remove the member type link.
13316 */
13317 if (lastLink == NULL)
13318 type->memberTypes = link->next;
13319 else
13320 lastLink->next = link->next;
13321 newLink = link;
13322 link = link->next;
13323 xmlFree(newLink);
13324 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013325 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013326 lastLink = link;
13327 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013328 }
13329 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013330 /*
13331 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013332 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013333 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013334 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13336 if (link == NULL) {
13337 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13338 return (-1);
13339 }
13340 link->type = memberType;
13341 link->next = NULL;
13342 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013343 type->memberTypes = link;
13344 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013345 lastLink->next = link;
13346 lastLink = link;
13347 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013348 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013349 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013350}
13351
Daniel Veillard4255d502002-04-16 15:50:10 +000013352/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013353 * xmlSchemaIsDerivedFromBuiltInType:
13354 * @ctxt: the schema parser context
13355 * @type: the type definition
13356 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013357 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013358 *
13359 * Returns 1 if the type has the given value type, or
13360 * is derived from such a type.
13361 */
William M. Brack803812b2004-06-03 02:11:24 +000013362static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013363xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013364{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013365 if (type == NULL)
13366 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013367 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013368 return (0);
13369 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13370 if (type->builtInType == valType)
13371 return(1);
13372 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13373 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13374 return (0);
13375 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013376 }
13377 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013378}
13379
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013380#if 0
13381/**
13382 * xmlSchemaIsDerivedFromBuiltInType:
13383 * @ctxt: the schema parser context
13384 * @type: the type definition
13385 * @valType: the value type
13386 *
13387 *
13388 * Returns 1 if the type has the given value type, or
13389 * is derived from such a type.
13390 */
13391static int
13392xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13393{
13394 if (type == NULL)
13395 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013396 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013397 return (0);
13398 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13399 if (type->builtInType == valType)
13400 return(1);
13401 return (0);
13402 } else
13403 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13404
13405 return (0);
13406}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013407
13408static xmlSchemaTypePtr
13409xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13410{
13411 if (type == NULL)
13412 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013413 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414 return (NULL);
13415 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013416 return(type);
13417 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418}
Daniel Veillard15724252008-08-30 15:01:04 +000013419#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013420
Daniel Veillard3646d642004-06-02 19:19:14 +000013421/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013422 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 * @type: the simpleType definition
13424 *
13425 * Returns the primitive type of the given type or
13426 * NULL in case of error.
13427 */
13428static xmlSchemaTypePtr
13429xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13430{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013431
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013433 /*
13434 * Note that anySimpleType is actually not a primitive type
13435 * but we need that here.
13436 */
13437 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13438 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 return (type);
13440 type = type->baseType;
13441 }
13442
13443 return (NULL);
13444}
13445
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013446#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013447/**
13448 * xmlSchemaGetBuiltInTypeAncestor:
13449 * @type: the simpleType definition
13450 *
13451 * Returns the primitive type of the given type or
13452 * NULL in case of error.
13453 */
13454static xmlSchemaTypePtr
13455xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13456{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013457 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013458 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013459 while (type != NULL) {
13460 if (type->type == XML_SCHEMA_TYPE_BASIC)
13461 return (type);
13462 type = type->baseType;
13463 }
13464
13465 return (NULL);
13466}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013467#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013468
Daniel Veillard01fa6152004-06-29 17:04:39 +000013469/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013470 * xmlSchemaCloneWildcardNsConstraints:
13471 * @ctxt: the schema parser context
13472 * @dest: the destination wildcard
13473 * @source: the source wildcard
13474 *
13475 * Clones the namespace constraints of source
13476 * and assignes them to dest.
13477 * Returns -1 on internal error, 0 otherwise.
13478 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013479static int
13480xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013481 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013482 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013483{
13484 xmlSchemaWildcardNsPtr cur, tmp, last;
13485
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013486 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013488 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013489 cur = source->nsSet;
13490 last = NULL;
13491 while (cur != NULL) {
13492 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13493 if (tmp == NULL)
13494 return(-1);
13495 tmp->value = cur->value;
13496 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013497 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013499 last->next = tmp;
13500 last = tmp;
13501 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013503 if (dest->negNsSet != NULL)
13504 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013505 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013506 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13507 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013508 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013509 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013510 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013511 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013512 return(0);
13513}
13514
Daniel Veillard50355f02004-06-08 17:52:16 +000013515/**
13516 * xmlSchemaUnionWildcards:
13517 * @ctxt: the schema parser context
13518 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013520 *
13521 * Unions the namespace constraints of the given wildcards.
13522 * @completeWild will hold the resulting union.
13523 * Returns a positive error code on failure, -1 in case of an
13524 * internal error, 0 otherwise.
13525 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013526static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013527xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013528 xmlSchemaWildcardPtr completeWild,
13529 xmlSchemaWildcardPtr curWild)
13530{
13531 xmlSchemaWildcardNsPtr cur, curB, tmp;
13532
13533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013535 * value.
13536 */
13537 if ((completeWild->any == curWild->any) &&
13538 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13539 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540
Daniel Veillard3646d642004-06-02 19:19:14 +000013541 if ((completeWild->negNsSet == NULL) ||
13542 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013543
Daniel Veillard3646d642004-06-02 19:19:14 +000013544 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013545 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546
13547 /*
13548 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013549 */
13550 cur = completeWild->nsSet;
13551 while (cur != NULL) {
13552 found = 0;
13553 curB = curWild->nsSet;
13554 while (curB != NULL) {
13555 if (cur->value == curB->value) {
13556 found = 1;
13557 break;
13558 }
13559 curB = curB->next;
13560 }
13561 if (!found)
13562 break;
13563 cur = cur->next;
13564 }
13565 if (found)
13566 return(0);
13567 } else
13568 return(0);
13569 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013571 /*
13572 * 2 If either O1 or O2 is any, then any must be the value
13573 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013575 if (completeWild->any == 0) {
13576 completeWild->any = 1;
13577 if (completeWild->nsSet != NULL) {
13578 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13579 completeWild->nsSet = NULL;
13580 }
13581 if (completeWild->negNsSet != NULL) {
13582 xmlFree(completeWild->negNsSet);
13583 completeWild->negNsSet = NULL;
13584 }
13585 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013586 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013587 }
13588 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013589 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013590 * then the union of those sets must be the value.
13591 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013592 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013593 int found;
13594 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595
Daniel Veillard3646d642004-06-02 19:19:14 +000013596 cur = curWild->nsSet;
13597 start = completeWild->nsSet;
13598 while (cur != NULL) {
13599 found = 0;
13600 curB = start;
13601 while (curB != NULL) {
13602 if (cur->value == curB->value) {
13603 found = 1;
13604 break;
13605 }
13606 curB = curB->next;
13607 }
13608 if (!found) {
13609 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013610 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013611 return (-1);
13612 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013614 completeWild->nsSet = tmp;
13615 }
13616 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 }
13618
Daniel Veillard3646d642004-06-02 19:19:14 +000013619 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013620 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013621 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 * 4 If the two are negations of different values (namespace names
Jan Pokorný761c9e92013-11-29 23:26:27 +010013623 * or `absent`), then a pair of not and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013624 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013626 (curWild->negNsSet != NULL) &&
13627 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13628 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013629
13630 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013631 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013632 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013633 * 5.
13634 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013636 (completeWild->negNsSet->value != NULL) &&
13637 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013639 (curWild->negNsSet->value != NULL) &&
13640 (completeWild->nsSet != NULL))) {
13641
13642 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643
Daniel Veillard3646d642004-06-02 19:19:14 +000013644 if (completeWild->nsSet != NULL) {
13645 cur = completeWild->nsSet;
13646 curB = curWild->negNsSet;
13647 } else {
13648 cur = curWild->nsSet;
13649 curB = completeWild->negNsSet;
13650 }
13651 nsFound = 0;
13652 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013653 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013654 absentFound = 1;
13655 else if (cur->value == curB->value)
13656 nsFound = 1;
13657 if (nsFound && absentFound)
13658 break;
13659 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013660 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013661
13662 if (nsFound && absentFound) {
13663 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013664 * 5.1 If the set S includes both the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013665 * name and `absent`, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013667 completeWild->any = 1;
13668 if (completeWild->nsSet != NULL) {
13669 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13670 completeWild->nsSet = NULL;
13671 }
13672 if (completeWild->negNsSet != NULL) {
13673 xmlFree(completeWild->negNsSet);
13674 completeWild->negNsSet = NULL;
13675 }
13676 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013677 /*
13678 * 5.2 If the set S includes the negated namespace name
Jan Pokorný761c9e92013-11-29 23:26:27 +010013679 * but not `absent`, then a pair of not and `absent` must
Daniel Veillard3646d642004-06-02 19:19:14 +000013680 * be the value.
13681 */
13682 if (completeWild->nsSet != NULL) {
13683 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13684 completeWild->nsSet = NULL;
13685 }
13686 if (completeWild->negNsSet == NULL) {
13687 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13688 if (completeWild->negNsSet == NULL)
13689 return (-1);
13690 }
13691 completeWild->negNsSet->value = NULL;
13692 } else if ((!nsFound) && absentFound) {
13693 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013694 * 5.3 If the set S includes `absent` but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013695 * namespace name, then the union is not expressible.
13696 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013698 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013699 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013701 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013702 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013703 /*
13704 * 5.4 If the set S does not include either the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013705 * name or `absent`, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013706 * and a namespace name must be the value.
13707 */
13708 if (completeWild->negNsSet == NULL) {
13709 if (completeWild->nsSet != NULL) {
13710 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13711 completeWild->nsSet = NULL;
13712 }
13713 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13714 if (completeWild->negNsSet == NULL)
13715 return (-1);
13716 completeWild->negNsSet->value = curWild->negNsSet->value;
13717 }
13718 }
13719 return (0);
13720 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013721 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013722 * 6.
13723 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013725 (completeWild->negNsSet->value == NULL) &&
13726 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013728 (curWild->negNsSet->value == NULL) &&
13729 (completeWild->nsSet != NULL))) {
13730
13731 if (completeWild->nsSet != NULL) {
13732 cur = completeWild->nsSet;
13733 } else {
13734 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013736 while (cur != NULL) {
13737 if (cur->value == NULL) {
13738 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013739 * 6.1 If the set S includes `absent`, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013740 * value.
13741 */
13742 completeWild->any = 1;
13743 if (completeWild->nsSet != NULL) {
13744 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13745 completeWild->nsSet = NULL;
13746 }
13747 if (completeWild->negNsSet != NULL) {
13748 xmlFree(completeWild->negNsSet);
13749 completeWild->negNsSet = NULL;
13750 }
13751 return (0);
13752 }
13753 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013755 if (completeWild->negNsSet == NULL) {
13756 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013757 * 6.2 If the set S does not include `absent`, then a pair of not
13758 * and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013759 */
13760 if (completeWild->nsSet != NULL) {
13761 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13762 completeWild->nsSet = NULL;
13763 }
13764 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13765 if (completeWild->negNsSet == NULL)
13766 return (-1);
13767 completeWild->negNsSet->value = NULL;
13768 }
13769 return (0);
13770 }
13771 return (0);
13772
13773}
13774
Daniel Veillard50355f02004-06-08 17:52:16 +000013775/**
13776 * xmlSchemaIntersectWildcards:
13777 * @ctxt: the schema parser context
13778 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013779 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013780 *
13781 * Intersects the namespace constraints of the given wildcards.
13782 * @completeWild will hold the resulting intersection.
13783 * Returns a positive error code on failure, -1 in case of an
13784 * internal error, 0 otherwise.
13785 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013786static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013788 xmlSchemaWildcardPtr completeWild,
13789 xmlSchemaWildcardPtr curWild)
13790{
William M. Brack803812b2004-06-03 02:11:24 +000013791 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013792
13793 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013794 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013795 * value.
13796 */
13797 if ((completeWild->any == curWild->any) &&
13798 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13799 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800
Daniel Veillard3646d642004-06-02 19:19:14 +000013801 if ((completeWild->negNsSet == NULL) ||
13802 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803
Daniel Veillard3646d642004-06-02 19:19:14 +000013804 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013805 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013806
13807 /*
13808 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013809 */
13810 cur = completeWild->nsSet;
13811 while (cur != NULL) {
13812 found = 0;
13813 curB = curWild->nsSet;
13814 while (curB != NULL) {
13815 if (cur->value == curB->value) {
13816 found = 1;
13817 break;
13818 }
13819 curB = curB->next;
13820 }
13821 if (!found)
13822 break;
13823 cur = cur->next;
13824 }
13825 if (found)
13826 return(0);
13827 } else
13828 return(0);
13829 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013831 /*
13832 * 2 If either O1 or O2 is any, then the other must be the value.
13833 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013834 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013835 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013836 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013837 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013839 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013840 * 3 If either O1 or O2 is a pair of not and a value (a namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013841 * name or `absent`) and the other is a set of (namespace names or
13842 * `absent`), then that set, minus the negated value if it was in
13843 * the set, minus `absent` if it was in the set, must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013844 */
13845 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13846 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13847 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848
Daniel Veillard3646d642004-06-02 19:19:14 +000013849 if (completeWild->nsSet == NULL) {
13850 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013851 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013852 return(-1);
13853 } else
13854 neg = curWild->negNsSet->value;
13855 /*
13856 * Remove absent and negated.
13857 */
13858 prev = NULL;
13859 cur = completeWild->nsSet;
13860 while (cur != NULL) {
13861 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013862 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013863 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013864 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013865 prev->next = cur->next;
13866 xmlFree(cur);
13867 break;
13868 }
13869 prev = cur;
13870 cur = cur->next;
13871 }
13872 if (neg != NULL) {
13873 prev = NULL;
13874 cur = completeWild->nsSet;
13875 while (cur != NULL) {
13876 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013878 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013879 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013880 prev->next = cur->next;
13881 xmlFree(cur);
13882 break;
13883 }
13884 prev = cur;
13885 cur = cur->next;
13886 }
13887 }
13888
13889 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013890 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013891 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013892 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013893 * then the intersection of those sets must be the value.
13894 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013895 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013896 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013897
Daniel Veillard3646d642004-06-02 19:19:14 +000013898 cur = completeWild->nsSet;
13899 prev = NULL;
13900 while (cur != NULL) {
13901 found = 0;
13902 curB = curWild->nsSet;
13903 while (curB != NULL) {
13904 if (cur->value == curB->value) {
13905 found = 1;
13906 break;
13907 }
13908 curB = curB->next;
13909 }
13910 if (!found) {
13911 if (prev == NULL)
13912 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013913 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013914 prev->next = cur->next;
13915 tmp = cur->next;
13916 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013917 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013918 continue;
13919 }
13920 prev = cur;
13921 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013922 }
13923
Daniel Veillard3646d642004-06-02 19:19:14 +000013924 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013925 }
13926 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013927 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928 */
13929 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013930 (curWild->negNsSet != NULL) &&
13931 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013932 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013933 (curWild->negNsSet->value != NULL)) {
13934
13935 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013936 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013938 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013939 }
13940 /*
13941 * 6 If the one is a negation of a namespace name and the other
Jan Pokorný761c9e92013-11-29 23:26:27 +010013942 * is a negation of `absent`, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013943 * of a namespace name must be the value.
13944 */
13945 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13946 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013947 (completeWild->negNsSet->value == NULL)) {
13948 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013949 }
13950 return(0);
13951}
13952
Daniel Veillard50355f02004-06-08 17:52:16 +000013953/**
13954 * xmlSchemaIsWildcardNsConstraintSubset:
13955 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013956 * @sub: the first wildcard
13957 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013958 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013959 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13960 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013961 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013962 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013963 */
13964static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013965xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13966 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967{
Daniel Veillard50355f02004-06-08 17:52:16 +000013968 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013970 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013971 if (super->any)
13972 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013973 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013974 * 2.1 sub must be a pair of not and a namespace name or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000013975 * 2.2 super must be a pair of not and the same value.
13976 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013977 if ((sub->negNsSet != NULL) &&
13978 (super->negNsSet != NULL) &&
Ryan Sleevi5cf1deb2012-02-29 10:56:32 +080013979 (sub->negNsSet->value == super->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013980 return (0);
13981 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013982 * 3.1 sub must be a set whose members are either namespace names or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000013983 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013984 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013985 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013986 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013987 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013988 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013989 xmlSchemaWildcardNsPtr cur, curB;
13990 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013991
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013992 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013993 while (cur != NULL) {
13994 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013995 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013996 while (curB != NULL) {
13997 if (cur->value == curB->value) {
13998 found = 1;
13999 break;
14000 }
14001 curB = curB->next;
14002 }
14003 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014004 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014005 cur = cur->next;
14006 }
14007 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014008 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014009 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014010 xmlSchemaWildcardNsPtr cur;
14011 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 * 3.2.2 super must be a pair of not and a namespace name or
Jan Pokorný761c9e92013-11-29 23:26:27 +010014013 * `absent` and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000014014 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014015 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014016 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014017 if (cur->value == super->negNsSet->value)
14018 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014019 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014020 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014021 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000014022 }
14023 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014024 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014025}
14026
Daniel Veillard50355f02004-06-08 17:52:16 +000014027static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014028xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014029 int *fixed,
14030 const xmlChar **value,
14031 xmlSchemaValPtr *val)
14032{
14033 *fixed = 0;
14034 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014035 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014036 *val = NULL;
14037
Daniel Veillarddee23482008-04-11 12:58:43 +000014038 if (attruse->defValue != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014039 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014040 if (val != NULL)
14041 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014042 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014043 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014044 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014045 } else if ((attruse->attrDecl != NULL) &&
14046 (attruse->attrDecl->defValue != NULL)) {
14047 *value = attruse->attrDecl->defValue;
14048 if (val != NULL)
14049 *val = attruse->attrDecl->defVal;
14050 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014051 *fixed = 1;
14052 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014053 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014054 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014055}
Daniel Veillard3646d642004-06-02 19:19:14 +000014056/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014057 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000014058 * @wild: the wildcard
14059 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014060 *
14061 * Validation Rule: Wildcard allows Namespace Name
14062 * (cvc-wildcard-namespace)
14063 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014064 * Returns 0 if the given namespace matches the wildcard,
14065 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000014066 */
14067static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014068xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14069 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000014070{
14071 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014072 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014073
14074 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014075 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014076 else if (wild->nsSet != NULL) {
14077 xmlSchemaWildcardNsPtr cur;
14078
14079 cur = wild->nsSet;
14080 while (cur != NULL) {
14081 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014082 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014083 cur = cur->next;
14084 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014085 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000014086 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014087 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014088
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014089 return(1);
14090}
14091
14092#define XML_SCHEMA_ACTION_DERIVE 0
14093#define XML_SCHEMA_ACTION_REDEFINE 1
14094
14095#define WXS_ACTION_STR(a) \
14096((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14097
14098/*
14099* Schema Component Constraint:
14100* Derivation Valid (Restriction, Complex)
14101* derivation-ok-restriction (2) - (4)
14102*
14103* ATTENTION:
14104* In XML Schema 1.1 this will be:
14105* Validation Rule:
14106* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14107*
14108*/
14109static int
14110xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14111 int action,
14112 xmlSchemaBasicItemPtr item,
14113 xmlSchemaBasicItemPtr baseItem,
14114 xmlSchemaItemListPtr uses,
14115 xmlSchemaItemListPtr baseUses,
14116 xmlSchemaWildcardPtr wild,
14117 xmlSchemaWildcardPtr baseWild)
Daniel Veillarddee23482008-04-11 12:58:43 +000014118{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014119 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014120 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014121 const xmlChar *bEffValue;
14122 int effFixed;
Daniel Veillarddee23482008-04-11 12:58:43 +000014123
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014124 if (uses != NULL) {
14125 for (i = 0; i < uses->nbItems; i++) {
14126 cur = uses->items[i];
14127 found = 0;
14128 if (baseUses == NULL)
14129 goto not_found;
14130 for (j = 0; j < baseUses->nbItems; j++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014131 bcur = baseUses->items[j];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014132 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14133 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14134 (WXS_ATTRUSE_DECL_TNS(cur) ==
14135 WXS_ATTRUSE_DECL_TNS(bcur)))
14136 {
14137 /*
14138 * (2.1) "If there is an attribute use in the {attribute
14139 * uses} of the {base type definition} (call this B) whose
14140 * {attribute declaration} has the same {name} and {target
14141 * namespace}, then all of the following must be true:"
14142 */
14143 found = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000014144
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014145 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14146 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14147 {
14148 xmlChar *str = NULL;
14149 /*
14150 * (2.1.1) "one of the following must be true:"
14151 * (2.1.1.1) "B's {required} is false."
14152 * (2.1.1.2) "R's {required} is true."
14153 */
14154 xmlSchemaPAttrUseErr4(pctxt,
14155 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14156 WXS_ITEM_NODE(item), item, cur,
14157 "The 'optional' attribute use is inconsistent "
14158 "with the corresponding 'required' attribute use of "
14159 "the %s %s",
14160 WXS_ACTION_STR(action),
14161 xmlSchemaGetComponentDesignation(&str, baseItem),
14162 NULL, NULL);
14163 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014164 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014165 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014166 WXS_ATTRUSE_TYPEDEF(cur),
14167 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14168 {
14169 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014170
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014171 /*
14172 * SPEC (2.1.2) "R's {attribute declaration}'s
14173 * {type definition} must be validly derived from
14174 * B's {type definition} given the empty set as
Jan Pokorný761c9e92013-11-29 23:26:27 +010014175 * defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014176 */
14177 xmlSchemaPAttrUseErr4(pctxt,
14178 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14179 WXS_ITEM_NODE(item), item, cur,
14180 "The attribute declaration's %s "
14181 "is not validly derived from "
14182 "the corresponding %s of the "
14183 "attribute declaration in the %s %s",
14184 xmlSchemaGetComponentDesignation(&strA,
14185 WXS_ATTRUSE_TYPEDEF(cur)),
14186 xmlSchemaGetComponentDesignation(&strB,
14187 WXS_ATTRUSE_TYPEDEF(bcur)),
14188 WXS_ACTION_STR(action),
14189 xmlSchemaGetComponentDesignation(&strC, baseItem));
14190 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14191 FREE_AND_NULL(strA);
14192 FREE_AND_NULL(strB);
14193 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014194 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014195 } else {
14196 /*
14197 * 2.1.3 [Definition:] Let the effective value
14198 * constraint of an attribute use be its {value
14199 * constraint}, if present, otherwise its {attribute
14200 * declaration}'s {value constraint} .
14201 */
14202 xmlSchemaGetEffectiveValueConstraint(bcur,
14203 &effFixed, &bEffValue, NULL);
14204 /*
14205 * 2.1.3 ... one of the following must be true
14206 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010014207 * 2.1.3.1 B's `effective value constraint` is
14208 * `absent` or default.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014209 */
14210 if ((bEffValue != NULL) &&
14211 (effFixed == 1)) {
14212 const xmlChar *rEffValue = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014213
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014214 xmlSchemaGetEffectiveValueConstraint(bcur,
14215 &effFixed, &rEffValue, NULL);
14216 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014217 * 2.1.3.2 R's `effective value constraint` is
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014218 * fixed with the same string as B's.
14219 * MAYBE TODO: Compare the computed values.
14220 * Hmm, it says "same string" so
14221 * string-equality might really be sufficient.
14222 */
14223 if ((effFixed == 0) ||
14224 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14225 {
14226 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014227
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014228 xmlSchemaPAttrUseErr4(pctxt,
14229 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14230 WXS_ITEM_NODE(item), item, cur,
14231 "The effective value constraint of the "
14232 "attribute use is inconsistent with "
14233 "its correspondent in the %s %s",
14234 WXS_ACTION_STR(action),
14235 xmlSchemaGetComponentDesignation(&str,
14236 baseItem),
14237 NULL, NULL);
14238 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014239 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014240 }
14241 }
14242 }
14243 break;
14244 }
14245 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014246not_found:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014247 if (!found) {
14248 /*
14249 * (2.2) "otherwise the {base type definition} must have an
14250 * {attribute wildcard} and the {target namespace} of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014251 * R's {attribute declaration} must be `valid` with respect
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014252 * to that wildcard, as defined in Wildcard allows Namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010014253 * Name ($3.10.4)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014254 */
14255 if ((baseWild == NULL) ||
14256 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14257 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14258 {
14259 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014260
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014261 xmlSchemaPAttrUseErr4(pctxt,
14262 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14263 WXS_ITEM_NODE(item), item, cur,
14264 "Neither a matching attribute use, "
14265 "nor a matching wildcard exists in the %s %s",
14266 WXS_ACTION_STR(action),
14267 xmlSchemaGetComponentDesignation(&str, baseItem),
14268 NULL, NULL);
14269 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014270 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014271 }
14272 }
14273 }
14274 }
14275 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000014276 * SPEC derivation-ok-restriction (3):
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014277 * (3) "For each attribute use in the {attribute uses} of the {base type
14278 * definition} whose {required} is true, there must be an attribute
14279 * use with an {attribute declaration} with the same {name} and
14280 * {target namespace} as its {attribute declaration} in the {attribute
14281 * uses} of the complex type definition itself whose {required} is true.
14282 */
14283 if (baseUses != NULL) {
14284 for (j = 0; j < baseUses->nbItems; j++) {
14285 bcur = baseUses->items[j];
14286 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14287 continue;
14288 found = 0;
14289 if (uses != NULL) {
14290 for (i = 0; i < uses->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014291 cur = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014292 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14293 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14294 (WXS_ATTRUSE_DECL_TNS(cur) ==
14295 WXS_ATTRUSE_DECL_TNS(bcur))) {
14296 found = 1;
14297 break;
14298 }
14299 }
14300 }
14301 if (!found) {
14302 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014303
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014304 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14305 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14306 NULL, item,
14307 "A matching attribute use for the "
14308 "'required' %s of the %s %s is missing",
14309 xmlSchemaGetComponentDesignation(&strA, bcur),
14310 WXS_ACTION_STR(action),
14311 xmlSchemaGetComponentDesignation(&strB, baseItem),
14312 NULL);
14313 FREE_AND_NULL(strA);
14314 FREE_AND_NULL(strB);
14315 }
14316 }
14317 }
14318 /*
14319 * derivation-ok-restriction (4)
14320 */
14321 if (wild != NULL) {
14322 /*
14323 * (4) "If there is an {attribute wildcard}, all of the
14324 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000014325 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014326 if (baseWild == NULL) {
14327 xmlChar *str = NULL;
14328
14329 /*
14330 * (4.1) "The {base type definition} must also have one."
Daniel Veillarddee23482008-04-11 12:58:43 +000014331 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014332 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14333 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14334 NULL, item,
14335 "The %s has an attribute wildcard, "
14336 "but the %s %s '%s' does not have one",
Daniel Veillarddee23482008-04-11 12:58:43 +000014337 WXS_ITEM_TYPE_NAME(item),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014338 WXS_ACTION_STR(action),
14339 WXS_ITEM_TYPE_NAME(baseItem),
14340 xmlSchemaGetComponentQName(&str, baseItem));
14341 FREE_AND_NULL(str);
14342 return(pctxt->err);
14343 } else if ((baseWild->any == 0) &&
14344 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14345 {
14346 xmlChar *str = NULL;
14347 /*
14348 * (4.2) "The complex type definition's {attribute wildcard}'s
14349 * {namespace constraint} must be a subset of the {base type
14350 * definition}'s {attribute wildcard}'s {namespace constraint},
Jan Pokorný761c9e92013-11-29 23:26:27 +010014351 * as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014352 */
14353 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14354 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14355 NULL, item,
14356 "The attribute wildcard is not a valid "
14357 "subset of the wildcard in the %s %s '%s'",
14358 WXS_ACTION_STR(action),
14359 WXS_ITEM_TYPE_NAME(baseItem),
14360 xmlSchemaGetComponentQName(&str, baseItem),
14361 NULL);
14362 FREE_AND_NULL(str);
14363 return(pctxt->err);
14364 }
Jan Pokorný761c9e92013-11-29 23:26:27 +010014365 /* 4.3 Unless the {base type definition} is the `ur-type
14366 * definition`, the complex type definition's {attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014367 * wildcard}'s {process contents} must be identical to or
14368 * stronger than the {base type definition}'s {attribute
14369 * wildcard}'s {process contents}, where strict is stronger
14370 * than lax is stronger than skip.
14371 */
14372 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14373 (wild->processContents < baseWild->processContents)) {
14374 xmlChar *str = NULL;
14375 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14376 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14377 NULL, baseItem,
14378 "The {process contents} of the attribute wildcard is "
14379 "weaker than the one in the %s %s '%s'",
14380 WXS_ACTION_STR(action),
14381 WXS_ITEM_TYPE_NAME(baseItem),
14382 xmlSchemaGetComponentQName(&str, baseItem),
14383 NULL);
14384 FREE_AND_NULL(str)
14385 return(pctxt->err);
14386 }
14387 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014388 return(0);
14389}
14390
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014391
14392static int
14393xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14394 xmlSchemaBasicItemPtr item,
14395 xmlSchemaWildcardPtr *completeWild,
14396 xmlSchemaItemListPtr list,
14397 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014398/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014399 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014400 * @ctxt: the schema parser context
14401 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014402 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014403 *
14404 * Builds the wildcard and the attribute uses on the given complex type.
14405 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014406 *
14407 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14408 * strings, so recheck this if we start to hardcode some schemata, since
14409 * they might not be in the same dict.
14410 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014411 */
14412static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014413xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014414 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014415{
14416 xmlSchemaTypePtr baseType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014417 xmlSchemaAttributeUsePtr use;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014418 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014419
Daniel Veillard01fa6152004-06-29 17:04:39 +000014420 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014421 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014422 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014423 return (-1);
14424 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014425 baseType = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014426 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014427 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014428 return(-1);
14429
14430 uses = type->attrUses;
14431 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014432 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014433 * Expand attribute group references. And build the 'complete'
14434 * wildcard, i.e. intersect multiple wildcards.
14435 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014436 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014437 if (uses != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014438 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014439 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014440 * This one will transfer all attr. prohibitions
14441 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014442 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014443 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14444 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14445 pctxt->attrProhibs) == -1)
14446 {
14447 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14448 "failed to expand attributes");
14449 }
14450 if (pctxt->attrProhibs->nbItems != 0)
14451 prohibs = pctxt->attrProhibs;
14452 } else {
14453 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14454 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14455 NULL) == -1)
14456 {
14457 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14458 "failed to expand attributes");
14459 }
14460 }
14461 }
14462 /*
14463 * Inherit the attribute uses of the base type.
14464 */
14465 if (baseUses != NULL) {
14466 int i, j;
14467 xmlSchemaAttributeUseProhibPtr pro;
14468
14469 if (WXS_IS_RESTRICTION(type)) {
14470 int usesCount;
Daniel Veillarddee23482008-04-11 12:58:43 +000014471 xmlSchemaAttributeUsePtr tmp;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014472
14473 if (uses != NULL)
14474 usesCount = uses->nbItems;
14475 else
14476 usesCount = 0;
14477
14478 /* Restriction. */
14479 for (i = 0; i < baseUses->nbItems; i++) {
14480 use = baseUses->items[i];
14481 if (prohibs) {
14482 /*
14483 * Filter out prohibited uses.
14484 */
14485 for (j = 0; j < prohibs->nbItems; j++) {
14486 pro = prohibs->items[j];
14487 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14488 (WXS_ATTRUSE_DECL_TNS(use) ==
14489 pro->targetNamespace))
14490 {
14491 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014492 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014493 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014494 }
14495 if (usesCount) {
14496 /*
14497 * Filter out existing uses.
14498 */
14499 for (j = 0; j < usesCount; j++) {
14500 tmp = uses->items[j];
14501 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14502 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14503 (WXS_ATTRUSE_DECL_TNS(use) ==
14504 WXS_ATTRUSE_DECL_TNS(tmp)))
14505 {
14506 goto inherit_next;
14507 }
14508 }
14509 }
14510 if (uses == NULL) {
14511 type->attrUses = xmlSchemaItemListCreate();
14512 if (type->attrUses == NULL)
14513 goto exit_failure;
14514 uses = type->attrUses;
14515 }
14516 xmlSchemaItemListAddSize(uses, 2, use);
14517inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014518 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014519 } else {
14520 /* Extension. */
Daniel Veillarddee23482008-04-11 12:58:43 +000014521 for (i = 0; i < baseUses->nbItems; i++) {
14522 use = baseUses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014523 if (uses == NULL) {
14524 type->attrUses = xmlSchemaItemListCreate();
14525 if (type->attrUses == NULL)
14526 goto exit_failure;
14527 uses = type->attrUses;
14528 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014529 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014530 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014531 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014532 }
14533 /*
14534 * Shrink attr. uses.
14535 */
14536 if (uses) {
14537 if (uses->nbItems == 0) {
14538 xmlSchemaItemListFree(uses);
14539 type->attrUses = NULL;
14540 }
14541 /*
14542 * TODO: We could shrink the size of the array
14543 * to fit the actual number of items.
14544 */
14545 }
14546 /*
14547 * Compute the complete wildcard.
14548 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014549 if (WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014550 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014551 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014552 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014553 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014554 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014555 if (type->attributeWildcard != NULL) {
14556 /*
14557 * Union the complete wildcard with the base wildcard.
14558 * SPEC {attribute wildcard}
14559 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
Jan Pokorný761c9e92013-11-29 23:26:27 +010014560 * and {annotation} are those of the `complete wildcard`,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014561 * and whose {namespace constraint} is the intensional union
Jan Pokorný761c9e92013-11-29 23:26:27 +010014562 * of the {namespace constraint} of the `complete wildcard`
14563 * and of the `base wildcard`, as defined in Attribute
14564 * Wildcard Union ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014565 */
14566 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14567 baseType->attributeWildcard) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000014568 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014569 } else {
14570 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014571 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14572 * then the `base wildcard`."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014573 */
14574 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillarddee23482008-04-11 12:58:43 +000014575 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014576 } else {
14577 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014578 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14579 * `complete wildcard`"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014580 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014581 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014582 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014583 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014584 /*
14585 * SPEC {attribute wildcard}
14586 * (3.1) "If the <restriction> alternative is chosen, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014587 * `complete wildcard`;"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014588 * NOOP
14589 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014590 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014591
Daniel Veillard3646d642004-06-02 19:19:14 +000014592 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014593
14594exit_failure:
14595 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014596}
14597
14598/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014599 * xmlSchemaTypeFinalContains:
14600 * @schema: the schema
14601 * @type: the type definition
14602 * @final: the final
14603 *
14604 * Evaluates if a type definition contains the given "final".
14605 * This does take "finalDefault" into account as well.
14606 *
14607 * Returns 1 if the type does containt the given "final",
14608 * 0 otherwise.
14609 */
14610static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014611xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014612{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014613 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014614 return (0);
14615 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014616 return (1);
14617 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014618 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014619}
14620
14621/**
14622 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14623 * @type: the Union Simple Type
14624 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014625 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014626 * returns NULL otherwise.
14627 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014628static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014629xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14630{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014631 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014632 if (type->memberTypes != NULL)
14633 return (type->memberTypes);
14634 else
14635 type = type->baseType;
14636 }
14637 return (NULL);
14638}
14639
14640/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014641 * xmlSchemaGetParticleTotalRangeMin:
14642 * @particle: the particle
14643 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014644 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014645 * (all and sequence) + (choice)
14646 *
14647 * Returns the minimun Effective Total Range.
14648 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014649static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014650xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014651{
14652 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014653 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014654 return (0);
14655 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014656 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014657 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014658 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014659
14660 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014661 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014662 while (part != NULL) {
14663 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14664 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014665 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014666 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014667 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014668 if (cur == 0)
14669 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014670 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014671 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014672 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014673 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014674 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014675 } else {
14676 /* <all> and <sequence> */
14677 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014678 xmlSchemaParticlePtr part =
14679 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014680
14681 if (part == NULL)
14682 return (0);
14683 do {
14684 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14685 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014686 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014687 else
14688 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014689 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014690 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014691 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014692 }
14693}
14694
Daniel Veillard15724252008-08-30 15:01:04 +000014695#if 0
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014696/**
14697 * xmlSchemaGetParticleTotalRangeMax:
14698 * @particle: the particle
14699 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014700 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014701 * (all and sequence) + (choice)
14702 *
14703 * Returns the maximum Effective Total Range.
14704 */
14705static int
14706xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14707{
14708 if ((particle->children == NULL) ||
14709 (particle->children->children == NULL))
14710 return (0);
14711 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14712 int max = -1, cur;
14713 xmlSchemaParticlePtr part =
14714 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014715
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014716 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14717 if (part->children == NULL)
14718 continue;
14719 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14720 (part->children->type == XML_SCHEMA_TYPE_ANY))
14721 cur = part->maxOccurs;
14722 else
14723 cur = xmlSchemaGetParticleTotalRangeMax(part);
14724 if (cur == UNBOUNDED)
14725 return (UNBOUNDED);
14726 if ((max < cur) || (max == -1))
14727 max = cur;
14728 }
14729 /* TODO: Handle overflows? */
14730 return (particle->maxOccurs * max);
14731 } else {
14732 /* <all> and <sequence> */
14733 int sum = 0, cur;
14734 xmlSchemaParticlePtr part =
14735 (xmlSchemaParticlePtr) particle->children->children;
14736
14737 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14738 if (part->children == NULL)
14739 continue;
14740 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14741 (part->children->type == XML_SCHEMA_TYPE_ANY))
14742 cur = part->maxOccurs;
14743 else
14744 cur = xmlSchemaGetParticleTotalRangeMax(part);
14745 if (cur == UNBOUNDED)
14746 return (UNBOUNDED);
14747 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14748 return (UNBOUNDED);
14749 sum += cur;
14750 }
14751 /* TODO: Handle overflows? */
14752 return (particle->maxOccurs * sum);
14753 }
14754}
Daniel Veillard15724252008-08-30 15:01:04 +000014755#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014756
14757/**
14758 * xmlSchemaIsParticleEmptiable:
14759 * @particle: the particle
14760 *
14761 * Schema Component Constraint: Particle Emptiable
14762 * Checks whether the given particle is emptiable.
14763 *
14764 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014765 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014766static int
14767xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14768{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014769 /*
14770 * SPEC (1) "Its {min occurs} is 0."
14771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 if ((particle == NULL) || (particle->minOccurs == 0) ||
14773 (particle->children == NULL))
14774 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014775 /*
14776 * SPEC (2) "Its {term} is a group and the minimum part of the
14777 * effective total range of that group, [...] is 0."
14778 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014779 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014780 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 return (1);
14782 }
14783 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014784}
14785
14786/**
14787 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014788 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014789 * @type: the derived simple type definition
14790 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014791 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014793 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014794 * Type Derivation OK (Simple) (cos-st-derived-OK)
14795 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014796 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014797 * derived from @baseType.
14798 *
14799 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014800 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014801static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014802xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014803 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014804 xmlSchemaTypePtr baseType,
14805 int subset)
14806{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014807 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014808 * 1 They are the same type definition.
14809 * TODO: The identy check might have to be more complex than this.
14810 */
14811 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014812 return (0);
14813 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014814 * 2.1 restriction is not in the subset, or in the {final}
14815 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014816 *
14817 * NOTE that this will be used also via "xsi:type".
14818 *
14819 * TODO: Revise this, it looks strange. How can the "type"
14820 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014821 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014822 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014823 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014824 return(-1);
14825 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014826 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014827 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014828 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829 (xmlSchemaTypeFinalContains(type->baseType,
14830 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14831 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014832 }
14833 /* 2.2 */
14834 if (type->baseType == baseType) {
14835 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014836 * 2.2.1 D's `base type definition` is B.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014837 */
14838 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014839 }
14840 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014841 * 2.2.2 D's `base type definition` is not the `ur-type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014842 * and is validly derived from B given the subset, as defined by this
14843 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014844 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014845 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014846 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014847 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014848 return (0);
14849 }
14850 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014851 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14852 * definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014853 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014854 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14855 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014856 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014857 }
14858 /*
14859 * 2.2.4 B's {variety} is union and D is validly derived from a type
14860 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014861 * defined by this constraint.
14862 *
14863 * NOTE: This seems not to involve built-in types, since there is no
14864 * built-in Union Simple Type.
14865 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014866 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014867 xmlSchemaTypeLinkPtr cur;
14868
14869 cur = baseType->memberTypes;
14870 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014871 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014872 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014873 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014874 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014875 type, cur->type, subset) == 0)
14876 {
14877 /*
14878 * It just has to be validly derived from at least one
14879 * member-type.
14880 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014881 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014882 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014883 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014884 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014885 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014886 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14887}
14888
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014889/**
14890 * xmlSchemaCheckTypeDefCircularInternal:
14891 * @pctxt: the schema parser context
14892 * @ctxtType: the type definition
14893 * @ancestor: an ancestor of @ctxtType
14894 *
14895 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014896 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014897 *
14898 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14899 * circular, 0 otherwise.
14900 */
14901static int
14902xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14903 xmlSchemaTypePtr ctxtType,
14904 xmlSchemaTypePtr ancestor)
14905{
14906 int ret;
14907
14908 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14909 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014910
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014911 if (ctxtType == ancestor) {
14912 xmlSchemaPCustomErr(pctxt,
14913 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014914 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014915 "The definition is circular", NULL);
14916 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14917 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014918 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14919 /*
14920 * Avoid inifinite recursion on circular types not yet checked.
14921 */
14922 return (0);
14923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014924 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14925 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14926 ancestor->baseType);
14927 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14928 return (ret);
14929}
14930
14931/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014932 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014933 * @item: the complex/simple type definition
14934 * @ctxt: the parser context
14935 * @name: the name
14936 *
14937 * Checks for circular type definitions.
14938 */
14939static void
14940xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014941 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014942{
14943 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014944 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14945 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014946 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014947 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14948 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014949}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014950
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014951/*
14952* Simple Type Definition Representation OK (src-simple-type) 4
14953*
14954* "4 Circular union type definition is disallowed. That is, if the
14955* <union> alternative is chosen, there must not be any entries in the
14956* memberTypes [attribute] at any depth which resolve to the component
14957* corresponding to the <simpleType>."
14958*
14959* Note that this should work on the *representation* of a component,
14960* thus assumes any union types in the member types not being yet
14961* substituted. At this stage we need the variety of the types
14962* to be already computed.
14963*/
14964static int
14965xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14966 xmlSchemaTypePtr ctxType,
14967 xmlSchemaTypeLinkPtr members)
Daniel Veillarddee23482008-04-11 12:58:43 +000014968{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014969 xmlSchemaTypeLinkPtr member;
14970 xmlSchemaTypePtr memberType;
Daniel Veillarddee23482008-04-11 12:58:43 +000014971
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014972 member = members;
14973 while (member != NULL) {
14974 memberType = member->type;
14975 while ((memberType != NULL) &&
14976 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14977 if (memberType == ctxType) {
14978 xmlSchemaPCustomErr(pctxt,
14979 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014980 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014981 "The union type definition is circular", NULL);
14982 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14983 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014984 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014985 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14986 {
14987 int res;
14988 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14989 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14990 ctxType,
14991 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14992 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14993 if (res != 0)
14994 return(res);
14995 }
14996 memberType = memberType->baseType;
14997 }
14998 member = member->next;
14999 }
15000 return(0);
15001}
15002
15003static int
15004xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15005 xmlSchemaTypePtr type)
15006{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015007 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015008 return(0);
15009 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15010 type->memberTypes));
15011}
15012
Daniel Veillard01fa6152004-06-29 17:04:39 +000015013/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015014 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015015 * @item: the complex/simple type definition
15016 * @ctxt: the parser context
15017 * @name: the name
15018 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015019 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015020 */
15021static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015022xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015023 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015024{
15025 if (typeDef == NULL)
15026 return;
15027
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015028 /*
15029 * Resolve the base type.
15030 */
15031 if (typeDef->baseType == NULL) {
15032 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15033 typeDef->base, typeDef->baseNs);
15034 if (typeDef->baseType == NULL) {
15035 xmlSchemaPResCompAttrErr(ctxt,
15036 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015037 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015038 "base", typeDef->base, typeDef->baseNs,
15039 XML_SCHEMA_TYPE_SIMPLE, NULL);
15040 return;
15041 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015042 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015043 if (WXS_IS_SIMPLE(typeDef)) {
15044 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015045 /*
15046 * Resolve the memberTypes.
15047 */
15048 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15049 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015050 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015051 /*
15052 * Resolve the itemType.
15053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015054 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15055
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015056 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015057 typeDef->base, typeDef->baseNs);
15058
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015059 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015060 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15061 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015062 typeDef->subtypes = NULL;
15063 xmlSchemaPResCompAttrErr(ctxt,
15064 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015065 WXS_BASIC_CAST typeDef, typeDef->node,
15066 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015067 XML_SCHEMA_TYPE_SIMPLE, NULL);
15068 }
15069 }
15070 return;
15071 }
Daniel Veillarddee23482008-04-11 12:58:43 +000015072 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015073 /*
15074 * The ball of letters below means, that if we have a particle
15075 * which has a QName-helper component as its {term}, we want
15076 * to resolve it...
15077 */
15078 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15079 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15080 XML_SCHEMA_TYPE_PARTICLE) &&
15081 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15082 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15083 XML_SCHEMA_EXTRA_QNAMEREF))
15084 {
15085 xmlSchemaQNameRefPtr ref =
15086 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15087 xmlSchemaModelGroupDefPtr groupDef;
15088
15089 /*
15090 * URGENT TODO: Test this.
15091 */
15092 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15093 /*
15094 * Resolve the MG definition reference.
15095 */
15096 groupDef =
15097 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15098 ref->itemType, ref->name, ref->targetNamespace);
15099 if (groupDef == NULL) {
15100 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15101 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15102 "ref", ref->name, ref->targetNamespace, ref->itemType,
15103 NULL);
15104 /* Remove the particle. */
15105 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15106 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15107 /* Remove the particle. */
15108 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15109 else {
15110 /*
15111 * Assign the MG definition's {model group} to the
15112 * particle's {term}.
15113 */
15114 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
Daniel Veillarddee23482008-04-11 12:58:43 +000015115
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015116 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15117 /*
15118 * SPEC cos-all-limited (1.2)
15119 * "1.2 the {term} property of a particle with
15120 * {max occurs}=1 which is part of a pair which constitutes
15121 * the {content type} of a complex type definition."
15122 */
15123 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15124 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15125 /* TODO: error code */
15126 XML_SCHEMAP_COS_ALL_LIMITED,
15127 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15128 "The particle's {max occurs} must be 1, since the "
15129 "reference resolves to an 'all' model group",
15130 NULL, NULL);
15131 }
15132 }
15133 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015134 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015135}
15136
15137
15138
15139/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015140 * xmlSchemaCheckSTPropsCorrect:
15141 * @ctxt: the schema parser context
15142 * @type: the simple type definition
15143 *
15144 * Checks st-props-correct.
15145 *
15146 * Returns 0 if the properties are correct,
15147 * if not, a positive error code and -1 on internal
15148 * errors.
15149 */
15150static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015151xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015152 xmlSchemaTypePtr type)
15153{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015154 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015155 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015156
Daniel Veillardc0826a72004-08-10 14:17:33 +000015157 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 /*
15159 * Schema Component Constraint: Simple Type Definition Properties Correct
15160 *
15161 * NOTE: This is somehow redundant, since we actually built a simple type
15162 * to have all the needed information; this acts as an self test.
15163 */
Jan Pokorný761c9e92013-11-29 23:26:27 +010015164 /* Base type: If the datatype has been `derived` by `restriction`
15165 * then the Simple Type Definition component from which it is `derived`,
15166 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015167 */
15168 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015169 /*
15170 * TODO: Think about: "modulo the impact of Missing
Jan Pokorný761c9e92013-11-29 23:26:27 +010015171 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015172 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015173 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015174 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015175 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015176 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015178
Daniel Veillard01fa6152004-06-29 17:04:39 +000015179 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015180 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015181 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015182 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015183 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015184 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015185 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015187 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188 }
Toyoda Eizi8bb12982011-08-04 16:40:48 +080015189 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15190 (WXS_IS_RESTRICTION(type) == 0) &&
15191 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15192 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015193 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015194 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015195 WXS_BASIC_CAST type, NULL,
Daniel Veillardbf9c1da2008-08-26 07:46:42 +000015196 "A type, derived by list or union, must have "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015197 "the simple ur-type definition as base type, not '%s'",
15198 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015199 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15201 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015202 /*
15203 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015204 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015205 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15206 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015207 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015208 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015209 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015210 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015211 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15212 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015213 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015215 /*
15216 * 3 The {final} of the {base type definition} must not contain restriction.
15217 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015218 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015219 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15220 xmlSchemaPCustomErr(ctxt,
15221 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015222 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015223 "The 'final' of its base type '%s' must not contain "
15224 "'restriction'",
15225 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015226 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015227 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015228 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015229
15230 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015231 * 2 All simple type definitions must be derived ultimately from the `simple
15232 * ur-type definition` (so circular definitions are disallowed). That is, it
15233 * must be possible to reach a built-in primitive datatype or the `simple
15234 * ur-type definition` by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015235 *
15236 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015237 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015238 return (0);
15239}
15240
15241/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015242 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015243 * @ctxt: the schema parser context
15244 * @type: the simple type definition
15245 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015246 * Schema Component Constraint:
15247 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15248
15249 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015250 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015251 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015252 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015253 * a positive error code otherwise.
15254 */
15255static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015256xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015257 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015258{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015259 xmlChar *str = NULL;
15260
Daniel Veillard01fa6152004-06-29 17:04:39 +000015261 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015262 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15263 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015264 return (-1);
15265 }
15266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015267 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015268 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015269 /*
15270 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015271 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015272 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015273 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015274 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015275 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015276 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015277 "The base type '%s' is not an atomic simple type",
15278 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015279 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015280 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15281 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015282 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015283 * restriction.
15284 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015285 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015286 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015287 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015289 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015290 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015291 "The final of its base type '%s' must not contain 'restriction'",
15292 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015293 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015294 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15295 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015296
15297 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015298 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015299 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015300 * Primitive datatypes.
15301 */
15302 if (type->facets != NULL) {
15303 xmlSchemaFacetPtr facet;
15304 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015305
Daniel Veillard01fa6152004-06-29 17:04:39 +000015306 primitive = xmlSchemaGetPrimitiveType(type);
15307 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015308 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015310 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015311 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015312 facet = type->facets;
15313 do {
15314 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015315 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015316 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015317 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015318 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015319 }
15320 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015321 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015322 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015323 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015324 }
15325 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015326 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15327 * of the {base type definition} (call this BF),then the DF's {value}
15328 * must be a valid restriction of BF's {value} as defined in
15329 * [XML Schemas: Datatypes]."
15330 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015331 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015332 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015333 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015334 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015335 xmlSchemaTypePtr itemType = NULL;
15336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015337 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015338 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015339 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15340 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015341 return (-1);
15342 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015343 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015344 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015345 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015346 * 2.1 The {item type definition} must have a {variety} of atomic or
15347 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015348 * must be atomic).
15349 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015350 if ((! WXS_IS_ATOMIC(itemType)) &&
15351 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015353 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015354 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015355 "The item type '%s' does not have a variety of atomic or union",
15356 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015357 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015358 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015359 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015360 xmlSchemaTypeLinkPtr member;
15361
15362 member = itemType->memberTypes;
15363 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015364 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015365 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015366 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015367 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015368 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015369 "member type '%s' of this item type is not atomic",
15370 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015371 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015372 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15373 }
15374 member = member->next;
15375 }
15376 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015377
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015378 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015379 xmlSchemaFacetPtr facet;
15380 /*
15381 * This is the case if we have: <simpleType><list ..
15382 */
15383 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015384 * 2.3.1
15385 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015386 * contain list.
15387 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015388 if (xmlSchemaTypeFinalContains(itemType,
15389 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15390 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015391 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015392 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393 "The final of its item type '%s' must not contain 'list'",
15394 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015395 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015396 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15397 }
15398 /*
15399 * 2.3.1.2 The {facets} must only contain the whiteSpace
15400 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015401 * OPTIMIZE TODO: the S4S already disallows any facet
15402 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015403 */
15404 if (type->facets != NULL) {
15405 facet = type->facets;
15406 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015407 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015408 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015409 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015410 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015411 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15412 }
15413 facet = facet->next;
15414 } while (facet != NULL);
15415 }
15416 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015417 * MAYBE TODO: (Hmm, not really) Datatypes states:
Jan Pokorný761c9e92013-11-29 23:26:27 +010015418 * A `list` datatype can be `derived` from an `atomic` datatype
15419 * whose `lexical space` allows space (such as string or anyURI)or
15420 * a `union` datatype any of whose {member type definitions}'s
15421 * `lexical space` allows space.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015422 */
15423 } else {
15424 /*
15425 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015426 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015427 */
15428 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015430 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15431 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015432 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015433 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015434 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015435 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015436 "The base type '%s' must be a list type",
15437 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015438 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015439 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15440 }
15441 /*
15442 * 2.3.2.2 The {final} of the {base type definition} must not
15443 * contain restriction.
15444 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015445 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015446 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015447 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015448 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015449 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015450 "The 'final' of the base type '%s' must not contain 'restriction'",
15451 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015452 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015453 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15454 }
15455 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015456 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015457 * from the {base type definition}'s {item type definition} given
Jan Pokorný761c9e92013-11-29 23:26:27 +010015458 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015459 */
15460 {
15461 xmlSchemaTypePtr baseItemType;
15462
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015463 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015464 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015465 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15466 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015467 return (-1);
15468 }
15469 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015470 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015471 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015472 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015473 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015474 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015475 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015476 "The item type '%s' is not validly derived from "
15477 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015478 xmlSchemaGetComponentQName(&str, itemType),
15479 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15480 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015481
15482 FREE_AND_NULL(str)
15483 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015484 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015485 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15486 }
15487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015488
Daniel Veillard01fa6152004-06-29 17:04:39 +000015489 if (type->facets != NULL) {
15490 xmlSchemaFacetPtr facet;
15491 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015492 /*
15493 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015494 * and enumeration facet components are allowed among the {facets}.
15495 */
15496 facet = type->facets;
15497 do {
15498 switch (facet->type) {
15499 case XML_SCHEMA_FACET_LENGTH:
15500 case XML_SCHEMA_FACET_MINLENGTH:
15501 case XML_SCHEMA_FACET_MAXLENGTH:
15502 case XML_SCHEMA_FACET_WHITESPACE:
15503 /*
15504 * TODO: 2.5.1.2 List datatypes
Jan Pokorný761c9e92013-11-29 23:26:27 +010015505 * The value of `whiteSpace` is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015506 */
15507 case XML_SCHEMA_FACET_PATTERN:
15508 case XML_SCHEMA_FACET_ENUMERATION:
15509 break;
15510 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015511 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015512 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015513 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015514 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015515 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015516 * invalid facets.
15517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015518 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015519 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015520 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015521 facet = facet->next;
15522 } while (facet != NULL);
15523 if (ok == 0)
15524 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15525 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015526 * SPEC (2.3.2.5) (same as 1.3.2)
15527 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015528 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015529 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015530 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015531 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015532 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015533 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015534 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015535 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015536 * atomic or list.
15537 */
15538 xmlSchemaTypeLinkPtr member;
15539
15540 member = type->memberTypes;
15541 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015542 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015543 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015544
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015545 if ((! WXS_IS_ATOMIC(member->type)) &&
15546 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015547 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015548 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015549 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015550 "The member type '%s' is neither an atomic, nor a list type",
15551 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015552 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015553 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15554 }
15555 member = member->next;
15556 }
15557 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015558 * 3.3.1 If the {base type definition} is the `simple ur-type
15559 * definition`
Daniel Veillard01fa6152004-06-29 17:04:39 +000015560 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015561 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015562 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015563 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015564 * {final} which does not contain union.
15565 */
15566 member = type->memberTypes;
15567 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015568 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015569 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015570 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015571 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015572 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015573 "The 'final' of member type '%s' contains 'union'",
15574 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015575 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015576 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15577 }
15578 member = member->next;
15579 }
15580 /*
15581 * 3.3.1.2 The {facets} must be empty.
15582 */
15583 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015584 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015586 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015587 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015588 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15589 }
15590 } else {
15591 /*
15592 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015593 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015594 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015595 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015596 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015597 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015598 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015599 "The base type '%s' is not a union type",
15600 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015601 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015602 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15603 }
15604 /*
15605 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15606 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015607 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015608 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015609 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015610 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015611 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015612 "The 'final' of its base type '%s' must not contain 'restriction'",
15613 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015614 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015615 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15616 }
15617 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015618 * 3.3.2.3 The {member type definitions}, in order, must be validly
15619 * derived from the corresponding type definitions in the {base
15620 * type definition}'s {member type definitions} given the empty set,
Jan Pokorný761c9e92013-11-29 23:26:27 +010015621 * as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015622 */
15623 {
15624 xmlSchemaTypeLinkPtr baseMember;
15625
15626 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015627 * OPTIMIZE: if the type is restricting, it has no local defined
15628 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015629 * thus a check for equality can be skipped.
15630 */
15631 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015632 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015633 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015634 * types of it's base type. This check seems not necessary with
15635 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015636 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015637 */
15638 if (type->memberTypes != NULL) {
15639 member = type->memberTypes;
15640 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015641 if ((member == NULL) && (baseMember != NULL)) {
15642 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15643 "different number of member types in base");
15644 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015645 while (member != NULL) {
15646 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015647 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15648 "different number of member types in base");
Daniel Veillard14b56432006-03-09 18:41:40 +000015649 } else if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015650 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015651 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015652 xmlChar *strBMT = NULL, *strBT = NULL;
15653
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015655 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015656 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015657 "The member type %s is not validly "
15658 "derived from its corresponding member "
15659 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015660 xmlSchemaGetComponentQName(&str, member->type),
15661 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15662 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015663 FREE_AND_NULL(str)
15664 FREE_AND_NULL(strBMT)
15665 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015666 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015667 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015668 member = member->next;
Daniel Veillardd44b9362009-09-07 12:15:08 +020015669 if (baseMember != NULL)
15670 baseMember = baseMember->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015671 }
15672 }
15673 }
15674 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015676 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015677 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015678 if (type->facets != NULL) {
15679 xmlSchemaFacetPtr facet;
15680 int ok = 1;
15681
15682 facet = type->facets;
15683 do {
15684 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15685 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015687 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015688 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015689 ok = 0;
15690 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015691 facet = facet->next;
15692 } while (facet != NULL);
15693 if (ok == 0)
15694 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015695
Daniel Veillard01fa6152004-06-29 17:04:39 +000015696 }
15697 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015698 * SPEC (3.3.2.5) (same as 1.3.2)
15699 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015700 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015701 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015702 */
15703 }
15704 }
15705
15706 return (0);
15707}
15708
15709/**
15710 * xmlSchemaCheckSRCSimpleType:
15711 * @ctxt: the schema parser context
15712 * @type: the simple type definition
15713 *
Daniel Veillarddee23482008-04-11 12:58:43 +000015714 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015715 *
15716 * Returns 0 if the constraints are satisfied,
15717 * if not a positive error code and -1 on internal
15718 * errors.
15719 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015720#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015721static int
15722xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15723 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015724{
15725 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015726 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015727 * must satisfy the conditions set out in Constraints on Simple Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010015728 * Definition Schema Components ($3.14.6).
Daniel Veillarddee23482008-04-11 12:58:43 +000015729 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015730 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015731 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015732 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015733 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015734 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015735 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015736 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015737 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000015738 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015739 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015740 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015741 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015742 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015743 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015744 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015745 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015746 */
Daniel Veillarddee23482008-04-11 12:58:43 +000015747 } else if (WXS_IS_UNION(type)) {
15748 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015749 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015751 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015752 return (0);
15753}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015754#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015755
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015756static int
15757xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15758{
15759 if (ctxt->vctxt == NULL) {
15760 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15761 if (ctxt->vctxt == NULL) {
15762 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015763 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015764 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015765 "failed to create a temp. validation context.\n",
15766 NULL, NULL);
15767 return (-1);
15768 }
15769 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015770 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015771 ctxt->error, ctxt->warning, ctxt->errCtxt);
15772 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15773 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015774 }
15775 return (0);
15776}
15777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778static int
15779xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15780 xmlNodePtr node,
15781 xmlSchemaTypePtr type,
15782 const xmlChar *value,
15783 xmlSchemaValPtr *retVal,
15784 int fireErrors,
15785 int normalize,
15786 int isNormalized);
15787
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015788/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015790 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015791 * @type: the simple type definition
15792 * @value: the default value
15793 * @node: an optional node (the holder of the value)
15794 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015795 * Schema Component Constraint: Element Default Valid (Immediate)
15796 * (cos-valid-default)
15797 * This will be used by the parser only. For the validator there's
15798 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015799 *
15800 * Returns 0 if the constraints are satisfied,
15801 * if not, a positive error code and -1 on internal
15802 * errors.
15803 */
15804static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015805xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15806 xmlNodePtr node,
15807 xmlSchemaTypePtr type,
15808 const xmlChar *value,
15809 xmlSchemaValPtr *val)
15810{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015811 int ret = 0;
15812
15813 /*
15814 * cos-valid-default:
15815 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015816 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015817 * definition the appropriate case among the following must be true:
15818 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015819 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015820 /*
15821 * Complex type.
15822 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015823 * SPEC (2.1) "its {content type} must be a simple type definition
15824 * or mixed."
15825 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010015826 * type}'s particle must be `emptiable` as defined by
15827 * Particle Emptiable ($3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015828 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015829 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15830 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015831 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015832 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015833 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015834 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015835 "For a string to be a valid default, the type definition "
15836 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015837 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015838 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15839 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015840 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015841 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015842 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010015843 * must be `valid` with respect to that definition as defined by String
15844 * Valid ($3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015845 *
15846 * AND
15847 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015848 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010015849 * string must be `valid` with respect to that simple type definition
15850 * as defined by String Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015851 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015852 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015853 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015854 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015855 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015856 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015857 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015858 else
15859 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015860
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015861 if (ret < 0) {
15862 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15863 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015865
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015866 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015867}
15868
15869/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015870 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015871 * @ctxt: the schema parser context
15872 * @type: the complex type definition
15873 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015874 *.(4.6) Constraints on Complex Type Definition Schema Components
15875 * Schema Component Constraint:
15876 * Complex Type Definition Properties Correct (ct-props-correct)
15877 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015878 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015879 * Returns 0 if the constraints are satisfied, a positive
15880 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015881 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015882static int
15883xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15884 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015885{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015886 /*
15887 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15888 *
15889 * SPEC (1) "The values of the properties of a complex type definition must
15890 * be as described in the property tableau in The Complex Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010015891 * Schema Component ($3.4.1), modulo the impact of Missing
15892 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015893 */
15894 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015895 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015896 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015897 /*
15898 * SPEC (2) "If the {base type definition} is a simple type definition,
15899 * the {derivation method} must be extension."
15900 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015901 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015902 XML_SCHEMAP_SRC_CT_1,
Daniel Veillarddee23482008-04-11 12:58:43 +000015903 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015904 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015905 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015906 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015907 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015908 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015909 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15910 * definition`. That is, it must be possible to reach the `ur-type
15911 * definition` by repeatedly following the {base type definition}."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015912 *
15913 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015914 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015915 /*
15916 * NOTE that (4) and (5) need the following:
15917 * - attribute uses need to be already inherited (apply attr. prohibitions)
15918 * - attribute group references need to be expanded already
15919 * - simple types need to be typefixed already
Daniel Veillarddee23482008-04-11 12:58:43 +000015920 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015921 if (type->attrUses &&
15922 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15923 {
15924 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15925 xmlSchemaAttributeUsePtr use, tmp;
15926 int i, j, hasId = 0;
15927
15928 for (i = uses->nbItems -1; i >= 0; i--) {
15929 use = uses->items[i];
Daniel Veillarddee23482008-04-11 12:58:43 +000015930
15931 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015932 * SPEC ct-props-correct
15933 * (4) "Two distinct attribute declarations in the
15934 * {attribute uses} must not have identical {name}s and
15935 * {target namespace}s."
15936 */
15937 if (i > 0) {
15938 for (j = i -1; j >= 0; j--) {
15939 tmp = uses->items[j];
15940 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15941 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15942 (WXS_ATTRUSE_DECL_TNS(use) ==
15943 WXS_ATTRUSE_DECL_TNS(tmp)))
15944 {
15945 xmlChar *str = NULL;
15946
15947 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15948 XML_SCHEMAP_AG_PROPS_CORRECT,
15949 NULL, WXS_BASIC_CAST type,
15950 "Duplicate %s",
15951 xmlSchemaGetComponentDesignation(&str, use),
15952 NULL);
15953 FREE_AND_NULL(str);
15954 /*
15955 * Remove the duplicate.
15956 */
15957 if (xmlSchemaItemListRemove(uses, i) == -1)
15958 goto exit_failure;
15959 goto next_use;
15960 }
15961 }
15962 }
15963 /*
15964 * SPEC ct-props-correct
15965 * (5) "Two distinct attribute declarations in the
15966 * {attribute uses} must not have {type definition}s which
15967 * are or are derived from ID."
15968 */
15969 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15970 if (xmlSchemaIsDerivedFromBuiltInType(
15971 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000015972 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015973 if (hasId) {
15974 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000015975
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015976 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15977 XML_SCHEMAP_AG_PROPS_CORRECT,
15978 NULL, WXS_BASIC_CAST type,
15979 "There must not exist more than one attribute "
15980 "declaration of type 'xs:ID' "
15981 "(or derived from 'xs:ID'). The %s violates this "
15982 "constraint",
15983 xmlSchemaGetComponentDesignation(&str, use),
15984 NULL);
15985 FREE_AND_NULL(str);
15986 if (xmlSchemaItemListRemove(uses, i) == -1)
15987 goto exit_failure;
15988 }
Daniel Veillarddee23482008-04-11 12:58:43 +000015989
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015990 hasId = 1;
15991 }
15992 }
15993next_use: {}
15994 }
15995 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015996 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015997exit_failure:
15998 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015999}
16000
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016001static int
16002xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16003 xmlSchemaTypePtr typeB)
16004{
16005 /*
16006 * TODO: This should implement component-identity
16007 * in the future.
16008 */
16009 if ((typeA == NULL) || (typeB == NULL))
16010 return (0);
16011 return (typeA == typeB);
16012}
16013
16014/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016015 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016016 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016017 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016018 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016019 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016020 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016021 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016022 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16023 *
16024 * STATUS: completed
16025 *
16026 * Returns 0 if the constraints are satisfied, or 1
16027 * if not.
16028 */
16029static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016030xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016031 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016032 xmlSchemaTypePtr baseType,
16033 int set)
16034{
16035 int equal = xmlSchemaAreEqualTypes(type, baseType);
16036 /* TODO: Error codes. */
16037 /*
16038 * SPEC "For a complex type definition (call it D, for derived)
16039 * to be validly derived from a type definition (call this
16040 * B, for base) given a subset of {extension, restriction}
16041 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016043 if (! equal) {
16044 /*
16045 * SPEC (1) "If B and D are not the same type definition, then the
16046 * {derivation method} of D must not be in the subset."
16047 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016048 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16049 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016050 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016051 } else {
16052 /*
16053 * SPEC (2.1) "B and D must be the same type definition."
16054 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016055 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016056 }
16057 /*
16058 * SPEC (2.2) "B must be D's {base type definition}."
16059 */
16060 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016061 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016062 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016063 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16064 * definition`."
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016065 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016066 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016067 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016068
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016069 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016070 /*
16071 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16072 * must be validly derived from B given the subset as defined by this
16073 * constraint."
16074 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016075 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016076 baseType, set));
16077 } else {
16078 /*
16079 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16080 * must be validly derived from B given the subset as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016081 * Derivation OK (Simple) ($3.14.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016082 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016083 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016084 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016085 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016086}
16087
16088/**
16089 * xmlSchemaCheckCOSDerivedOK:
16090 * @type: the derived simple type definition
16091 * @baseType: the base type definition
16092 *
16093 * Calls:
16094 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016095 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016096 * Checks wheter @type can be validly derived from @baseType.
16097 *
16098 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016099 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016100static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016101xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016102 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016103 xmlSchemaTypePtr baseType,
16104 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016105{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016106 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016107 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016108 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016109 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016110}
16111
William M. Brack2f2a6632004-08-20 23:09:47 +000016112/**
16113 * xmlSchemaCheckCOSCTExtends:
16114 * @ctxt: the schema parser context
16115 * @type: the complex type definition
16116 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016118 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016119 * Derivation Valid (Extension) (cos-ct-extends)
16120 *
16121 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016122 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016123 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016124 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000016125 *
16126 * Returns 0 if the constraints are satisfied, a positive
16127 * error code if not and -1 if an internal error occured.
16128 */
16129static int
16130xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16131 xmlSchemaTypePtr type)
16132{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016133 xmlSchemaTypePtr base = type->baseType;
16134 /*
16135 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16136 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000016137 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016138 /*
16139 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 * then all of the following must be true:"
16141 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016142 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016143 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016144 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016145 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016146 */
16147 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16148 xmlSchemaPCustomErr(ctxt,
16149 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016150 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016151 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016152 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016153 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16154 }
Daniel Veillarddee23482008-04-11 12:58:43 +000016155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016156 /*
16157 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16158 * since they are automatically satisfied through the
16159 * inheriting mechanism.
16160 * Note that even if redefining components, the inheriting mechanism
16161 * is used.
16162 */
16163#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016164 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016165 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016166 * uses}
16167 * of the complex type definition itself, that is, for every attribute
16168 * use in the {attribute uses} of the {base type definition}, there
16169 * must be an attribute use in the {attribute uses} of the complex
16170 * type definition itself whose {attribute declaration} has the same
16171 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016172 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016173 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016174 if (base->attrUses != NULL) {
16175 int i, j, found;
16176 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016177
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016178 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16179 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16180 found = 0;
16181 if (type->attrUses != NULL) {
16182 use = (WXS_LIST_CAST type->attrUses)->items[j];
16183 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16184 {
16185 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16186 WXS_ATTRUSE_DECL_NAME(buse)) &&
16187 (WXS_ATTRUSE_DECL_TNS(use) ==
16188 WXS_ATTRUSE_DECL_TNS(buse)) &&
16189 (WXS_ATTRUSE_TYPEDEF(use) ==
16190 WXS_ATTRUSE_TYPEDEF(buse))
16191 {
16192 found = 1;
16193 break;
16194 }
16195 }
16196 }
16197 if (! found) {
16198 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016199
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016200 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16201 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16202 NULL, WXS_BASIC_CAST type,
Daniel Veillarddee23482008-04-11 12:58:43 +000016203 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016204 * TODO: The report does not indicate that also the
16205 * type needs to be the same.
16206 */
16207 "This type is missing a matching correspondent "
16208 "for its {base type}'s %s in its {attribute uses}",
16209 xmlSchemaGetComponentDesignation(&str,
16210 buse->children),
16211 NULL);
16212 FREE_AND_NULL(str)
16213 }
16214 }
16215 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016216 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16218 * definition must also have one, and the base type definition's
16219 * {attribute wildcard}'s {namespace constraint} must be a subset
16220 * of the complex type definition's {attribute wildcard}'s {namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010016221 * constraint}, as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016222 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016223
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016224 /*
16225 * MAYBE TODO: Enable if ever needed. But this will be needed only
16226 * if created the type via a schema construction API.
16227 */
16228 if (base->attributeWildcard != NULL) {
16229 if (type->attributeWilcard == NULL) {
16230 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016232 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16233 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16234 NULL, type,
16235 "The base %s has an attribute wildcard, "
16236 "but this type is missing an attribute wildcard",
16237 xmlSchemaGetComponentDesignation(&str, base));
16238 FREE_AND_NULL(str)
16239
16240 } else if (xmlSchemaCheckCOSNSSubset(
16241 base->attributeWildcard, type->attributeWildcard))
16242 {
16243 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016244
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016245 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16246 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16247 NULL, type,
16248 "The attribute wildcard is not a valid "
16249 "superset of the one in the base %s",
16250 xmlSchemaGetComponentDesignation(&str, base));
16251 FREE_AND_NULL(str)
16252 }
16253 }
16254#endif
16255 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016256 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016257 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016258 if ((type->contentTypeDef != NULL) &&
16259 (type->contentTypeDef == base->contentTypeDef)) {
16260 /*
16261 * SPEC (1.4.1) "The {content type} of the {base type definition}
16262 * and the {content type} of the complex type definition itself
16263 * must be the same simple type definition"
16264 * PASS
16265 */
16266 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16267 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16268 /*
16269 * SPEC (1.4.2) "The {content type} of both the {base type
16270 * definition} and the complex type definition itself must
16271 * be empty."
16272 * PASS
16273 */
16274 } else {
16275 /*
16276 * SPEC (1.4.3) "All of the following must be true:"
16277 */
16278 if (type->subtypes == NULL) {
16279 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016280 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016281 * definition itself must specify a particle.
16282 */
16283 xmlSchemaPCustomErr(ctxt,
16284 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016285 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016286 "The content type must specify a particle", NULL);
16287 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16288 }
16289 /*
16290 * SPEC (1.4.3.2) "One of the following must be true:"
16291 */
16292 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16293 /*
16294 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16295 * definition} must be empty.
16296 * PASS
16297 */
16298 } else {
16299 /*
16300 * SPEC (1.4.3.2.2) "All of the following must be true:"
16301 */
16302 if ((type->contentType != base->contentType) ||
16303 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16304 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16305 /*
16306 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16307 * or both must be element-only."
16308 */
16309 xmlSchemaPCustomErr(ctxt,
16310 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016311 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016312 "The content type of both, the type and its base "
16313 "type, must either 'mixed' or 'element-only'", NULL);
16314 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016316 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016317 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016318 * complex type definition must be a `valid extension`
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016319 * of the {base type definition}'s particle, as defined
Jan Pokorný761c9e92013-11-29 23:26:27 +010016320 * in Particle Valid (Extension) ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016321 *
16322 * NOTE that we won't check "Particle Valid (Extension)",
16323 * since it is ensured by the derivation process in
16324 * xmlSchemaTypeFixup(). We need to implement this when heading
16325 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016326 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016327 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016328 }
16329 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016330 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016332 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016333 } else {
16334 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016335 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016336 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016337 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 if (type->contentTypeDef != base) {
16339 /*
16340 * SPEC (2.1) "The {content type} must be the same simple type
16341 * definition."
16342 */
16343 xmlSchemaPCustomErr(ctxt,
16344 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016345 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 "The content type must be the simple base type", NULL);
16347 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16348 }
16349 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16350 /*
16351 * SPEC (2.2) "The {final} of the {base type definition} must not
16352 * contain extension"
16353 * NOTE that this is the same as (1.1).
16354 */
16355 xmlSchemaPCustomErr(ctxt,
16356 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016357 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 "The 'final' of the base type definition "
16359 "contains 'extension'", NULL);
16360 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016361 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016362 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016363 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016364}
16365
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016366/**
16367 * xmlSchemaCheckDerivationOKRestriction:
16368 * @ctxt: the schema parser context
16369 * @type: the complex type definition
16370 *
16371 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016372 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016373 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16374 *
16375 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016376 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016377 * (5.4.2) ???
16378 *
16379 * ATTENTION:
16380 * In XML Schema 1.1 this will be:
16381 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 *
16383 * Returns 0 if the constraints are satisfied, a positive
16384 * error code if not and -1 if an internal error occured.
16385 */
16386static int
16387xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16388 xmlSchemaTypePtr type)
16389{
16390 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016391
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016393 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016395 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016396 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016397 if (! WXS_IS_COMPLEX(base)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000016398 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016399 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16400 type->node, WXS_BASIC_CAST type,
16401 "The base type must be a complex type", NULL, NULL);
16402 return(ctxt->err);
16403 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16405 /*
16406 * SPEC (1) "The {base type definition} must be a complex type
16407 * definition whose {final} does not contain restriction."
16408 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016409 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016410 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16411 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016412 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016413 "contains 'restriction'", NULL, NULL);
16414 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016415 }
16416 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016417 * SPEC (2), (3) and (4)
16418 * Those are handled in a separate function, since the
16419 * same constraints are needed for redefinition of
16420 * attribute groups as well.
16421 */
16422 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16423 XML_SCHEMA_ACTION_DERIVE,
16424 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16425 type->attrUses, base->attrUses,
16426 type->attributeWildcard,
16427 base->attributeWildcard) == -1)
16428 {
16429 return(-1);
16430 }
16431 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 * SPEC (5) "One of the following must be true:"
16433 */
16434 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16435 /*
16436 * SPEC (5.1) "The {base type definition} must be the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016437 * `ur-type definition`."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016438 * PASS
16439 */
16440 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16441 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16442 /*
16443 * SPEC (5.2.1) "The {content type} of the complex type definition
16444 * must be a simple type definition"
16445 *
16446 * SPEC (5.2.2) "One of the following must be true:"
16447 */
16448 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016449 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16450 {
16451 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016452 /*
16453 * SPEC (5.2.2.1) "The {content type} of the {base type
16454 * definition} must be a simple type definition from which
16455 * the {content type} is validly derived given the empty
Jan Pokorný761c9e92013-11-29 23:26:27 +010016456 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016457 *
16458 * ATTENTION TODO: This seems not needed if the type implicitely
16459 * derived from the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +000016460 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016461 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016462 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16463 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016464 if (err != 0) {
16465 xmlChar *strA = NULL, *strB = NULL;
16466
16467 if (err == -1)
16468 return(-1);
16469 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16470 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16471 NULL, WXS_BASIC_CAST type,
16472 "The {content type} %s is not validly derived from the "
16473 "base type's {content type} %s",
16474 xmlSchemaGetComponentDesignation(&strA,
16475 type->contentTypeDef),
16476 xmlSchemaGetComponentDesignation(&strB,
16477 base->contentTypeDef));
16478 FREE_AND_NULL(strA);
16479 FREE_AND_NULL(strB);
16480 return(ctxt->err);
16481 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016482 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16483 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016484 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016485 /*
16486 * SPEC (5.2.2.2) "The {base type definition} must be mixed
Jan Pokorný761c9e92013-11-29 23:26:27 +010016487 * and have a particle which is `emptiable` as defined in
16488 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016489 * PASS
16490 */
16491 } else {
16492 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016493 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16494 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016495 "The content type of the base type must be either "
16496 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016497 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016498 }
16499 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16500 /*
16501 * SPEC (5.3.1) "The {content type} of the complex type itself must
16502 * be empty"
16503 */
16504 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016506 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016507 * definition} must also be empty."
16508 * PASS
16509 */
16510 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16511 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16512 xmlSchemaIsParticleEmptiable(
16513 (xmlSchemaParticlePtr) base->subtypes)) {
16514 /*
16515 * SPEC (5.3.2.2) "The {content type} of the {base type
16516 * definition} must be elementOnly or mixed and have a particle
Jan Pokorný761c9e92013-11-29 23:26:27 +010016517 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016518 * PASS
16519 */
16520 } else {
16521 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016522 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16523 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016524 "The content type of the base type must be either "
16525 "empty or 'mixed' (or 'elements-only') and an emptiable "
16526 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016527 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 }
16529 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016530 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016531 /*
16532 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16533 * itself must be element-only"
Daniel Veillarddee23482008-04-11 12:58:43 +000016534 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016535 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016536 /*
16537 * SPEC (5.4.1.2) "The {content type} of the complex type
16538 * definition itself and of the {base type definition} must be
16539 * mixed"
16540 */
16541 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016542 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16543 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016544 "If the content type is 'mixed', then the content type of the "
16545 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016546 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016547 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016548 /*
16549 * SPEC (5.4.2) "The particle of the complex type definition itself
Jan Pokorný761c9e92013-11-29 23:26:27 +010016550 * must be a `valid restriction` of the particle of the {content
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016551 * type} of the {base type definition} as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010016552 * (Restriction) ($3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016553 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016554 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 } else {
16557 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016558 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16559 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016560 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016561 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016562 }
16563 return (0);
16564}
16565
16566/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016567 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016568 * @ctxt: the schema parser context
16569 * @type: the complex type definition
16570 *
16571 * (3.4.6) Constraints on Complex Type Definition Schema Components
16572 *
16573 * Returns 0 if the constraints are satisfied, a positive
16574 * error code if not and -1 if an internal error occured.
16575 */
16576static int
16577xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16578 xmlSchemaTypePtr type)
16579{
16580 int ret;
16581 /*
16582 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016583 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016584 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16585 if (ret != 0)
16586 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016587 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016588 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16589 else
16590 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16591 return (ret);
16592}
16593
16594/**
16595 * xmlSchemaCheckSRCCT:
16596 * @ctxt: the schema parser context
16597 * @type: the complex type definition
16598 *
16599 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016600 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016601 * Complex Type Definition Representation OK (src-ct)
16602 *
16603 * Returns 0 if the constraints are satisfied, a positive
16604 * error code if not and -1 if an internal error occured.
16605 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016606static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016607xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016608 xmlSchemaTypePtr type)
16609{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016610 xmlSchemaTypePtr base;
16611 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016612
16613 /*
16614 * TODO: Adjust the error codes here, as I used
16615 * XML_SCHEMAP_SRC_CT_1 only yet.
16616 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016617 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016618 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016619 /*
16620 * 1 If the <complexContent> alternative is chosen, the type definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010016621 * `resolved` to by the `actual value` of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016622 * must be a complex type definition;
16623 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016624 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016625 xmlChar *str = NULL;
16626 xmlSchemaPCustomErr(ctxt,
16627 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016628 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016629 "If using <complexContent>, the base type is expected to be "
16630 "a complex type. The base type '%s' is a simple type",
16631 xmlSchemaFormatQName(&str, base->targetNamespace,
16632 base->name));
16633 FREE_AND_NULL(str)
16634 return (XML_SCHEMAP_SRC_CT_1);
16635 }
16636 } else {
16637 /*
16638 * SPEC
16639 * 2 If the <simpleContent> alternative is chosen, all of the
16640 * following must be true:
Jan Pokorný761c9e92013-11-29 23:26:27 +010016641 * 2.1 The type definition `resolved` to by the `actual value` of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016642 * base [attribute] must be one of the following:
16643 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016644 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016645 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016646 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016647 /*
16648 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016649 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016650 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016651 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016652 xmlSchemaPCustomErr(ctxt,
16653 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016654 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016655 "If using <simpleContent> and <restriction>, the base "
16656 "type must be a complex type. The base type '%s' is "
16657 "a simple type",
16658 xmlSchemaFormatQName(&str, base->targetNamespace,
16659 base->name));
16660 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016661 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016662 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016663 } else {
16664 /* Base type is a complex type. */
16665 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16666 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16667 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016668 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016669 * simple type definition;
16670 * PASS
16671 */
16672 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016673 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016674 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016675 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016676 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016677 type->name);
16678 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016679 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016680 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016681 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016682
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016683 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016684 * 2.1.2 only if the <restriction> alternative is also
16685 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016686 * is mixed and a particle emptiable.
16687 */
16688 if (! xmlSchemaIsParticleEmptiable(
16689 (xmlSchemaParticlePtr) base->subtypes)) {
16690 ret = XML_SCHEMAP_SRC_CT_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000016691 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016692 /*
16693 * Attention: at this point the <simpleType> child is in
16694 * ->contentTypeDef (put there during parsing).
Daniel Veillarddee23482008-04-11 12:58:43 +000016695 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016696 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016697 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016698 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016699 * 2.2 If clause 2.1.2 above is satisfied, then there
16700 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016701 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016702 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016703 /* TODO: Change error code to ..._SRC_CT_2_2. */
16704 xmlSchemaPCustomErr(ctxt,
16705 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016706 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016707 "A <simpleType> is expected among the children "
16708 "of <restriction>, if <simpleContent> is used and "
16709 "the base type '%s' is a complex type",
16710 xmlSchemaFormatQName(&str, base->targetNamespace,
16711 base->name));
16712 FREE_AND_NULL(str)
16713 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016714 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016715 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016716 ret = XML_SCHEMAP_SRC_CT_1;
16717 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016718 }
16719 if (ret > 0) {
16720 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016721 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016722 xmlSchemaPCustomErr(ctxt,
16723 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016724 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 "If <simpleContent> and <restriction> is used, the "
16726 "base type must be a simple type or a complex type with "
16727 "mixed content and particle emptiable. The base type "
16728 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016729 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016730 base->name));
16731 } else {
16732 xmlSchemaPCustomErr(ctxt,
16733 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016734 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016735 "If <simpleContent> and <extension> is used, the "
16736 "base type must be a simple type. The base type '%s' "
16737 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016738 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016739 base->name));
16740 }
16741 FREE_AND_NULL(str)
16742 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016743 }
16744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016745 * SPEC (3) "The corresponding complex type definition component must
16746 * satisfy the conditions set out in Constraints on Complex Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016747 * Definition Schema Components ($3.4.6);"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016748 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016749 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016750 /*
16751 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016752 * above for {attribute wildcard} is satisfied, the intensional
16753 * intersection must be expressible, as defined in Attribute Wildcard
Jan Pokorný761c9e92013-11-29 23:26:27 +010016754 * Intersection ($3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016755 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016756 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016757 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016758}
William M. Brack2f2a6632004-08-20 23:09:47 +000016759
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016760#ifdef ENABLE_PARTICLE_RESTRICTION
16761/**
16762 * xmlSchemaCheckParticleRangeOK:
16763 * @ctxt: the schema parser context
16764 * @type: the complex type definition
16765 *
16766 * (3.9.6) Constraints on Particle Schema Components
16767 * Schema Component Constraint:
16768 * Occurrence Range OK (range-ok)
16769 *
16770 * STATUS: complete
16771 *
16772 * Returns 0 if the constraints are satisfied, a positive
16773 * error code if not and -1 if an internal error occured.
16774 */
16775static int
16776xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16777 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016778{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016779 if (rmin < bmin)
16780 return (1);
16781 if ((bmax != UNBOUNDED) &&
16782 (rmax > bmax))
16783 return (1);
16784 return (0);
16785}
16786
16787/**
16788 * xmlSchemaCheckRCaseNameAndTypeOK:
16789 * @ctxt: the schema parser context
16790 * @r: the restricting element declaration particle
16791 * @b: the base element declaration particle
16792 *
16793 * (3.9.6) Constraints on Particle Schema Components
16794 * Schema Component Constraint:
16795 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16796 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016797 *
16798 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016799 * MISSING (3.2.3)
16800 * CLARIFY: (3.2.2)
16801 *
16802 * Returns 0 if the constraints are satisfied, a positive
16803 * error code if not and -1 if an internal error occured.
16804 */
16805static int
16806xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16807 xmlSchemaParticlePtr r,
16808 xmlSchemaParticlePtr b)
16809{
16810 xmlSchemaElementPtr elemR, elemB;
16811
16812 /* TODO: Error codes (rcase-NameAndTypeOK). */
16813 elemR = (xmlSchemaElementPtr) r->children;
16814 elemB = (xmlSchemaElementPtr) b->children;
16815 /*
16816 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16817 * the same."
16818 */
16819 if ((elemR != elemB) &&
16820 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16821 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16822 return (1);
16823 /*
16824 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016825 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016826 */
16827 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16828 b->minOccurs, b->maxOccurs) != 0)
16829 return (1);
16830 /*
16831 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16832 * {scope} are global."
16833 */
16834 if (elemR == elemB)
16835 return (0);
16836 /*
16837 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16838 */
16839 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16840 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16841 return (1);
16842 /*
16843 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16844 * or is not fixed, or R's declaration's {value constraint} is fixed
16845 * with the same value."
16846 */
16847 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16848 ((elemR->value == NULL) ||
16849 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16850 /* TODO: Equality of the initial value or normalized or canonical? */
16851 (! xmlStrEqual(elemR->value, elemB->value))))
16852 return (1);
16853 /*
16854 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16855 * definitions} is a subset of B's declaration's {identity-constraint
16856 * definitions}, if any."
16857 */
16858 if (elemB->idcs != NULL) {
16859 /* TODO */
16860 }
16861 /*
16862 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16863 * superset of B's declaration's {disallowed substitutions}."
16864 */
16865 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16866 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16867 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16868 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16869 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16870 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16871 return (1);
16872 /*
16873 * SPEC (3.2.5) "R's {type definition} is validly derived given
16874 * {extension, list, union} from B's {type definition}"
16875 *
16876 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16877 * set, if the corresponding constraints handle "restriction" and
16878 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016879 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016880 */
16881 {
16882 int set = 0;
16883
16884 set |= SUBSET_EXTENSION;
16885 set |= SUBSET_LIST;
16886 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016887 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016888 elemB->subtypes, set) != 0)
16889 return (1);
16890 }
16891 return (0);
16892}
16893
16894/**
16895 * xmlSchemaCheckRCaseNSCompat:
16896 * @ctxt: the schema parser context
16897 * @r: the restricting element declaration particle
16898 * @b: the base wildcard particle
16899 *
16900 * (3.9.6) Constraints on Particle Schema Components
16901 * Schema Component Constraint:
16902 * Particle Derivation OK (Elt:Any -- NSCompat)
16903 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016904 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016905 * STATUS: complete
16906 *
16907 * Returns 0 if the constraints are satisfied, a positive
16908 * error code if not and -1 if an internal error occured.
16909 */
16910static int
16911xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16912 xmlSchemaParticlePtr r,
16913 xmlSchemaParticlePtr b)
16914{
16915 /* TODO:Error codes (rcase-NSCompat). */
16916 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016917 * SPEC "For an element declaration particle to be a `valid restriction`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016918 * of a wildcard particle all of the following must be true:"
16919 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010016920 * SPEC (1) "The element declaration's {target namespace} is `valid`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016921 * with respect to the wildcard's {namespace constraint} as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010016922 * Wildcard allows Namespace Name ($3.10.4)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016924 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016925 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16926 return (1);
16927 /*
16928 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016929 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016930 */
16931 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16932 b->minOccurs, b->maxOccurs) != 0)
16933 return (1);
16934
16935 return (0);
16936}
16937
16938/**
16939 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16940 * @ctxt: the schema parser context
16941 * @r: the restricting element declaration particle
16942 * @b: the base model group particle
16943 *
16944 * (3.9.6) Constraints on Particle Schema Components
16945 * Schema Component Constraint:
16946 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16947 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016948 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016949 * STATUS: TODO
16950 *
16951 * Returns 0 if the constraints are satisfied, a positive
16952 * error code if not and -1 if an internal error occured.
16953 */
16954static int
16955xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16956 xmlSchemaParticlePtr r,
16957 xmlSchemaParticlePtr b)
16958{
16959 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16960 TODO
16961 return (0);
16962}
16963
16964/**
16965 * xmlSchemaCheckRCaseNSSubset:
16966 * @ctxt: the schema parser context
16967 * @r: the restricting wildcard particle
16968 * @b: the base wildcard particle
16969 *
16970 * (3.9.6) Constraints on Particle Schema Components
16971 * Schema Component Constraint:
16972 * Particle Derivation OK (Any:Any -- NSSubset)
16973 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016974 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016975 * STATUS: complete
16976 *
16977 * Returns 0 if the constraints are satisfied, a positive
16978 * error code if not and -1 if an internal error occured.
16979 */
16980static int
16981xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16982 xmlSchemaParticlePtr r,
16983 xmlSchemaParticlePtr b,
16984 int isAnyTypeBase)
16985{
16986 /* TODO: Error codes (rcase-NSSubset). */
16987 /*
16988 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016989 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016990 */
16991 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16992 b->minOccurs, b->maxOccurs))
16993 return (1);
16994 /*
16995 * SPEC (2) "R's {namespace constraint} must be an intensional subset
Jan Pokorný761c9e92013-11-29 23:26:27 +010016996 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016997 */
16998 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16999 (xmlSchemaWildcardPtr) b->children))
17000 return (1);
17001 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017002 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17003 * definition`, R's {process contents} must be identical to or stronger
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017004 * than B's {process contents}, where strict is stronger than lax is
17005 * stronger than skip."
17006 */
17007 if (! isAnyTypeBase) {
17008 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17009 ((xmlSchemaWildcardPtr) b->children)->processContents)
17010 return (1);
17011 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017012
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017013 return (0);
17014}
17015
17016/**
17017 * xmlSchemaCheckCOSParticleRestrict:
17018 * @ctxt: the schema parser context
17019 * @type: the complex type definition
17020 *
17021 * (3.9.6) Constraints on Particle Schema Components
17022 * Schema Component Constraint:
17023 * Particle Valid (Restriction) (cos-particle-restrict)
17024 *
17025 * STATUS: TODO
17026 *
17027 * Returns 0 if the constraints are satisfied, a positive
17028 * error code if not and -1 if an internal error occured.
17029 */
17030static int
17031xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17032 xmlSchemaParticlePtr r,
17033 xmlSchemaParticlePtr b)
17034{
17035 int ret = 0;
17036
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017037 /*part = WXS_TYPE_PARTICLE(type);
17038 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017039 */
17040
17041 TODO
17042
17043 /*
17044 * SPEC (1) "They are the same particle."
17045 */
17046 if (r == b)
17047 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017048
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017049
17050 return (0);
17051}
17052
Daniel Veillard15724252008-08-30 15:01:04 +000017053#if 0
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017054/**
17055 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17056 * @ctxt: the schema parser context
17057 * @r: the model group particle
17058 * @b: the base wildcard particle
17059 *
17060 * (3.9.6) Constraints on Particle Schema Components
17061 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017062 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017063 * NSRecurseCheckCardinality)
17064 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017065 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017066 * STATUS: TODO: subst-groups
17067 *
17068 * Returns 0 if the constraints are satisfied, a positive
17069 * error code if not and -1 if an internal error occured.
17070 */
17071static int
17072xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17073 xmlSchemaParticlePtr r,
17074 xmlSchemaParticlePtr b)
17075{
17076 xmlSchemaParticlePtr part;
17077 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17078 if ((r->children == NULL) || (r->children->children == NULL))
17079 return (-1);
17080 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017081 * SPEC "For a group particle to be a `valid restriction` of a
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017082 * wildcard particle..."
17083 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010017084 * SPEC (1) "Every member of the {particles} of the group is a `valid
17085 * restriction` of the wildcard as defined by
17086 * Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017087 */
17088 part = (xmlSchemaParticlePtr) r->children->children;
17089 do {
17090 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17091 return (1);
17092 part = (xmlSchemaParticlePtr) part->next;
17093 } while (part != NULL);
17094 /*
17095 * SPEC (2) "The effective total range of the group [...] is a
17096 * valid restriction of B's occurrence range as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010017097 * Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017098 */
17099 if (xmlSchemaCheckParticleRangeOK(
17100 xmlSchemaGetParticleTotalRangeMin(r),
17101 xmlSchemaGetParticleTotalRangeMax(r),
17102 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017103 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017104 return (0);
17105}
Daniel Veillard15724252008-08-30 15:01:04 +000017106#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017107
17108/**
17109 * xmlSchemaCheckRCaseRecurse:
17110 * @ctxt: the schema parser context
17111 * @r: the <all> or <sequence> model group particle
17112 * @b: the base <all> or <sequence> model group particle
17113 *
17114 * (3.9.6) Constraints on Particle Schema Components
17115 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017116 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017117 Recurse)
17118 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017119 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017120 * STATUS: ?
17121 * TODO: subst-groups
17122 *
17123 * Returns 0 if the constraints are satisfied, a positive
17124 * error code if not and -1 if an internal error occured.
17125 */
17126static int
17127xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17128 xmlSchemaParticlePtr r,
17129 xmlSchemaParticlePtr b)
17130{
17131 /* xmlSchemaParticlePtr part; */
17132 /* TODO: Error codes (rcase-Recurse). */
17133 if ((r->children == NULL) || (b->children == NULL) ||
17134 (r->children->type != b->children->type))
17135 return (-1);
17136 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017137 * SPEC "For an all or sequence group particle to be a `valid
17138 * restriction` of another group particle with the same {compositor}..."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017139 *
17140 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017141 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017142 */
17143 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17144 b->minOccurs, b->maxOccurs))
17145 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017146
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017147
17148 return (0);
17149}
17150
17151#endif
17152
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017153#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17154 xmlSchemaPCustomErrExt(pctxt, \
17155 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017156 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017157 "It is an error for both '%s' and '%s' to be specified on the "\
17158 "same type definition", \
17159 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17160 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17161
17162#define FACET_RESTR_ERR(fac1, msg) \
17163 xmlSchemaPCustomErr(pctxt, \
17164 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017165 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017166 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017167
17168#define FACET_RESTR_FIXED_ERR(fac) \
17169 xmlSchemaPCustomErr(pctxt, \
17170 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017171 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017172 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017173 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017174
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017175static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017176xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17177 xmlSchemaFacetPtr facet1,
17178 xmlSchemaFacetPtr facet2,
17179 int lessGreater,
17180 int orEqual,
17181 int ofBase)
17182{
17183 xmlChar *msg = NULL;
17184
17185 msg = xmlStrdup(BAD_CAST "'");
17186 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17187 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17188 if (lessGreater == 0)
17189 msg = xmlStrcat(msg, BAD_CAST " equal to");
17190 if (lessGreater == 1)
17191 msg = xmlStrcat(msg, BAD_CAST " greater than");
17192 else
17193 msg = xmlStrcat(msg, BAD_CAST " less than");
17194
17195 if (orEqual)
17196 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17197 msg = xmlStrcat(msg, BAD_CAST " '");
17198 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17199 if (ofBase)
17200 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17201 else
17202 msg = xmlStrcat(msg, BAD_CAST "'");
17203
17204 xmlSchemaPCustomErr(pctxt,
17205 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017206 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017207 (const char *) msg, NULL);
17208
17209 if (msg != NULL)
17210 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017211}
17212
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017213/*
17214* xmlSchemaDeriveAndValidateFacets:
17215*
17216* Schema Component Constraint: Simple Type Restriction (Facets)
17217* (st-restrict-facets)
17218*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017219static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017220xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17221 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017222{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017223 xmlSchemaTypePtr base = type->baseType;
17224 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017225 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017226 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17227 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17228 fmininc = NULL, fmaxinc = NULL,
17229 fminexc = NULL, fmaxexc = NULL,
17230 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17231 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17232 bfmininc = NULL, bfmaxinc = NULL,
17233 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017234 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017235
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017236 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017237 * SPEC st-restrict-facets 1:
Daniel Veillarddee23482008-04-11 12:58:43 +000017238 * "The {variety} of R is the same as that of B."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017239 */
17240 /*
17241 * SPEC st-restrict-facets 2:
17242 * "If {variety} is atomic, the {primitive type definition}
17243 * of R is the same as that of B."
17244 *
17245 * NOTE: we leave 1 & 2 out for now, since this will be
17246 * satisfied by the derivation process.
17247 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17248 */
17249 /*
17250 * SPEC st-restrict-facets 3:
17251 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017252 * of B, eliminating duplicates. To eliminate duplicates,
17253 * when a facet of the same kind occurs in both S and the
17254 * {facets} of B, the one in the {facets} of B is not
17255 * included, with the exception of enumeration and pattern
17256 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017257 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017258 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017259
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017260 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17261 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017262
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017263 last = type->facetSet;
17264 if (last != NULL)
17265 while (last->next != NULL)
17266 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017267
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017268 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17269 facet = cur->facet;
17270 switch (facet->type) {
17271 case XML_SCHEMA_FACET_LENGTH:
17272 flength = facet; break;
17273 case XML_SCHEMA_FACET_MINLENGTH:
17274 fminlen = facet; break;
17275 case XML_SCHEMA_FACET_MININCLUSIVE:
17276 fmininc = facet; break;
17277 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17278 fminexc = facet; break;
17279 case XML_SCHEMA_FACET_MAXLENGTH:
17280 fmaxlen = facet; break;
17281 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17282 fmaxinc = facet; break;
17283 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17284 fmaxexc = facet; break;
17285 case XML_SCHEMA_FACET_TOTALDIGITS:
17286 ftotdig = facet; break;
17287 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17288 ffracdig = facet; break;
17289 default:
17290 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017292 }
17293 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17294 facet = cur->facet;
17295 switch (facet->type) {
17296 case XML_SCHEMA_FACET_LENGTH:
17297 bflength = facet; break;
17298 case XML_SCHEMA_FACET_MINLENGTH:
17299 bfminlen = facet; break;
17300 case XML_SCHEMA_FACET_MININCLUSIVE:
17301 bfmininc = facet; break;
17302 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17303 bfminexc = facet; break;
17304 case XML_SCHEMA_FACET_MAXLENGTH:
17305 bfmaxlen = facet; break;
17306 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17307 bfmaxinc = facet; break;
17308 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17309 bfmaxexc = facet; break;
17310 case XML_SCHEMA_FACET_TOTALDIGITS:
17311 bftotdig = facet; break;
17312 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17313 bffracdig = facet; break;
17314 default:
17315 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017316 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017317 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017318 /*
17319 * length and minLength or maxLength (2.2) + (3.2)
17320 */
17321 if (flength && (fminlen || fmaxlen)) {
17322 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17323 "either of 'minLength' or 'maxLength' to be specified on "
17324 "the same type definition")
17325 }
17326 /*
17327 * Mutual exclusions in the same derivation step.
17328 */
17329 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017330 /*
17331 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017332 */
17333 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17334 }
17335 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017336 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017337 * SCC "minInclusive and minExclusive"
17338 */
17339 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017340 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017341
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017342 if (flength && bflength) {
17343 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017344 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017345 * The values have to be equal.
17346 */
17347 res = xmlSchemaCompareValues(flength->val, bflength->val);
17348 if (res == -2)
17349 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017350 if (res != 0)
17351 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17352 if ((res != 0) && (bflength->fixed)) {
17353 FACET_RESTR_FIXED_ERR(flength)
17354 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017355
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017356 }
17357 if (fminlen && bfminlen) {
17358 /*
17359 * SCC "minLength valid restriction"
17360 * minLength >= BASE minLength
17361 */
17362 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17363 if (res == -2)
17364 goto internal_error;
17365 if (res == -1)
17366 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17367 if ((res != 0) && (bfminlen->fixed)) {
17368 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017369 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017370 }
17371 if (fmaxlen && bfmaxlen) {
17372 /*
17373 * SCC "maxLength valid restriction"
17374 * maxLength <= BASE minLength
17375 */
17376 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17377 if (res == -2)
17378 goto internal_error;
17379 if (res == 1)
17380 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17381 if ((res != 0) && (bfmaxlen->fixed)) {
17382 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017384 }
17385 /*
17386 * SCC "length and minLength or maxLength"
17387 */
17388 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017389 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017390 if (flength) {
17391 if (! fminlen)
Miroslav Bajtos8f58f892009-08-07 17:22:12 +020017392 fminlen = bfminlen;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017393 if (fminlen) {
17394 /* (1.1) length >= minLength */
17395 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17396 if (res == -2)
17397 goto internal_error;
17398 if (res == -1)
17399 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17400 }
17401 if (! fmaxlen)
17402 fmaxlen = bfmaxlen;
17403 if (fmaxlen) {
17404 /* (2.1) length <= maxLength */
17405 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17406 if (res == -2)
17407 goto internal_error;
17408 if (res == 1)
17409 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17410 }
17411 }
17412 if (fmaxinc) {
17413 /*
17414 * "maxInclusive"
17415 */
17416 if (fmininc) {
17417 /* SCC "maxInclusive >= minInclusive" */
17418 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17419 if (res == -2)
17420 goto internal_error;
17421 if (res == -1) {
17422 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17423 }
17424 }
17425 /*
17426 * SCC "maxInclusive valid restriction"
17427 */
17428 if (bfmaxinc) {
17429 /* maxInclusive <= BASE maxInclusive */
17430 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17431 if (res == -2)
17432 goto internal_error;
17433 if (res == 1)
17434 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17435 if ((res != 0) && (bfmaxinc->fixed)) {
17436 FACET_RESTR_FIXED_ERR(fmaxinc)
17437 }
17438 }
17439 if (bfmaxexc) {
17440 /* maxInclusive < BASE maxExclusive */
17441 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17442 if (res == -2)
17443 goto internal_error;
17444 if (res != -1) {
17445 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17446 }
17447 }
17448 if (bfmininc) {
17449 /* maxInclusive >= BASE minInclusive */
17450 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17451 if (res == -2)
17452 goto internal_error;
17453 if (res == -1) {
17454 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17455 }
17456 }
17457 if (bfminexc) {
17458 /* maxInclusive > BASE minExclusive */
17459 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17460 if (res == -2)
17461 goto internal_error;
17462 if (res != 1) {
17463 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17464 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017465 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017466 }
17467 if (fmaxexc) {
17468 /*
17469 * "maxExclusive >= minExclusive"
17470 */
17471 if (fminexc) {
17472 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17473 if (res == -2)
17474 goto internal_error;
17475 if (res == -1) {
17476 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17477 }
17478 }
17479 /*
17480 * "maxExclusive valid restriction"
17481 */
17482 if (bfmaxexc) {
17483 /* maxExclusive <= BASE maxExclusive */
17484 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17485 if (res == -2)
17486 goto internal_error;
17487 if (res == 1) {
17488 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17489 }
17490 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017491 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017492 }
17493 }
17494 if (bfmaxinc) {
17495 /* maxExclusive <= BASE maxInclusive */
17496 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17497 if (res == -2)
17498 goto internal_error;
17499 if (res == 1) {
17500 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17501 }
17502 }
17503 if (bfmininc) {
17504 /* maxExclusive > BASE minInclusive */
17505 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17506 if (res == -2)
17507 goto internal_error;
17508 if (res != 1) {
17509 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17510 }
17511 }
17512 if (bfminexc) {
17513 /* maxExclusive > BASE minExclusive */
17514 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17515 if (res == -2)
17516 goto internal_error;
17517 if (res != 1) {
17518 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17519 }
17520 }
17521 }
17522 if (fminexc) {
17523 /*
17524 * "minExclusive < maxInclusive"
17525 */
17526 if (fmaxinc) {
17527 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17528 if (res == -2)
17529 goto internal_error;
17530 if (res != -1) {
17531 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17532 }
17533 }
17534 /*
17535 * "minExclusive valid restriction"
17536 */
17537 if (bfminexc) {
17538 /* minExclusive >= BASE minExclusive */
17539 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17540 if (res == -2)
17541 goto internal_error;
17542 if (res == -1) {
17543 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17544 }
17545 if ((res != 0) && (bfminexc->fixed)) {
17546 FACET_RESTR_FIXED_ERR(fminexc)
17547 }
17548 }
17549 if (bfmaxinc) {
17550 /* minExclusive <= BASE maxInclusive */
17551 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17552 if (res == -2)
17553 goto internal_error;
17554 if (res == 1) {
17555 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17556 }
17557 }
17558 if (bfmininc) {
17559 /* minExclusive >= BASE minInclusive */
17560 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17561 if (res == -2)
17562 goto internal_error;
17563 if (res == -1) {
17564 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17565 }
17566 }
17567 if (bfmaxexc) {
17568 /* minExclusive < BASE maxExclusive */
17569 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17570 if (res == -2)
17571 goto internal_error;
17572 if (res != -1) {
17573 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17574 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017575 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017576 }
17577 if (fmininc) {
17578 /*
17579 * "minInclusive < maxExclusive"
17580 */
17581 if (fmaxexc) {
17582 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17583 if (res == -2)
17584 goto internal_error;
17585 if (res != -1) {
17586 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17587 }
17588 }
17589 /*
17590 * "minExclusive valid restriction"
17591 */
17592 if (bfmininc) {
17593 /* minInclusive >= BASE minInclusive */
17594 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17595 if (res == -2)
17596 goto internal_error;
17597 if (res == -1) {
17598 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17599 }
17600 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017602 }
17603 }
17604 if (bfmaxinc) {
17605 /* minInclusive <= BASE maxInclusive */
17606 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17607 if (res == -2)
17608 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017609 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017610 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17611 }
17612 }
17613 if (bfminexc) {
17614 /* minInclusive > BASE minExclusive */
17615 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17616 if (res == -2)
17617 goto internal_error;
17618 if (res != 1)
17619 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17620 }
17621 if (bfmaxexc) {
17622 /* minInclusive < BASE maxExclusive */
17623 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17624 if (res == -2)
17625 goto internal_error;
17626 if (res != -1)
17627 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17628 }
17629 }
17630 if (ftotdig && bftotdig) {
17631 /*
17632 * SCC " totalDigits valid restriction"
17633 * totalDigits <= BASE totalDigits
17634 */
17635 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17636 if (res == -2)
17637 goto internal_error;
17638 if (res == 1)
17639 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17640 -1, 1, 1);
17641 if ((res != 0) && (bftotdig->fixed)) {
17642 FACET_RESTR_FIXED_ERR(ftotdig)
17643 }
17644 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017646 /*
17647 * SCC "fractionDigits valid restriction"
17648 * fractionDigits <= BASE fractionDigits
17649 */
17650 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17651 if (res == -2)
17652 goto internal_error;
17653 if (res == 1)
17654 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17655 -1, 1, 1);
17656 if ((res != 0) && (bffracdig->fixed)) {
17657 FACET_RESTR_FIXED_ERR(ffracdig)
17658 }
17659 }
17660 /*
17661 * SCC "fractionDigits less than or equal to totalDigits"
17662 */
17663 if (! ftotdig)
17664 ftotdig = bftotdig;
17665 if (! ffracdig)
17666 ffracdig = bffracdig;
17667 if (ftotdig && ffracdig) {
17668 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17669 if (res == -2)
17670 goto internal_error;
17671 if (res == 1)
17672 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17673 -1, 1, 0);
17674 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017675 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017676 * *Enumerations* won' be added here, since only the first set
17677 * of enumerations in the ancestor-or-self axis is used
17678 * for validation, plus we need to use the base type of those
17679 * enumerations for whitespace.
17680 *
17681 * *Patterns*: won't be add here, since they are ORed at
17682 * type level and ANDed at ancestor level. This will
17683 * happed during validation by walking the base axis
17684 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017685 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017686 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17687 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017688 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017689 * Special handling of enumerations and patterns.
17690 * TODO: hmm, they should not appear in the set, so remove this.
17691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017692 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017693 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017694 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017695 /*
17696 * Search for a duplicate facet in the current type.
17697 */
17698 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017699 /* err = 0; */
17700 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017701 while (link != NULL) {
17702 facet = link->facet;
17703 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017704 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017705 case XML_SCHEMA_FACET_WHITESPACE:
17706 /*
17707 * The whitespace must be stronger.
17708 */
17709 if (facet->whitespace < bfacet->whitespace) {
Rob Richardsc6947bb2008-06-29 15:04:41 +000017710 FACET_RESTR_ERR(facet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017711 "The 'whitespace' value has to be equal to "
17712 "or stronger than the 'whitespace' value of "
17713 "the base type")
17714 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017715 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017716 (facet->whitespace != bfacet->whitespace)) {
17717 FACET_RESTR_FIXED_ERR(facet)
17718 }
17719 break;
17720 default:
17721 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017723 /* Duplicate found. */
17724 break;
17725 }
17726 link = link->next;
17727 }
17728 /*
17729 * If no duplicate was found: add the base types's facet
17730 * to the set.
17731 */
17732 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017733 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017734 xmlMalloc(sizeof(xmlSchemaFacetLink));
17735 if (link == NULL) {
17736 xmlSchemaPErrMemory(pctxt,
17737 "deriving facets, creating a facet link", NULL);
17738 return (-1);
17739 }
17740 link->facet = cur->facet;
17741 link->next = NULL;
17742 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017743 type->facetSet = link;
17744 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017745 last->next = link;
17746 last = link;
17747 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017748
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017749 }
17750
17751 return (0);
17752internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017753 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17754 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017755 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017756}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017757
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017758static int
17759xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17760 xmlSchemaTypePtr type)
17761{
17762 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17763 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017764 * The actual value is then formed by replacing any union type
Jan Pokorný761c9e92013-11-29 23:26:27 +010017765 * definition in the `explicit members` with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017766 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017767 *
17768 * TODO: There's a bug entry at
17769 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17770 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017771 */
17772 link = type->memberTypes;
17773 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017774
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017775 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017776 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017777
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017778 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017779 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017780 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017781 link->type = subLink->type;
17782 if (subLink->next != NULL) {
17783 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017784 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017785 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017786 while (subLink != NULL) {
17787 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017788 xmlMalloc(sizeof(xmlSchemaTypeLink));
17789 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017790 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017791 NULL);
17792 return (-1);
17793 }
17794 newLink->type = subLink->type;
17795 prevLink->next = newLink;
17796 prevLink = newLink;
17797 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017798
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017799 subLink = subLink->next;
17800 }
17801 }
17802 }
17803 }
17804 link = link->next;
17805 }
17806 return (0);
17807}
17808
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017809static void
17810xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
Daniel Veillarddee23482008-04-11 12:58:43 +000017811{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017812 int has = 0, needVal = 0, normVal = 0;
17813
17814 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17815 if (has) {
17816 needVal = (type->baseType->flags &
17817 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17818 normVal = (type->baseType->flags &
17819 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17820 }
17821 if (type->facets != NULL) {
17822 xmlSchemaFacetPtr fac;
Daniel Veillarddee23482008-04-11 12:58:43 +000017823
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017824 for (fac = type->facets; fac != NULL; fac = fac->next) {
17825 switch (fac->type) {
17826 case XML_SCHEMA_FACET_WHITESPACE:
17827 break;
17828 case XML_SCHEMA_FACET_PATTERN:
17829 normVal = 1;
17830 has = 1;
17831 break;
17832 case XML_SCHEMA_FACET_ENUMERATION:
17833 needVal = 1;
17834 normVal = 1;
17835 has = 1;
17836 break;
17837 default:
17838 has = 1;
17839 break;
17840 }
Daniel Veillarddee23482008-04-11 12:58:43 +000017841 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017842 }
17843 if (normVal)
17844 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17845 if (needVal)
17846 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17847 if (has)
17848 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17849
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017850 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017851 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17852 /*
17853 * OPTIMIZE VAL TODO: Some facets need a computed value.
17854 */
17855 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17856 (prim->builtInType != XML_SCHEMAS_STRING)) {
17857 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
Daniel Veillarddee23482008-04-11 12:58:43 +000017858 }
17859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017860}
17861
17862static int
17863xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17864{
Daniel Veillarddee23482008-04-11 12:58:43 +000017865
17866
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017867 /*
17868 * Evaluate the whitespace-facet value.
Daniel Veillarddee23482008-04-11 12:58:43 +000017869 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017870 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017871 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17872 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017873 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017874 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000017875
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017876 if (type->facetSet != NULL) {
17877 xmlSchemaFacetLinkPtr lin;
17878
17879 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17880 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17881 switch (lin->facet->whitespace) {
17882 case XML_SCHEMAS_FACET_PRESERVE:
17883 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17884 break;
17885 case XML_SCHEMAS_FACET_REPLACE:
17886 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17887 break;
17888 case XML_SCHEMAS_FACET_COLLAPSE:
17889 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17890 break;
17891 default:
17892 return (-1);
17893 }
17894 return (0);
17895 }
17896 }
17897 }
17898 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017899 * For all `atomic` datatypes other than string (and types `derived`
17900 * by `restriction` from it) the value of whiteSpace is fixed to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017901 * collapse
17902 */
17903 {
17904 xmlSchemaTypePtr anc;
17905
Daniel Veillarddee23482008-04-11 12:58:43 +000017906 for (anc = type->baseType; anc != NULL &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017907 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17908 anc = anc->baseType) {
17909
17910 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillarddee23482008-04-11 12:58:43 +000017911 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017912 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17913
17914 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
Daniel Veillarddee23482008-04-11 12:58:43 +000017915 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017916 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17917
17918 } else
17919 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17920 break;
17921 }
17922 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017923 }
17924 return (0);
17925}
17926
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017927static int
17928xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17929 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017930{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017931 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17932 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017933 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017934 return(0);
17935 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017936
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017937 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017938 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017939 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017940 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017941 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017942 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017943 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017944 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017945 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017946 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017947 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017948 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017949 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017950 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017951 * Corresponds to <simpleType><union>...
Daniel Veillarddee23482008-04-11 12:58:43 +000017952 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017953 if (type->memberTypes == NULL) {
17954 /*
17955 * This one is really needed, so get out.
17956 */
17957 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17958 "union type has no member-types assigned");
17959 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000017960 }
17961 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017962 /*
17963 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017964 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017965 if (type->baseType == NULL) {
17966 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17967 "type has no base-type assigned");
17968 return(-1);
17969 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017970 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017971 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17972 return(-1);
17973 /*
17974 * Variety
17975 * If the <restriction> alternative is chosen, then the
17976 * {variety} of the {base type definition}.
17977 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017978 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017979 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017980 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017981 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017982 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017983 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017984 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017985 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017986 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017987 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017988 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017989 * NOTE that we won't assign the memberTypes of the base,
17990 * since this will make trouble when freeing them; we will
17991 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017992 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017993 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017994 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017995 return(0);
17996}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017997
Daniel Veillard8651f532002-04-17 09:06:27 +000017998#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000017999static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018000xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18001 xmlSchemaTypePtr type)
18002{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018003 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018004 xmlGenericError(xmlGenericErrorContext,
18005 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018006 type->node->doc->URL,
18007 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018008 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018009 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018010 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018011 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018012 switch (type->contentType) {
18013 case XML_SCHEMA_CONTENT_SIMPLE:
18014 xmlGenericError(xmlGenericErrorContext, "simple\n");
18015 break;
18016 case XML_SCHEMA_CONTENT_ELEMENTS:
18017 xmlGenericError(xmlGenericErrorContext, "elements\n");
18018 break;
18019 case XML_SCHEMA_CONTENT_UNKNOWN:
18020 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18021 break;
18022 case XML_SCHEMA_CONTENT_EMPTY:
18023 xmlGenericError(xmlGenericErrorContext, "empty\n");
18024 break;
18025 case XML_SCHEMA_CONTENT_MIXED:
18026 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018027 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018028 xmlGenericError(xmlGenericErrorContext,
18029 "mixed as emptiable particle\n");
18030 else
18031 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18032 break;
18033 /* Removed, since not used. */
18034 /*
18035 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18036 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18037 break;
18038 */
18039 case XML_SCHEMA_CONTENT_BASIC:
18040 xmlGenericError(xmlGenericErrorContext, "basic\n");
18041 break;
18042 default:
18043 xmlGenericError(xmlGenericErrorContext,
18044 "not registered !!!\n");
18045 break;
18046 }
Daniel Veillard8651f532002-04-17 09:06:27 +000018047 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018048}
Daniel Veillard8651f532002-04-17 09:06:27 +000018049#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018050
18051/*
18052* 3.14.6 Constraints on Simple Type Definition Schema Components
18053*/
18054static int
18055xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18056 xmlSchemaTypePtr type)
18057{
18058 int res, olderrs = pctxt->nberrors;
18059
18060 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18061 return(-1);
18062
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018063 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018064 return(0);
18065
18066 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18067 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18068
18069 if (type->baseType == NULL) {
18070 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18071 "missing baseType");
18072 goto exit_failure;
18073 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018074 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018075 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000018076 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018077 * If a member type of a union is a union itself, we need to substitute
18078 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018079 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18080 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018081 */
18082 if ((type->memberTypes != NULL) &&
18083 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
Daniel Veillarddee23482008-04-11 12:58:43 +000018084 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018085 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000018086 * SPEC src-simple-type 1
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018087 * "The corresponding simple type definition, if any, must satisfy
18088 * the conditions set out in Constraints on Simple Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010018089 * Schema Components ($3.14.6)."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018090 */
18091 /*
18092 * Schema Component Constraint: Simple Type Definition Properties Correct
18093 * (st-props-correct)
18094 */
18095 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18096 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018097 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018098 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18099 * (cos-st-restricts)
18100 */
18101 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18102 HFAILURE HERROR
18103 /*
18104 * TODO: Removed the error report, since it got annoying to get an
18105 * extra error report, if anything failed until now.
18106 * Enable this if needed.
18107 *
18108 * xmlSchemaPErr(ctxt, type->node,
18109 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18110 * "Simple type '%s' does not satisfy the constraints "
18111 * "on simple type definitions.\n",
18112 * type->name, NULL);
18113 */
18114 /*
18115 * Schema Component Constraint: Simple Type Restriction (Facets)
18116 * (st-restrict-facets)
18117 */
18118 res = xmlSchemaCheckFacetValues(type, pctxt);
18119 HFAILURE HERROR
18120 if ((type->facetSet != NULL) ||
18121 (type->baseType->facetSet != NULL)) {
18122 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18123 HFAILURE HERROR
18124 }
18125 /*
18126 * Whitespace value.
18127 */
18128 res = xmlSchemaTypeFixupWhitespace(type);
18129 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018130 xmlSchemaTypeFixupOptimFacets(type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018131
18132exit_error:
18133#ifdef DEBUG_TYPE
18134 xmlSchemaDebugFixedType(pctxt, type);
18135#endif
18136 if (olderrs != pctxt->nberrors)
18137 return(pctxt->err);
18138 return(0);
18139
18140exit_failure:
18141#ifdef DEBUG_TYPE
18142 xmlSchemaDebugFixedType(pctxt, type);
18143#endif
18144 return(-1);
18145}
18146
18147static int
18148xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18149 xmlSchemaTypePtr type)
18150{
18151 int res = 0, olderrs = pctxt->nberrors;
18152 xmlSchemaTypePtr baseType = type->baseType;
18153
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018154 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018155 return(0);
18156 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18157 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018158 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018159 "missing baseType");
18160 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018161 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018162 /*
18163 * Fixup the base type.
18164 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018165 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018166 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018167 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18168 /*
18169 * Skip fixup if the base type is invalid.
18170 * TODO: Generate a warning!
18171 */
18172 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000018173 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018174 /*
18175 * This basically checks if the base type can be derived.
18176 */
18177 res = xmlSchemaCheckSRCCT(pctxt, type);
Daniel Veillarddee23482008-04-11 12:58:43 +000018178 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018179 /*
18180 * Fixup the content type.
18181 */
18182 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18183 /*
18184 * Corresponds to <complexType><simpleContent>...
18185 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018186 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018187 (baseType->contentTypeDef != NULL) &&
18188 (WXS_IS_RESTRICTION(type))) {
18189 xmlSchemaTypePtr contentBase, content;
18190#ifdef ENABLE_NAMED_LOCALS
18191 char buf[30];
18192 const xmlChar *tmpname;
18193#endif
18194 /*
18195 * SPEC (1) If <restriction> + base type is <complexType>,
18196 * "whose own {content type} is a simple type..."
18197 */
18198 if (type->contentTypeDef != NULL) {
18199 /*
18200 * SPEC (1.1) "the simple type definition corresponding to the
18201 * <simpleType> among the [children] of <restriction> if there
18202 * is one;"
18203 * Note that this "<simpleType> among the [children]" was put
18204 * into ->contentTypeDef during parsing.
18205 */
18206 contentBase = type->contentTypeDef;
18207 type->contentTypeDef = NULL;
18208 } else {
18209 /*
18210 * (1.2) "...otherwise (<restriction> has no <simpleType>
18211 * among its [children]), the simple type definition which
18212 * is the {content type} of the ... base type."
18213 */
18214 contentBase = baseType->contentTypeDef;
18215 }
18216 /*
18217 * SPEC
18218 * "... a simple type definition which restricts the simple
18219 * type definition identified in clause 1.1 or clause 1.2
18220 * with a set of facet components"
18221 *
18222 * Create the anonymous simple type, which will be the content
18223 * type of the complex type.
18224 */
18225#ifdef ENABLE_NAMED_LOCALS
18226 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18227 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018228 content = xmlSchemaAddType(pctxt, pctxt->schema,
18229 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018230 type->node, 0);
18231#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018232 content = xmlSchemaAddType(pctxt, pctxt->schema,
18233 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018234 type->node, 0);
18235#endif
18236 if (content == NULL)
18237 goto exit_failure;
18238 /*
18239 * We will use the same node as for the <complexType>
18240 * to have it somehow anchored in the schema doc.
18241 */
18242 content->type = XML_SCHEMA_TYPE_SIMPLE;
18243 content->baseType = contentBase;
18244 /*
18245 * Move the facets, previously anchored on the
18246 * complexType during parsing.
18247 */
18248 content->facets = type->facets;
18249 type->facets = NULL;
18250 content->facetSet = type->facetSet;
18251 type->facetSet = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000018252
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018253 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018254 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018255 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018256 /*
18257 * Fixup the newly created type. We don't need to check
18258 * for circularity here.
18259 */
18260 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018261 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018262 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018263 HFAILURE HERROR
18264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018265 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018266 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18267 (WXS_IS_RESTRICTION(type))) {
18268 /*
18269 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18270 * an emptiable particle, then a simple type definition which
18271 * restricts the <restriction>'s <simpleType> child.
18272 */
18273 if ((type->contentTypeDef == NULL) ||
18274 (type->contentTypeDef->baseType == NULL)) {
18275 /*
18276 * TODO: Check if this ever happens.
18277 */
18278 xmlSchemaPCustomErr(pctxt,
18279 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018280 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018281 "Internal error: xmlSchemaTypeFixup, "
18282 "complex type '%s': the <simpleContent><restriction> "
18283 "is missing a <simpleType> child, but was not catched "
18284 "by xmlSchemaCheckSRCCT()", type->name);
18285 goto exit_failure;
18286 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018287 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018288 /*
18289 * SPEC (3) If <extension> + base is <complexType> with
18290 * <simpleType> content, "...then the {content type} of that
18291 * complex type definition"
18292 */
18293 if (baseType->contentTypeDef == NULL) {
18294 /*
18295 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18296 * should have catched this already.
18297 */
18298 xmlSchemaPCustomErr(pctxt,
18299 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018300 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018301 "Internal error: xmlSchemaTypeFixup, "
18302 "complex type '%s': the <extension>ed base type is "
18303 "a complex type with no simple content type",
18304 type->name);
18305 goto exit_failure;
18306 }
18307 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018308 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018309 /*
18310 * SPEC (4) <extension> + base is <simpleType>
18311 * "... then that simple type definition"
18312 */
18313 type->contentTypeDef = baseType;
18314 } else {
18315 /*
18316 * TODO: Check if this ever happens.
18317 */
18318 xmlSchemaPCustomErr(pctxt,
18319 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018320 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018321 "Internal error: xmlSchemaTypeFixup, "
18322 "complex type '%s' with <simpleContent>: unhandled "
18323 "derivation case", type->name);
18324 goto exit_failure;
18325 }
18326 } else {
18327 int dummySequence = 0;
18328 xmlSchemaParticlePtr particle =
18329 (xmlSchemaParticlePtr) type->subtypes;
18330 /*
18331 * Corresponds to <complexType><complexContent>...
18332 *
18333 * NOTE that the effective mixed was already set during parsing of
18334 * <complexType> and <complexContent>; its flag value is
18335 * XML_SCHEMAS_TYPE_MIXED.
18336 *
18337 * Compute the "effective content":
18338 * (2.1.1) + (2.1.2) + (2.1.3)
18339 */
18340 if ((particle == NULL) ||
18341 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18342 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18343 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18344 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18345 (particle->minOccurs == 0))) &&
18346 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18347 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18348 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018349 * SPEC (2.1.4) "If the `effective mixed` is true, then
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018350 * a particle whose properties are as follows:..."
18351 *
18352 * Empty sequence model group with
18353 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18354 * NOTE that we sill assign it the <complexType> node to
18355 * somehow anchor it in the doc.
18356 */
18357 if ((particle == NULL) ||
18358 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18359 /*
18360 * Create the particle.
18361 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018362 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018363 type->node, 1, 1);
18364 if (particle == NULL)
18365 goto exit_failure;
18366 /*
18367 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018368 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018369 particle->children = (xmlSchemaTreeItemPtr)
18370 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18371 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18372 if (particle->children == NULL)
18373 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018374
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018375 type->subtypes = (xmlSchemaTypePtr) particle;
18376 }
18377 dummySequence = 1;
18378 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18379 } else {
18380 /*
18381 * SPEC (2.1.5) "otherwise empty"
18382 */
18383 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18384 }
18385 } else {
18386 /*
18387 * SPEC (2.2) "otherwise the particle corresponding to the
18388 * <all>, <choice>, <group> or <sequence> among the
18389 * [children]."
18390 */
18391 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18392 }
18393 /*
18394 * Compute the "content type".
18395 */
18396 if (WXS_IS_RESTRICTION(type)) {
18397 /*
18398 * SPEC (3.1) "If <restriction>..."
18399 * (3.1.1) + (3.1.2) */
18400 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18401 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18402 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18403 }
18404 } else {
18405 /*
18406 * SPEC (3.2) "If <extension>..."
18407 */
18408 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18409 /*
18410 * SPEC (3.2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010018411 * "If the `effective content` is empty, then the
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018412 * {content type} of the [...] base ..."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018413 */
18414 type->contentType = baseType->contentType;
18415 type->subtypes = baseType->subtypes;
18416 /*
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018417 * Fixes bug #347316:
18418 * This is the case when the base type has a simple
18419 * type definition as content.
18420 */
18421 type->contentTypeDef = baseType->contentTypeDef;
18422 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018423 * NOTE that the effective mixed is ignored here.
18424 */
18425 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18426 /*
18427 * SPEC (3.2.2)
18428 */
18429 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18430 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18431 } else {
18432 /*
18433 * SPEC (3.2.3)
18434 */
18435 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18436 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18437 /*
18438 * "A model group whose {compositor} is sequence and whose
18439 * {particles} are..."
18440 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018441 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18442 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18443 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18444 XML_SCHEMA_TYPE_ALL))
18445 {
18446 /*
18447 * SPEC cos-all-limited (1)
18448 */
18449 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18450 /* TODO: error code */
18451 XML_SCHEMAP_COS_ALL_LIMITED,
18452 WXS_ITEM_NODE(type), NULL,
18453 "The type has an 'all' model group in its "
18454 "{content type} and thus cannot be derived from "
18455 "a non-empty type, since this would produce a "
18456 "'sequence' model group containing the 'all' "
18457 "model group; 'all' model groups are not "
18458 "allowed to appear inside other model groups",
18459 NULL, NULL);
18460
18461 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18462 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18463 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18464 XML_SCHEMA_TYPE_ALL))
18465 {
18466 /*
18467 * SPEC cos-all-limited (1)
18468 */
18469 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18470 /* TODO: error code */
18471 XML_SCHEMAP_COS_ALL_LIMITED,
18472 WXS_ITEM_NODE(type), NULL,
18473 "A type cannot be derived by extension from a type "
18474 "which has an 'all' model group in its "
18475 "{content type}, since this would produce a "
18476 "'sequence' model group containing the 'all' "
18477 "model group; 'all' model groups are not "
18478 "allowed to appear inside other model groups",
18479 NULL, NULL);
18480
18481 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018482 xmlSchemaTreeItemPtr effectiveContent =
18483 (xmlSchemaTreeItemPtr) type->subtypes;
18484 /*
18485 * Create the particle.
18486 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018487 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018488 type->node, 1, 1);
18489 if (particle == NULL)
18490 goto exit_failure;
18491 /*
18492 * Create the "sequence" model group.
18493 */
18494 particle->children = (xmlSchemaTreeItemPtr)
18495 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18496 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18497 if (particle->children == NULL)
18498 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018499 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018500 /*
18501 * SPEC "the particle of the {content type} of
18502 * the ... base ..."
18503 * Create a duplicate of the base type's particle
18504 * and assign its "term" to it.
18505 */
18506 particle->children->children =
18507 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018508 type->node,
Remi Gacogne4609e6c2012-05-11 15:31:05 +080018509 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18510 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018511 if (particle->children->children == NULL)
18512 goto exit_failure;
18513 particle = (xmlSchemaParticlePtr)
18514 particle->children->children;
18515 particle->children =
18516 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18517 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018518 * SPEC "followed by the `effective content`."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018519 */
18520 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018521 /*
18522 * This all will result in:
18523 * new-particle
18524 * --> new-sequence(
18525 * new-particle
18526 * --> base-model,
18527 * this-particle
18528 * --> this-model
18529 * )
18530 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018531 } else {
18532 /*
18533 * This is the case when there is already an empty
18534 * <sequence> with minOccurs==maxOccurs==1.
18535 * Just add the base types's content type.
18536 * NOTE that, although we miss to add an intermediate
18537 * <sequence>, this should produce no difference to
18538 * neither the regex compilation of the content model,
18539 * nor to the complex type contraints.
18540 */
18541 particle->children->children =
18542 (xmlSchemaTreeItemPtr) baseType->subtypes;
18543 }
18544 }
18545 }
18546 }
18547 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018548 * Now fixup attribute uses:
18549 * - expand attr. group references
18550 * - intersect attribute wildcards
18551 * - inherit attribute uses of the base type
18552 * - inherit or union attr. wildcards if extending
18553 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018554 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018555 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018556 HFAILURE HERROR
18557 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018558 * Apply the complex type component constraints; this will not
18559 * check attributes, since this is done in
18560 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018561 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018562 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018563 HFAILURE HERROR
18564
18565#ifdef DEBUG_TYPE
18566 xmlSchemaDebugFixedType(pctxt, type);
18567#endif
18568 if (olderrs != pctxt->nberrors)
18569 return(pctxt->err);
18570 else
18571 return(0);
18572
18573exit_error:
18574 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18575#ifdef DEBUG_TYPE
18576 xmlSchemaDebugFixedType(pctxt, type);
18577#endif
18578 return(pctxt->err);
18579
18580exit_failure:
18581 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18582#ifdef DEBUG_TYPE
18583 xmlSchemaDebugFixedType(pctxt, type);
18584#endif
18585 return(-1);
18586}
18587
18588
18589/**
18590 * xmlSchemaTypeFixup:
18591 * @typeDecl: the schema type definition
18592 * @ctxt: the schema parser context
18593 *
18594 * Fixes the content model of the type.
18595 * URGENT TODO: We need an int result!
18596 */
18597static int
18598xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018599 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018600{
18601 if (type == NULL)
18602 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018603 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18604 AERROR_INT("xmlSchemaTypeFixup",
18605 "this function needs a parser context");
18606 return(-1);
18607 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018608 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018609 return(0);
18610 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018611 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018612 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018613 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018614 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018615}
18616
18617/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018618 * xmlSchemaCheckFacet:
18619 * @facet: the facet
18620 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018621 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018622 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018623 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018625 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018626 * Returns 0 if valid, a positive error code if not valid and
18627 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018628 */
18629int
18630xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018631 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018632 xmlSchemaParserCtxtPtr pctxt,
18633 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018634{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018635 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018636
Daniel Veillardce682bc2004-11-05 17:22:25 +000018637 if ((facet == NULL) || (typeDecl == NULL))
18638 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018639 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018640 * TODO: will the parser context be given if used from
18641 * the relaxNG module?
18642 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018643 if (pctxt == NULL)
18644 ctxtGiven = 0;
18645 else
18646 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018647
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018648 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018649 case XML_SCHEMA_FACET_MININCLUSIVE:
18650 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18651 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018652 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18653 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018654 /*
18655 * Okay we need to validate the value
18656 * at that point.
18657 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018658 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018659
18660 /* 4.3.5.5 Constraints on enumeration Schema Components
18661 * Schema Component Constraint: enumeration valid restriction
Jan Pokorný761c9e92013-11-29 23:26:27 +010018662 * It is an `error` if any member of {value} is not in the
18663 * `value space` of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018664 *
18665 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Jan Pokorný761c9e92013-11-29 23:26:27 +010018666 * The value `must` be in the
18667 * `value space` of the `base type`.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018668 */
18669 /*
18670 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018671 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018673 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018674 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018675 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018677 */
18678 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18679 base = typeDecl->baseType;
18680 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018681 PERROR_INT("xmlSchemaCheckFacet",
18682 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018683 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018684 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018685 } else
18686 base = typeDecl;
Daniel Veillarddee23482008-04-11 12:58:43 +000018687
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018688 if (! ctxtGiven) {
18689 /*
18690 * A context is needed if called from RelaxNG.
Daniel Veillarddee23482008-04-11 12:58:43 +000018691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692 pctxt = xmlSchemaNewParserCtxt("*");
18693 if (pctxt == NULL)
18694 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018695 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018696 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018697 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018698 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018699 * facet->node is just the node holding the facet
18700 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018701 * of the facet.
Daniel Veillarddee23482008-04-11 12:58:43 +000018702 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018703 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018704 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018705 facet->value, &(facet->val), 1, 1, 0);
18706 if (ret != 0) {
18707 if (ret < 0) {
18708 /* No error message for RelaxNG. */
Daniel Veillarddee23482008-04-11 12:58:43 +000018709 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018710 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018711 XML_SCHEMAP_INTERNAL, facet->node, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000018712 "Internal error: xmlSchemaCheckFacet, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018713 "failed to validate the value '%s' of the "
18714 "facet '%s' against the base type",
18715 facet->value, xmlSchemaFacetTypeToString(facet->type));
18716 }
18717 goto internal_error;
18718 }
18719 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18720 /* No error message for RelaxNG. */
18721 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018722 xmlChar *str = NULL;
18723
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018724 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018725 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018726 "The value '%s' of the facet does not validate "
18727 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018728 facet->value,
18729 xmlSchemaFormatQName(&str,
18730 base->targetNamespace, base->name));
18731 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018732 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018733 goto exit;
18734 } else if (facet->val == NULL) {
18735 if (ctxtGiven) {
18736 PERROR_INT("xmlSchemaCheckFacet",
18737 "value was not computed");
18738 }
18739 TODO
18740 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018741 break;
18742 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018743 case XML_SCHEMA_FACET_PATTERN:
18744 facet->regexp = xmlRegexpCompile(facet->value);
18745 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018746 ret = XML_SCHEMAP_REGEXP_INVALID;
18747 /* No error message for RelaxNG. */
18748 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018749 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018750 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018751 "The value '%s' of the facet 'pattern' is not a "
18752 "valid regular expression",
18753 facet->value, NULL);
18754 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018755 }
18756 break;
18757 case XML_SCHEMA_FACET_TOTALDIGITS:
18758 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18759 case XML_SCHEMA_FACET_LENGTH:
18760 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018761 case XML_SCHEMA_FACET_MINLENGTH:
18762
18763 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18764 ret = xmlSchemaValidatePredefinedType(
18765 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18766 facet->value, &(facet->val));
18767 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018768 ret = xmlSchemaValidatePredefinedType(
18769 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18770 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018771 }
18772 if (ret != 0) {
18773 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018774 /* No error message for RelaxNG. */
18775 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018776 PERROR_INT("xmlSchemaCheckFacet",
18777 "validating facet value");
18778 }
18779 goto internal_error;
18780 }
18781 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18782 /* No error message for RelaxNG. */
18783 if (ctxtGiven) {
18784 /* error code */
18785 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18786 ret, facet->node, WXS_BASIC_CAST typeDecl,
Daniel Veillarddee23482008-04-11 12:58:43 +000018787 "The value '%s' of the facet '%s' is not a valid '%s'",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018788 facet->value,
18789 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillarddee23482008-04-11 12:58:43 +000018790 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018791 BAD_CAST "nonNegativeInteger" :
18792 BAD_CAST "positiveInteger",
18793 NULL);
18794 }
18795 }
18796 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000018797
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018798 case XML_SCHEMA_FACET_WHITESPACE:{
18799 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18800 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18801 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18802 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18803 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18804 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18805 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018806 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18807 /* No error message for RelaxNG. */
18808 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018809 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018810 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018811 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018812 "The value '%s' of the facet 'whitespace' is not "
18813 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018814 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018815 }
18816 }
18817 default:
18818 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018819 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018820exit:
18821 if ((! ctxtGiven) && (pctxt != NULL))
18822 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018823 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018824internal_error:
18825 if ((! ctxtGiven) && (pctxt != NULL))
18826 xmlSchemaFreeParserCtxt(pctxt);
18827 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018828}
18829
18830/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018831 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018832 * @typeDecl: the schema type definition
18833 * @ctxt: the schema parser context
18834 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018835 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018836 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018837static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018838xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018839 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018840{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018841 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018842 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018843 /*
18844 * NOTE: It is intended to use the facets list, instead
18845 * of facetSet.
18846 */
18847 if (typeDecl->facets != NULL) {
18848 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018849
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018850 /*
18851 * Temporarily assign the "schema" to the validation context
18852 * of the parser context. This is needed for NOTATION validation.
18853 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018854 if (pctxt->vctxt == NULL) {
18855 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18856 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018857 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018858 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018859 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018860 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18861 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018862 facet = facet->next;
18863 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018864 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018865 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018866 if (olderrs != pctxt->nberrors)
18867 return(pctxt->err);
18868 return(0);
18869exit_failure:
18870 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018871}
18872
18873/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018874 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018875 * @ctxtMGroup: the searched model group
18876 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018877 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018878 *
18879 * This one is intended to be used by
18880 * xmlSchemaCheckGroupDefCircular only.
18881 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018882 * Returns the particle with the circular model group definition reference,
18883 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018884 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018885static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018886xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018887 xmlSchemaTreeItemPtr particle)
18888{
18889 xmlSchemaTreeItemPtr circ = NULL;
18890 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018891 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018892
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018893 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018894 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018895 if (term == NULL)
18896 continue;
18897 switch (term->type) {
18898 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018899 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018900 if (gdef == groupDef)
18901 return (particle);
18902 /*
18903 * Mark this model group definition to avoid infinite
18904 * recursion on circular references not yet examined.
18905 */
18906 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18907 continue;
18908 if (gdef->children != NULL) {
18909 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18910 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18911 gdef->children->children);
18912 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18913 if (circ != NULL)
18914 return (circ);
18915 }
18916 break;
18917 case XML_SCHEMA_TYPE_SEQUENCE:
18918 case XML_SCHEMA_TYPE_CHOICE:
18919 case XML_SCHEMA_TYPE_ALL:
18920 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18921 if (circ != NULL)
18922 return (circ);
18923 break;
18924 default:
18925 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018926 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018927 }
18928 return (NULL);
18929}
18930
18931/**
18932 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018933 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018934 * @ctxt: the parser context
18935 * @name: the name
18936 *
18937 * Checks for circular references to model group definitions.
18938 */
18939static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018940xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018941 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018942{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018943 /*
18944 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018945 * 2 Circular groups are disallowed. That is, within the {particles}
18946 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018947 * is the group itself.
18948 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018949 if ((item == NULL) ||
18950 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18951 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018952 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018953 {
18954 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018956 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018957 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018958 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018959 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018960 * TODO: The error report is not adequate: this constraint
18961 * is defined for model groups but not definitions, but since
18962 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018963 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018964 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018965 */
18966 xmlSchemaPCustomErr(ctxt,
18967 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018968 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018969 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018970 "defined", xmlSchemaFormatQName(&str,
18971 item->targetNamespace, item->name));
18972 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018973 /*
18974 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018975 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018976 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018977 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018978 }
18979 }
18980}
18981
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018982/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018983 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018984 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018985 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018986 *
18987 * Assigns the model group of model group definitions to the "term"
18988 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018989 * In xmlSchemaResolveModelGroupParticleReferences the model group
18990 * definitions were assigned to the "term", since needed for the
18991 * circularity check.
18992 *
18993 * Schema Component Constraint:
18994 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018995 */
18996static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018997xmlSchemaModelGroupToModelGroupDefFixup(
18998 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18999 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019000{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019001 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19002
19003 while (particle != NULL) {
19004 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19005 ((WXS_PARTICLE_TERM(particle))->type !=
19006 XML_SCHEMA_TYPE_GROUP))
19007 {
19008 particle = WXS_PTC_CAST particle->next;
19009 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000019010 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019011 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19012 /*
19013 * TODO: Remove the particle.
19014 */
19015 WXS_PARTICLE_TERM(particle) = NULL;
19016 particle = WXS_PTC_CAST particle->next;
19017 continue;
19018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019019 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019020 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019021 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019022 WXS_PARTICLE_TERM(particle) =
19023 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19024
19025 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019026 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019027}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019028
19029/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019030 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019031 * @ctxtGr: the searched attribute group
19032 * @attr: the current attribute list to be processed
19033 *
19034 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019035 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019036 *
19037 * Returns the circular attribute grou reference, otherwise NULL.
19038 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019039static xmlSchemaQNameRefPtr
19040xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19041 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019042{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019043 xmlSchemaAttributeGroupPtr gr;
19044 xmlSchemaQNameRefPtr ref, circ;
19045 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019046 /*
19047 * We will search for an attribute group reference which
19048 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019049 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019050 for (i = 0; i < list->nbItems; i++) {
19051 ref = list->items[i];
19052 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19053 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19054 (ref->item != NULL))
19055 {
19056 gr = WXS_ATTR_GROUP_CAST ref->item;
19057 if (gr == ctxtGr)
19058 return(ref);
19059 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
Daniel Veillarddee23482008-04-11 12:58:43 +000019060 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019061 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019062 * Mark as visited to avoid infinite recursion on
19063 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019064 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019065 if ((gr->attrUses) &&
19066 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19067 {
19068 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19069 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019070 (xmlSchemaItemListPtr) gr->attrUses);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019071 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19072 if (circ != NULL)
19073 return (circ);
19074 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019075
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019076 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019077 }
19078 return (NULL);
19079}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019080
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019081/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019082 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019083 * attrGr: the attribute group definition
19084 * @ctxt: the parser context
19085 * @name: the name
19086 *
19087 * Checks for circular references of attribute groups.
19088 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019089static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019090xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019091 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019092{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019093 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019094 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019095 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019096 * 3 Circular group reference is disallowed outside <redefine>.
19097 * That is, unless this element information item's parent is
19098 * <redefine>, then among the [children], if any, there must
19099 * not be an <attributeGroup> with ref [attribute] which resolves
19100 * to the component corresponding to this <attributeGroup>. Indirect
19101 * circularity is also ruled out. That is, when QName resolution
Jan Pokorný761c9e92013-11-29 23:26:27 +010019102 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019103 * any <attributeGroup>s with a ref [attribute] among the [children],
Jan Pokorný761c9e92013-11-29 23:26:27 +010019104 * it must not be the case that a `QName` is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019105 * which resolves to the component corresponding to this <attributeGroup>.
19106 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019107 if (attrGr->attrUses == NULL)
19108 return(0);
19109 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19110 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019111 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019112 xmlSchemaQNameRefPtr circ;
Daniel Veillarddee23482008-04-11 12:58:43 +000019113
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019114 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019115 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019116 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019117 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019118 /*
19119 * TODO: Report the referenced attr group as QName.
19120 */
19121 xmlSchemaPCustomErr(ctxt,
19122 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019123 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019124 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019125 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19126 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019127 /*
19128 * NOTE: We will cut the reference to avoid further
19129 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019130 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019131 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019132 circ->item = NULL;
19133 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019134 }
19135 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019136 return(0);
19137}
19138
19139static int
19140xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19141 xmlSchemaAttributeGroupPtr attrGr);
19142
19143/**
19144 * xmlSchemaExpandAttributeGroupRefs:
19145 * @pctxt: the parser context
19146 * @node: the node of the component holding the attribute uses
Daniel Veillarddee23482008-04-11 12:58:43 +000019147 * @completeWild: the intersected wildcard to be returned
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019148 * @list: the attribute uses
19149 *
19150 * Substitutes contained attribute group references
19151 * for their attribute uses. Wilcards are intersected.
19152 * Attribute use prohibitions are removed from the list
19153 * and returned via the @prohibs list.
19154 * Pointlessness of attr. prohibs, if a matching attr. decl
19155 * is existent a well, are checked.
19156 */
19157static int
19158xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19159 xmlSchemaBasicItemPtr item,
19160 xmlSchemaWildcardPtr *completeWild,
19161 xmlSchemaItemListPtr list,
19162 xmlSchemaItemListPtr prohibs)
19163{
19164 xmlSchemaAttributeGroupPtr gr;
19165 xmlSchemaAttributeUsePtr use;
19166 xmlSchemaItemListPtr sublist;
19167 int i, j;
19168 int created = (*completeWild == NULL) ? 0 : 1;
19169
19170 if (prohibs)
19171 prohibs->nbItems = 0;
19172
19173 for (i = 0; i < list->nbItems; i++) {
19174 use = list->items[i];
19175
Daniel Veillarddee23482008-04-11 12:58:43 +000019176 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019177 if (prohibs == NULL) {
19178 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19179 "unexpected attr prohibition found");
19180 return(-1);
19181 }
19182 /*
19183 * Remove from attribute uses.
19184 */
19185 if (xmlSchemaItemListRemove(list, i) == -1)
19186 return(-1);
19187 i--;
19188 /*
19189 * Note that duplicate prohibitions were already
19190 * handled at parsing time.
Daniel Veillarddee23482008-04-11 12:58:43 +000019191 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019192 /*
19193 * Add to list of prohibitions.
19194 */
19195 xmlSchemaItemListAddSize(prohibs, 2, use);
19196 continue;
19197 }
19198 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19199 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19200 {
19201 if ((WXS_QNAME_CAST use)->item == NULL)
19202 return(-1);
19203 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19204 /*
19205 * Expand the referenced attr. group.
19206 * TODO: remove this, this is done in a previous step, so
19207 * already done here.
19208 */
19209 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19210 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19211 return(-1);
19212 }
19213 /*
19214 * Build the 'complete' wildcard; i.e. intersect multiple
19215 * wildcards.
19216 */
19217 if (gr->attributeWildcard != NULL) {
19218 if (*completeWild == NULL) {
19219 *completeWild = gr->attributeWildcard;
19220 } else {
19221 if (! created) {
19222 xmlSchemaWildcardPtr tmpWild;
19223
19224 /*
19225 * Copy the first encountered wildcard as context,
19226 * except for the annotation.
19227 *
19228 * Although the complete wildcard might not correspond
19229 * to any node in the schema, we will anchor it on
19230 * the node of the owner component.
19231 */
19232 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19233 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19234 WXS_ITEM_NODE(item));
19235 if (tmpWild == NULL)
19236 return(-1);
19237 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19238 tmpWild, *completeWild) == -1)
19239 return (-1);
19240 tmpWild->processContents = (*completeWild)->processContents;
19241 *completeWild = tmpWild;
19242 created = 1;
19243 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019244
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019245 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19246 gr->attributeWildcard) == -1)
19247 return(-1);
19248 }
19249 }
19250 /*
19251 * Just remove the reference if the referenced group does not
19252 * contain any attribute uses.
19253 */
William M. Brack06559b32007-03-14 09:34:15 +000019254 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19255 if ((sublist == NULL) || sublist->nbItems == 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019256 if (xmlSchemaItemListRemove(list, i) == -1)
19257 return(-1);
19258 i--;
19259 continue;
19260 }
19261 /*
19262 * Add the attribute uses.
19263 */
William M. Brack06559b32007-03-14 09:34:15 +000019264 list->items[i] = sublist->items[0];
19265 if (sublist->nbItems != 1) {
19266 for (j = 1; j < sublist->nbItems; j++) {
19267 i++;
19268 if (xmlSchemaItemListInsert(list,
19269 sublist->items[j], i) == -1)
19270 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019271 }
William M. Brack06559b32007-03-14 09:34:15 +000019272 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019273 }
19274
19275 }
19276 /*
19277 * Handle pointless prohibitions of declared attributes.
19278 */
19279 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19280 xmlSchemaAttributeUseProhibPtr prohib;
19281
19282 for (i = prohibs->nbItems -1; i >= 0; i--) {
19283 prohib = prohibs->items[i];
19284 for (j = 0; j < list->nbItems; j++) {
19285 use = list->items[j];
19286
19287 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19288 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19289 {
19290 xmlChar *str = NULL;
19291
19292 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19293 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19294 prohib->node, NULL,
19295 "Skipping pointless attribute use prohibition "
19296 "'%s', since a corresponding attribute use "
19297 "exists already in the type definition",
19298 xmlSchemaFormatQName(&str,
19299 prohib->targetNamespace, prohib->name),
19300 NULL, NULL);
19301 FREE_AND_NULL(str);
19302 /*
19303 * Remove the prohibition.
19304 */
19305 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19306 return(-1);
19307 break;
19308 }
19309 }
19310 }
19311 }
19312 return(0);
19313}
19314
19315/**
19316 * xmlSchemaAttributeGroupExpandRefs:
19317 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019318 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019319 *
19320 * Computation of:
19321 * {attribute uses} property
19322 * {attribute wildcard} property
19323 *
19324 * Substitutes contained attribute group references
19325 * for their attribute uses. Wilcards are intersected.
19326 */
19327static int
19328xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19329 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019330{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019331 if ((attrGr->attrUses == NULL) ||
19332 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19333 return(0);
19334
19335 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19336 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19337 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000019338 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019339 return(0);
19340}
19341
19342/**
19343 * xmlSchemaAttributeGroupExpandRefs:
19344 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019345 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019346 *
19347 * Substitutes contained attribute group references
19348 * for their attribute uses. Wilcards are intersected.
Daniel Veillarddee23482008-04-11 12:58:43 +000019349 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019350 * Schema Component Constraint:
Daniel Veillarddee23482008-04-11 12:58:43 +000019351 * Attribute Group Definition Properties Correct (ag-props-correct)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019352 */
19353static int
19354xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19355 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019356{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019357 /*
19358 * SPEC ag-props-correct
19359 * (1) "The values of the properties of an attribute group definition
19360 * must be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019361 * Group Definition Schema Component ($3.6.1), modulo the impact of
19362 * Missing Sub-components ($5.3);"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019363 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019364
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019365 if ((attrGr->attrUses != NULL) &&
19366 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19367 {
19368 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19369 xmlSchemaAttributeUsePtr use, tmp;
19370 int i, j, hasId = 0;
19371
19372 for (i = uses->nbItems -1; i >= 0; i--) {
Daniel Veillarddee23482008-04-11 12:58:43 +000019373 use = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019374 /*
19375 * SPEC ag-props-correct
19376 * (2) "Two distinct members of the {attribute uses} must not have
19377 * {attribute declaration}s both of whose {name}s match and whose
19378 * {target namespace}s are identical."
19379 */
19380 if (i > 0) {
19381 for (j = i -1; j >= 0; j--) {
19382 tmp = uses->items[j];
19383 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19384 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19385 (WXS_ATTRUSE_DECL_TNS(use) ==
19386 WXS_ATTRUSE_DECL_TNS(tmp)))
19387 {
19388 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019389
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019390 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19391 XML_SCHEMAP_AG_PROPS_CORRECT,
19392 attrGr->node, WXS_BASIC_CAST attrGr,
19393 "Duplicate %s",
19394 xmlSchemaGetComponentDesignation(&str, use),
19395 NULL);
19396 FREE_AND_NULL(str);
19397 /*
19398 * Remove the duplicate.
19399 */
19400 if (xmlSchemaItemListRemove(uses, i) == -1)
19401 return(-1);
19402 goto next_use;
19403 }
19404 }
19405 }
19406 /*
19407 * SPEC ag-props-correct
19408 * (3) "Two distinct members of the {attribute uses} must not have
19409 * {attribute declaration}s both of whose {type definition}s are or
19410 * are derived from ID."
19411 * TODO: Does 'derived' include member-types of unions?
19412 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019413 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019414 if (xmlSchemaIsDerivedFromBuiltInType(
19415 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000019416 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019417 if (hasId) {
19418 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019419
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019420 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19421 XML_SCHEMAP_AG_PROPS_CORRECT,
19422 attrGr->node, WXS_BASIC_CAST attrGr,
19423 "There must not exist more than one attribute "
19424 "declaration of type 'xs:ID' "
19425 "(or derived from 'xs:ID'). The %s violates this "
19426 "constraint",
19427 xmlSchemaGetComponentDesignation(&str, use),
19428 NULL);
19429 FREE_AND_NULL(str);
19430 if (xmlSchemaItemListRemove(uses, i) == -1)
19431 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000019432 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019433 hasId = 1;
19434 }
19435 }
19436next_use: {}
19437 }
19438 }
19439 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019440}
19441
19442/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019443 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019444 * @attrgrpDecl: the schema attribute definition
19445 * @ctxt: the schema parser context
19446 * @name: the attribute name
19447 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019448 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019449 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019450static int
19451xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19452 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019453{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019454 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019455
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019456 if (ref->item != NULL)
19457 return(0);
19458 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19459 ref->name,
19460 ref->targetNamespace);
19461 if (group == NULL) {
19462 xmlSchemaPResCompAttrErr(ctxt,
19463 XML_SCHEMAP_SRC_RESOLVE,
19464 NULL, ref->node,
19465 "ref", ref->name, ref->targetNamespace,
19466 ref->itemType, NULL);
19467 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019468 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019469 ref->item = WXS_BASIC_CAST group;
19470 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019471}
19472
19473/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019474 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019475 * @item: an schema attribute declaration/use
19476 * @ctxt: a schema parser context
19477 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019478 *
19479 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019480 * Schema Component Constraint:
19481 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019482 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019483 * Validates the value constraints of an attribute declaration/use.
19484 * NOTE that this needs the simle type definitions to be already
19485 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019486 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019487static int
19488xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19489 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019490{
19491
19492 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019493 * SPEC a-props-correct (1)
19494 * "The values of the properties of an attribute declaration must
19495 * be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019496 * Declaration Schema Component ($3.2.1), modulo the impact of
19497 * Missing Sub-components ($5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019498 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019499
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019500 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19501 return(0);
19502
19503 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019504 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019505
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019506 /*
19507 * SPEC a-props-correct (3)
19508 * "If the {type definition} is or is derived from ID then there
19509 * must not be a {value constraint}."
19510 */
19511 if (xmlSchemaIsDerivedFromBuiltInType(
19512 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19513 {
19514 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19515 XML_SCHEMAP_A_PROPS_CORRECT_3,
19516 NULL, WXS_BASIC_CAST attr,
19517 "Value constraints are not allowed if the type definition "
19518 "is or is derived from xs:ID",
19519 NULL, NULL);
19520 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019521 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019522 /*
19523 * SPEC a-props-correct (2)
19524 * "if there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019525 * representation of its value must be `valid` with respect
19526 * to the {type definition} as defined in String Valid ($3.14.4)."
Jan Pokorný7a7cad62013-11-29 23:26:26 +010019527 * TODO: Don't care about the *canonical* stuff here, this requirement
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019528 * will be removed in WXS 1.1 anyway.
19529 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019530 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019531 attr->node, WXS_ATTR_TYPEDEF(attr),
19532 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019533 1, 1, 0);
19534 if (ret != 0) {
19535 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019536 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019537 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019538 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019539 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019540 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019541 XML_SCHEMAP_A_PROPS_CORRECT_2,
19542 NULL, WXS_BASIC_CAST attr,
19543 "The value of the value constraint is not valid",
19544 NULL, NULL);
19545 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019547 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019548
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019549 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019550}
19551
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019552static xmlSchemaElementPtr
19553xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19554 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019555{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019556 xmlSchemaElementPtr ret;
19557
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019558 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019559 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019560 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019561 return (ancestor);
19562
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019563 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019564 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019565 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019566 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019567 WXS_SUBST_HEAD(ancestor));
19568 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019569
19570 return (ret);
19571}
19572
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019573/**
19574 * xmlSchemaCheckElemPropsCorrect:
19575 * @ctxt: a schema parser context
19576 * @decl: the element declaration
19577 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019578 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019579 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019580 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019581 *
19582 * STATUS:
19583 * missing: (6)
19584 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019585static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019586xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19587 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019588{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019589 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019590 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019591 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019592 * SPEC (1) "The values of the properties of an element declaration
19593 * must be as described in the property tableau in The Element
Jan Pokorný761c9e92013-11-29 23:26:27 +010019594 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19595 * Sub-components ($5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019596 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019597 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19598 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019599
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019600 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019601 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010019602 * SPEC (3) "If there is a non-`absent` {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019603 * affiliation}, then {scope} must be global."
19604 */
19605 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19606 xmlSchemaPCustomErr(pctxt,
19607 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019608 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019609 "Only global element declarations can have a "
19610 "substitution group affiliation", NULL);
19611 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019612 }
19613 /*
19614 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19615 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019616 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019617 * property."
19618 */
19619 if (head == elemDecl)
19620 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019621 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019622 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19623 else
19624 circ = NULL;
19625 if (circ != NULL) {
19626 xmlChar *strA = NULL, *strB = NULL;
19627
19628 xmlSchemaPCustomErrExt(pctxt,
19629 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019630 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019631 "The element declaration '%s' defines a circular "
19632 "substitution group to element declaration '%s'",
19633 xmlSchemaGetComponentQName(&strA, circ),
19634 xmlSchemaGetComponentQName(&strB, head),
19635 NULL);
19636 FREE_AND_NULL(strA)
19637 FREE_AND_NULL(strB)
19638 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19639 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019640 /*
19641 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019642 * the {type definition}
19643 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019644 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019645 * of the {substitution group exclusions} of the {substitution group
Jan Pokorný761c9e92013-11-29 23:26:27 +010019646 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019647 * (if the {type definition} is complex) or as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019648 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019649 * simple)."
19650 *
19651 * NOTE: {substitution group exclusions} means the values of the
19652 * attribute "final".
19653 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019654
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019655 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019656 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019657
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019658 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19659 set |= SUBSET_EXTENSION;
19660 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19661 set |= SUBSET_RESTRICTION;
19662
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019663 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019664 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019665 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19666
19667 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019668 xmlSchemaPCustomErrExt(pctxt,
19669 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019670 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019671 "The type definition '%s' was "
19672 "either rejected by the substitution group "
19673 "affiliation '%s', or not validly derived from its type "
19674 "definition '%s'",
19675 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019676 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019677 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019678 FREE_AND_NULL(strA)
19679 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019680 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019681 }
19682 }
19683 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019684 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019685 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019686 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019687 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019688 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019689 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019690 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019691 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019692 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019693 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019694 (WXS_IS_COMPLEX(typeDef) &&
19695 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019696 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19697 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019698
19699 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19700 xmlSchemaPCustomErr(pctxt,
19701 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019702 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019703 "The type definition (or type definition's content type) is or "
19704 "is derived from ID; value constraints are not allowed in "
19705 "conjunction with such a type definition", NULL);
19706 } else if (elemDecl->value != NULL) {
19707 int vcret;
19708 xmlNodePtr node = NULL;
19709
19710 /*
19711 * SPEC (2) "If there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019712 * representation of its value must be `valid` with respect to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019713 * {type definition} as defined in Element Default Valid (Immediate)
Jan Pokorný761c9e92013-11-29 23:26:27 +010019714 * ($3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019715 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019716 if (typeDef == NULL) {
19717 xmlSchemaPErr(pctxt, elemDecl->node,
19718 XML_SCHEMAP_INTERNAL,
19719 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19720 "type is missing... skipping validation of "
19721 "the value constraint", NULL, NULL);
19722 return (-1);
19723 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019724 if (elemDecl->node != NULL) {
19725 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19726 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19727 BAD_CAST "fixed");
19728 else
19729 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19730 BAD_CAST "default");
19731 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019732 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19733 typeDef, elemDecl->value, &(elemDecl->defVal));
19734 if (vcret != 0) {
19735 if (vcret < 0) {
19736 PERROR_INT("xmlSchemaElemCheckValConstr",
19737 "failed to validate the value constraint of an "
19738 "element declaration");
19739 return (-1);
19740 }
19741 return (vcret);
19742 }
19743 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019744
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019745 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019746}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019747
19748/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019749 * xmlSchemaCheckElemSubstGroup:
19750 * @ctxt: a schema parser context
19751 * @decl: the element declaration
19752 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019753 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019754 * Schema Component Constraint:
19755 * Substitution Group (cos-equiv-class)
19756 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019757 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019758 * a list will be built for each subst. group head, holding all direct
19759 * referents to this head.
19760 * NOTE that this function needs:
19761 * 1. circular subst. groups to be checked beforehand
19762 * 2. the declaration's type to be derived from the head's type
19763 *
19764 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019765 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019766 */
19767static void
19768xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19769 xmlSchemaElementPtr elemDecl)
19770{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019771 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019772 /* SPEC (1) "Its {abstract} is false." */
19773 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19774 return;
19775 {
19776 xmlSchemaElementPtr head;
19777 xmlSchemaTypePtr headType, type;
19778 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019779 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019780 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19781 * {disallowed substitutions} as the blocking constraint, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019782 * Substitution Group OK (Transitive) ($3.3.6)."
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019783 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019784 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19785 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019786 set = 0;
19787 methSet = 0;
19788 /*
19789 * The blocking constraints.
19790 */
19791 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19792 continue;
19793 headType = head->subtypes;
19794 type = elemDecl->subtypes;
19795 if (headType == type)
19796 goto add_member;
19797 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19798 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19799 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19800 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19801 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019802 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019803 * "The set of all {derivation method}s involved in the
19804 * derivation of D's {type definition} from C's {type definition}
19805 * does not intersect with the union of the blocking constraint,
19806 * C's {prohibited substitutions} (if C is complex, otherwise the
19807 * empty set) and the {prohibited substitutions} (respectively the
19808 * empty set) of any intermediate {type definition}s in the
19809 * derivation of D's {type definition} from C's {type definition}."
19810 */
19811 /*
19812 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19813 * subst.head axis, the methSet does not need to be computed for
19814 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019815 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019816 /*
19817 * The set of all {derivation method}s involved in the derivation
19818 */
19819 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019820 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019821 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19822 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019823
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019824 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019825 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19826 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19827
19828 type = type->baseType;
19829 }
19830 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019831 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019832 * the head's type.
19833 */
19834 type = elemDecl->subtypes->baseType;
19835 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019836 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019837 if ((type->flags &
19838 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19839 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19840 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19841 if ((type->flags &
19842 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19843 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19844 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19845 } else
19846 break;
19847 if (type == headType)
19848 break;
19849 type = type->baseType;
19850 }
19851 if ((set != 0) &&
19852 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19853 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19854 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19855 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19856 continue;
19857 }
19858add_member:
19859 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19860 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19861 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19862 }
19863 }
19864}
19865
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019866#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19867/**
19868 * xmlSchemaCheckElementDeclComponent
19869 * @pctxt: the schema parser context
19870 * @ctxtComponent: the context component (an element declaration)
19871 * @ctxtParticle: the first particle of the context component
19872 * @searchParticle: the element declaration particle to be analysed
19873 *
Daniel Veillarddee23482008-04-11 12:58:43 +000019874 * Schema Component Constraint: Element Declarations Consistent
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019875 */
19876static int
19877xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19878 xmlSchemaBasicItemPtr ctxtComponent,
Daniel Veillarddee23482008-04-11 12:58:43 +000019879 xmlSchemaParticlePtr ctxtParticle,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019880 xmlSchemaParticlePtr searchParticle,
19881 xmlSchemaParticlePtr curParticle,
19882 int search)
19883{
19884 return(0);
19885
19886 int ret = 0;
19887 xmlSchemaParticlePtr cur = curParticle;
Daniel Veillarddee23482008-04-11 12:58:43 +000019888 if (curParticle == NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019889 return(0);
19890 }
19891 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19892 /*
19893 * Just return in this case. A missing "term" of the particle
19894 * might arise due to an invalid "term" component.
19895 */
19896 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000019897 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019898 while (cur != NULL) {
19899 switch (WXS_PARTICLE_TERM(cur)->type) {
19900 case XML_SCHEMA_TYPE_ANY:
19901 break;
19902 case XML_SCHEMA_TYPE_ELEMENT:
19903 if (search == 0) {
19904 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19905 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19906 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000019907 return(ret);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019908 } else {
19909 xmlSchemaElementPtr elem =
19910 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19911 /*
19912 * SPEC Element Declarations Consistent:
19913 * "If the {particles} contains, either directly,
19914 * indirectly (that is, within the {particles} of a
Jan Pokorný761c9e92013-11-29 23:26:27 +010019915 * contained model group, recursively) or `implicitly`
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019916 * two or more element declaration particles with
19917 * the same {name} and {target namespace}, then
19918 * all their type definitions must be the same
19919 * top-level definition [...]"
19920 */
19921 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19922 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19923 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19924 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19925 {
19926 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019927
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019928 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19929 /* TODO: error code */
19930 XML_SCHEMAP_COS_NONAMBIG,
19931 WXS_ITEM_NODE(cur), NULL,
19932 "In the content model of %s, there are multiple "
19933 "element declarations for '%s' with different "
19934 "type definitions",
19935 xmlSchemaGetComponentDesignation(&strA,
19936 ctxtComponent),
19937 xmlSchemaFormatQName(&strB,
19938 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19939 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19940 FREE_AND_NULL(strA);
19941 FREE_AND_NULL(strB);
19942 return(XML_SCHEMAP_COS_NONAMBIG);
19943 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019944 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019945 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000019946 case XML_SCHEMA_TYPE_SEQUENCE: {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019947 break;
19948 }
19949 case XML_SCHEMA_TYPE_CHOICE:{
19950 /*
19951 xmlSchemaTreeItemPtr sub;
Daniel Veillarddee23482008-04-11 12:58:43 +000019952
19953 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019954 while (sub != NULL) {
19955 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19956 ctxtParticle, ctxtElem);
19957 if (ret != 0)
19958 return(ret);
19959 sub = sub->next;
19960 }
19961 */
19962 break;
19963 }
19964 case XML_SCHEMA_TYPE_ALL:
19965 break;
19966 case XML_SCHEMA_TYPE_GROUP:
19967 break;
19968 default:
19969 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19970 "xmlSchemaCheckElementDeclConsistent",
19971 "found unexpected term of type '%s' in content model",
19972 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19973 return(-1);
19974 }
19975 cur = (xmlSchemaParticlePtr) cur->next;
19976 }
19977
19978exit:
19979 return(ret);
19980}
19981#endif
19982
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019983/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019984 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019985 * @item: an schema element declaration/particle
19986 * @ctxt: a schema parser context
19987 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019988 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019989 * Validates the value constraints of an element declaration.
Daniel Veillarddee23482008-04-11 12:58:43 +000019990 * Adds substitution group members.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019991 */
19992static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019993xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019994 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019995{
19996 if (elemDecl == NULL)
19997 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019998 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19999 return;
20000 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020001 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20002 /*
20003 * Adds substitution group members.
20004 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020005 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020006 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020007}
20008
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020009/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020010 * xmlSchemaResolveModelGroupParticleReferences:
20011 * @particle: a particle component
20012 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020013 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020014 * Resolves references of a model group's {particles} to
20015 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020016 */
20017static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020018xmlSchemaResolveModelGroupParticleReferences(
20019 xmlSchemaParserCtxtPtr ctxt,
20020 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020021{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020022 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20023 xmlSchemaQNameRefPtr ref;
20024 xmlSchemaBasicItemPtr refItem;
20025
20026 /*
20027 * URGENT TODO: Test this.
20028 */
20029 while (particle != NULL) {
20030 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20031 ((WXS_PARTICLE_TERM(particle))->type !=
20032 XML_SCHEMA_EXTRA_QNAMEREF))
20033 {
20034 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020035 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020036 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020037 /*
20038 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020039 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020040 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020041 particle->children = NULL;
20042
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020043 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20044 ref->itemType, ref->name, ref->targetNamespace);
20045 if (refItem == NULL) {
20046 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020047 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020048 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020049 /* TODO: remove the particle. */
20050 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020051 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020052 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20053 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20054 /* TODO: remove the particle. */
20055 goto next_particle;
20056 /*
20057 * NOTE that we will assign the model group definition
20058 * itself to the "term" of the particle. This will ease
20059 * the check for circular model group definitions. After
20060 * that the "term" will be assigned the model group of the
20061 * model group definition.
20062 */
20063 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20064 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020065 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020066 * SPEC cos-all-limited (1)
20067 * SPEC cos-all-limited (1.2)
20068 * "It appears only as the value of one or both of the
20069 * following properties:"
20070 * (1.1) "the {model group} property of a model group
20071 * definition."
20072 * (1.2) "the {term} property of a particle [... of] the "
20073 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020074 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020075 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20076 /* TODO: error code */
20077 XML_SCHEMAP_COS_ALL_LIMITED,
20078 WXS_ITEM_NODE(particle), NULL,
20079 "A model group definition is referenced, but "
20080 "it contains an 'all' model group, which "
20081 "cannot be contained by model groups",
20082 NULL, NULL);
20083 /* TODO: remove the particle. */
20084 goto next_particle;
20085 }
20086 particle->children = (xmlSchemaTreeItemPtr) refItem;
20087 } else {
20088 /*
20089 * TODO: Are referenced element declarations the only
20090 * other components we expect here?
20091 */
20092 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020093 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020094next_particle:
20095 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020096 }
20097}
20098
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020099static int
20100xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
Daniel Veillarddee23482008-04-11 12:58:43 +000020101 xmlSchemaValPtr y)
20102{
20103 xmlSchemaTypePtr tx, ty, ptx, pty;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020104 int ret;
20105
20106 while (x != NULL) {
20107 /* Same types. */
20108 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20109 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20110 ptx = xmlSchemaGetPrimitiveType(tx);
20111 pty = xmlSchemaGetPrimitiveType(ty);
20112 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020113 * (1) if a datatype T' is `derived` by `restriction` from an
20114 * atomic datatype T then the `value space` of T' is a subset of
20115 * the `value space` of T. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020116 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020117 * (2) if datatypes T' and T'' are `derived` by `restriction`
20118 * from a common atomic ancestor T then the `value space`s of T'
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020119 * and T'' may overlap.
20120 */
20121 if (ptx != pty)
20122 return(0);
20123 /*
20124 * We assume computed values to be normalized, so do a fast
20125 * string comparison for string based types.
20126 */
20127 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020128 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020129 if (! xmlStrEqual(
20130 xmlSchemaValueGetAsString(x),
20131 xmlSchemaValueGetAsString(y)))
20132 return (0);
20133 } else {
20134 ret = xmlSchemaCompareValuesWhtsp(
20135 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20136 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20137 if (ret == -2)
20138 return(-1);
20139 if (ret != 0)
20140 return(0);
20141 }
20142 /*
20143 * Lists.
20144 */
20145 x = xmlSchemaValueGetNext(x);
20146 if (x != NULL) {
20147 y = xmlSchemaValueGetNext(y);
20148 if (y == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020149 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020150 } else if (xmlSchemaValueGetNext(y) != NULL)
20151 return (0);
20152 else
20153 return (1);
20154 }
20155 return (0);
20156}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020157
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020158/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020159 * xmlSchemaResolveAttrUseReferences:
20160 * @item: an attribute use
20161 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020162 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020163 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020164 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020165static int
20166xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20167 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000020168{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020169 if ((ctxt == NULL) || (ause == NULL))
20170 return(-1);
20171 if ((ause->attrDecl == NULL) ||
20172 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20173 return(0);
20174
20175 {
20176 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20177
20178 /*
20179 * TODO: Evaluate, what errors could occur if the declaration is not
20180 * found.
20181 */
20182 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20183 ref->name, ref->targetNamespace);
20184 if (ause->attrDecl == NULL) {
20185 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardf8e3db02012-09-11 13:26:36 +080020186 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020187 WXS_BASIC_CAST ause, ause->node,
20188 "ref", ref->name, ref->targetNamespace,
20189 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20190 return(ctxt->err);;
20191 }
20192 }
20193 return(0);
20194}
20195
20196/**
20197 * xmlSchemaCheckAttrUsePropsCorrect:
20198 * @ctxt: a parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000020199 * @use: an attribute use
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020200 *
20201 * Schema Component Constraint:
20202 * Attribute Use Correct (au-props-correct)
Daniel Veillarddee23482008-04-11 12:58:43 +000020203 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020204 */
20205static int
20206xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20207 xmlSchemaAttributeUsePtr use)
20208{
20209 if ((ctxt == NULL) || (use == NULL))
20210 return(-1);
20211 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20212 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
Daniel Veillarddee23482008-04-11 12:58:43 +000020213 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020214
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020215 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020216 * SPEC au-props-correct (1)
20217 * "The values of the properties of an attribute use must be as
20218 * described in the property tableau in The Attribute Use Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020219 * Component ($3.5.1), modulo the impact of Missing
20220 * Sub-components ($5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000020221 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020222
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020223 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20224 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20225 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20226 {
20227 xmlSchemaPCustomErr(ctxt,
20228 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20229 WXS_BASIC_CAST use, NULL,
20230 "The attribute declaration has a 'fixed' value constraint "
20231 ", thus the attribute use must also have a 'fixed' value "
20232 "constraint",
20233 NULL);
20234 return(ctxt->err);
20235 }
20236 /*
20237 * Compute and check the value constraint's value.
20238 */
20239 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20240 int ret;
20241 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000020242 * TODO: The spec seems to be missing a check of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020243 * value constraint of the attribute use. We will do it here.
20244 */
20245 /*
20246 * SPEC a-props-correct (3)
20247 */
20248 if (xmlSchemaIsDerivedFromBuiltInType(
20249 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20250 {
20251 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20252 XML_SCHEMAP_AU_PROPS_CORRECT,
20253 NULL, WXS_BASIC_CAST use,
20254 "Value constraints are not allowed if the type definition "
20255 "is or is derived from xs:ID",
20256 NULL, NULL);
20257 return(ctxt->err);
20258 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020259
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020260 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20261 use->node, WXS_ATTRUSE_TYPEDEF(use),
20262 use->defValue, &(use->defVal),
20263 1, 1, 0);
20264 if (ret != 0) {
20265 if (ret < 0) {
20266 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20267 "calling xmlSchemaVCheckCVCSimpleType()");
20268 return(-1);
20269 }
20270 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20271 XML_SCHEMAP_AU_PROPS_CORRECT,
20272 NULL, WXS_BASIC_CAST use,
20273 "The value of the value constraint is not valid",
20274 NULL, NULL);
20275 return(ctxt->err);
20276 }
20277 }
20278 /*
20279 * SPEC au-props-correct (2)
20280 * "If the {attribute declaration} has a fixed
20281 * {value constraint}, then if the attribute use itself has a
20282 * {value constraint}, it must also be fixed and its value must match
20283 * that of the {attribute declaration}'s {value constraint}."
20284 */
20285 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20286 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20287 {
20288 if (! xmlSchemaAreValuesEqual(use->defVal,
20289 (WXS_ATTRUSE_DECL(use))->defVal))
20290 {
20291 xmlSchemaPCustomErr(ctxt,
20292 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20293 WXS_BASIC_CAST use, NULL,
20294 "The 'fixed' value constraint of the attribute use "
20295 "must match the attribute declaration's value "
20296 "constraint '%s'",
20297 (WXS_ATTRUSE_DECL(use))->defValue);
20298 }
20299 return(ctxt->err);
20300 }
20301 return(0);
20302}
20303
20304
20305
20306
20307/**
20308 * xmlSchemaResolveAttrTypeReferences:
20309 * @item: an attribute declaration
Daniel Veillarddee23482008-04-11 12:58:43 +000020310 * @ctxt: a parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020311 *
20312 * Resolves the referenced type definition component.
20313 */
20314static int
20315xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20316 xmlSchemaParserCtxtPtr ctxt)
20317{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020318 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020319 * The simple type definition corresponding to the <simpleType> element
20320 * information item in the [children], if present, otherwise the simple
Jan Pokorný761c9e92013-11-29 23:26:27 +010020321 * type definition `resolved` to by the `actual value` of the type
20322 * [attribute], if present, otherwise the `simple ur-type definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000020323 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020324 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020325 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020326 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20327 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020328 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020329 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020330 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020331
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020332 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20333 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020334 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020335 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020336 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020337 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020338 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020339 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020340 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020341 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020342 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020343
Daniel Veillard3646d642004-06-02 19:19:14 +000020344 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020345 /*
20346 * The type defaults to the xs:anySimpleType.
20347 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020348 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20349 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020350 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020351}
20352
20353/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020354 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020355 * @idc: the identity-constraint definition
20356 * @ctxt: the schema parser context
20357 * @name: the attribute name
20358 *
20359 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020360 * Schema Component Constraint:
20361 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020362 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020363static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020364xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020365 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020366{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020367 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020368 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020369 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020370 idc->ref->item = (xmlSchemaBasicItemPtr)
20371 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20372 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020373 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020374 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020375 * TODO: It is actually not an error to fail to resolve
20376 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020377 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020378 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020379 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020380 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020381 "refer", idc->ref->name,
20382 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020383 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020384 return(pctxt->err);
20385 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20386 /*
20387 * SPEC c-props-correct (1)
20388 */
20389 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20390 XML_SCHEMAP_C_PROPS_CORRECT,
20391 NULL, WXS_BASIC_CAST idc,
20392 "The keyref references a keyref",
20393 NULL, NULL);
20394 idc->ref->item = NULL;
20395 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020396 } else {
20397 if (idc->nbFields !=
20398 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20399 xmlChar *str = NULL;
20400 xmlSchemaIDCPtr refer;
Daniel Veillarddee23482008-04-11 12:58:43 +000020401
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020402 refer = (xmlSchemaIDCPtr) idc->ref->item;
20403 /*
20404 * SPEC c-props-correct(2)
20405 * "If the {identity-constraint category} is keyref,
20406 * the cardinality of the {fields} must equal that of
20407 * the {fields} of the {referenced key}.
20408 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020409 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020410 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020411 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020412 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020413 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020414 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020415 refer->name),
20416 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020417 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020418 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020419 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020420 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020421 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020422 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020423}
20424
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020425static int
20426xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20427 xmlSchemaParserCtxtPtr pctxt)
20428{
20429 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20430 prohib->targetNamespace) == NULL) {
20431
20432 xmlSchemaPResCompAttrErr(pctxt,
20433 XML_SCHEMAP_SRC_RESOLVE,
20434 NULL, prohib->node,
20435 "ref", prohib->name, prohib->targetNamespace,
20436 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20437 return(XML_SCHEMAP_SRC_RESOLVE);
20438 }
20439 return(0);
20440}
20441
20442#define WXS_REDEFINED_TYPE(c) \
20443(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20444
20445#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20446(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20447
20448#define WXS_REDEFINED_ATTR_GROUP(c) \
20449(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20450
20451static int
20452xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20453{
20454 int err = 0;
20455 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20456 xmlSchemaBasicItemPtr prev, item;
20457 int wasRedefined;
20458
20459 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020460 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020461
20462 do {
20463 item = redef->item;
20464 /*
20465 * First try to locate the redefined component in the
20466 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020467 * NOTE: According to this schema bug entry:
20468 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20469 * it's not clear if the referenced component needs to originate
20470 * from the <redefine>d schema _document_ or the schema; the latter
20471 * would include all imported and included sub-schemas of the
20472 * <redefine>d schema. Currenlty we latter approach is used.
20473 * SUPPLEMENT: It seems that the WG moves towards the latter
20474 * approach, so we are doing it right.
Daniel Veillarddee23482008-04-11 12:58:43 +000020475 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020476 */
20477 prev = xmlSchemaFindRedefCompInGraph(
20478 redef->targetBucket, item->type,
20479 redef->refName, redef->refTargetNs);
20480 if (prev == NULL) {
20481 xmlChar *str = NULL;
20482 xmlNodePtr node;
20483
20484 /*
20485 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010020486 * (6.2.1) "The `actual value` of its own name attribute plus
20487 * target namespace must successfully `resolve` to a model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020488 * group definition in I."
Jan Pokorný761c9e92013-11-29 23:26:27 +010020489 * (7.2.1) "The `actual value` of its own name attribute plus
20490 * target namespace must successfully `resolve` to an attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020491 * group definition in I."
20492
20493 *
20494 * Note that, if we are redefining with the use of references
20495 * to components, the spec assumes the src-resolve to be used;
20496 * but this won't assure that we search only *inside* the
20497 * redefined schema.
20498 */
20499 if (redef->reference)
20500 node = WXS_ITEM_NODE(redef->reference);
20501 else
20502 node = WXS_ITEM_NODE(item);
20503 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20504 /*
20505 * TODO: error code.
20506 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
Daniel Veillarddee23482008-04-11 12:58:43 +000020507 * reference kind.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020508 */
20509 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020510 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020511 "the redefined schema",
20512 WXS_ITEM_TYPE_NAME(item),
20513 xmlSchemaFormatQName(&str, redef->refTargetNs,
20514 redef->refName));
Daniel Veillarddee23482008-04-11 12:58:43 +000020515 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020516 err = pctxt->err;
20517 redef = redef->next;
20518 continue;
20519 }
20520 /*
20521 * TODO: Obtaining and setting the redefinition state is really
20522 * clumsy.
20523 */
20524 wasRedefined = 0;
20525 switch (item->type) {
20526 case XML_SCHEMA_TYPE_COMPLEX:
20527 case XML_SCHEMA_TYPE_SIMPLE:
20528 if ((WXS_TYPE_CAST prev)->flags &
20529 XML_SCHEMAS_TYPE_REDEFINED)
20530 {
20531 wasRedefined = 1;
20532 break;
20533 }
20534 /* Mark it as redefined. */
20535 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20536 /*
20537 * Assign the redefined type to the
20538 * base type of the redefining type.
20539 * TODO: How
20540 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020541 ((xmlSchemaTypePtr) item)->baseType =
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020542 (xmlSchemaTypePtr) prev;
20543 break;
20544 case XML_SCHEMA_TYPE_GROUP:
20545 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20546 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20547 {
20548 wasRedefined = 1;
20549 break;
20550 }
20551 /* Mark it as redefined. */
20552 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20553 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20554 if (redef->reference != NULL) {
20555 /*
20556 * Overwrite the QName-reference with the
20557 * referenced model group def.
20558 */
20559 (WXS_PTC_CAST redef->reference)->children =
20560 WXS_TREE_CAST prev;
20561 }
20562 redef->target = prev;
20563 break;
20564 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20565 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20566 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20567 {
20568 wasRedefined = 1;
20569 break;
20570 }
20571 (WXS_ATTR_GROUP_CAST prev)->flags |=
20572 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20573 if (redef->reference != NULL) {
20574 /*
20575 * Assign the redefined attribute group to the
20576 * QName-reference component.
20577 * This is the easy case, since we will just
20578 * expand the redefined group.
20579 */
20580 (WXS_QNAME_CAST redef->reference)->item = prev;
20581 redef->target = NULL;
20582 } else {
20583 /*
20584 * This is the complicated case: we need
20585 * to apply src-redefine (7.2.2) at a later
20586 * stage, i.e. when attribute group references
20587 * have beed expanded and simple types have
20588 * beed fixed.
20589 */
20590 redef->target = prev;
20591 }
20592 break;
20593 default:
20594 PERROR_INT("xmlSchemaResolveRedefReferences",
20595 "Unexpected redefined component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020596 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020597 }
20598 if (wasRedefined) {
20599 xmlChar *str = NULL;
20600 xmlNodePtr node;
20601
20602 if (redef->reference)
20603 node = WXS_ITEM_NODE(redef->reference);
20604 else
20605 node = WXS_ITEM_NODE(redef->item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020606
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020607 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20608 /* TODO: error code. */
20609 XML_SCHEMAP_SRC_REDEFINE,
20610 node, NULL,
20611 "The referenced %s was already redefined. Multiple "
20612 "redefinition of the same component is not supported",
20613 xmlSchemaGetComponentDesignation(&str, prev),
20614 NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000020615 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020616 err = pctxt->err;
20617 redef = redef->next;
20618 continue;
20619 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020620 redef = redef->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020621 } while (redef != NULL);
20622
20623 return(err);
20624}
20625
20626static int
20627xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20628{
20629 int err = 0;
20630 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20631 xmlSchemaBasicItemPtr item;
20632
20633 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020634 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020635
20636 do {
20637 if (redef->target == NULL) {
20638 redef = redef->next;
20639 continue;
20640 }
20641 item = redef->item;
Daniel Veillarddee23482008-04-11 12:58:43 +000020642
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020643 switch (item->type) {
20644 case XML_SCHEMA_TYPE_SIMPLE:
20645 case XML_SCHEMA_TYPE_COMPLEX:
20646 /*
20647 * Since the spec wants the {name} of the redefined
20648 * type to be 'absent', we'll NULL it.
20649 */
20650 (WXS_TYPE_CAST redef->target)->name = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020651
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020652 /*
20653 * TODO: Seems like there's nothing more to do. The normal
20654 * inheritance mechanism is used. But not 100% sure.
20655 */
20656 break;
20657 case XML_SCHEMA_TYPE_GROUP:
20658 /*
20659 * URGENT TODO:
20660 * SPEC src-redefine:
20661 * (6.2.2) "The {model group} of the model group definition
20662 * which corresponds to it per XML Representation of Model
Jan Pokorný761c9e92013-11-29 23:26:27 +010020663 * Group Definition Schema Components ($3.7.2) must be a
20664 * `valid restriction` of the {model group} of that model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020665 * group definition in I, as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010020666 * (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020667 */
20668 break;
20669 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20670 /*
20671 * SPEC src-redefine:
20672 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20673 * the attribute group definition which corresponds to it
20674 * per XML Representation of Attribute Group Definition Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020675 * Components ($3.6.2) must be `valid restrictions` of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020676 * {attribute uses} and {attribute wildcard} of that attribute
20677 * group definition in I, as defined in clause 2, clause 3 and
20678 * clause 4 of Derivation Valid (Restriction, Complex)
Jan Pokorný761c9e92013-11-29 23:26:27 +010020679 * ($3.4.6) (where references to the base type definition are
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020680 * understood as references to the attribute group definition
20681 * in I)."
20682 */
20683 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20684 XML_SCHEMA_ACTION_REDEFINE,
20685 item, redef->target,
20686 (WXS_ATTR_GROUP_CAST item)->attrUses,
20687 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20688 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20689 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20690 if (err == -1)
20691 return(-1);
20692 break;
20693 default:
20694 break;
20695 }
20696 redef = redef->next;
20697 } while (redef != NULL);
20698 return(0);
20699}
Daniel Veillarddee23482008-04-11 12:58:43 +000020700
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020701
20702static int
20703xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20704 xmlSchemaBucketPtr bucket)
20705{
20706 xmlSchemaBasicItemPtr item;
20707 int err;
20708 xmlHashTablePtr *table;
20709 const xmlChar *name;
20710 int i;
20711
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020712#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020713 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20714 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20715 else \
20716 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20717
20718 /*
20719 * Add global components to the schema's hash tables.
20720 * This is the place where duplicate components will be
20721 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020722 * TODO: I think normally we should support imports of the
20723 * same namespace from multiple locations. We don't do currently,
20724 * but if we do then according to:
20725 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20726 * we would need, if imported directly, to import redefined
20727 * components as well to be able to catch clashing components.
20728 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020729 */
20730 if (bucket == NULL)
20731 return(-1);
20732 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20733 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000020734 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20735
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020736 for (i = 0; i < bucket->globals->nbItems; i++) {
20737 item = bucket->globals->items[i];
20738 table = NULL;
20739 switch (item->type) {
20740 case XML_SCHEMA_TYPE_COMPLEX:
20741 case XML_SCHEMA_TYPE_SIMPLE:
20742 if (WXS_REDEFINED_TYPE(item))
20743 continue;
20744 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020745 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020746 break;
20747 case XML_SCHEMA_TYPE_ELEMENT:
20748 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020749 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020750 break;
20751 case XML_SCHEMA_TYPE_ATTRIBUTE:
20752 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020753 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020754 break;
20755 case XML_SCHEMA_TYPE_GROUP:
20756 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20757 continue;
20758 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020759 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020760 break;
20761 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20762 if (WXS_REDEFINED_ATTR_GROUP(item))
20763 continue;
20764 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020765 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020766 break;
20767 case XML_SCHEMA_TYPE_IDC_KEY:
20768 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20769 case XML_SCHEMA_TYPE_IDC_KEYREF:
20770 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020771 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020772 break;
20773 case XML_SCHEMA_TYPE_NOTATION:
20774 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020775 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +000020776 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020777 default:
20778 PERROR_INT("xmlSchemaAddComponents",
20779 "Unexpected global component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020780 continue;
20781 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020782 if (*table == NULL) {
20783 *table = xmlHashCreateDict(10, pctxt->dict);
20784 if (*table == NULL) {
20785 PERROR_INT("xmlSchemaAddComponents",
20786 "failed to create a component hash table");
20787 return(-1);
20788 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020789 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020790 err = xmlHashAddEntry(*table, name, item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020791 if (err != 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020792 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020793
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020794 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20795 XML_SCHEMAP_REDEFINED_TYPE,
20796 WXS_ITEM_NODE(item),
20797 WXS_BASIC_CAST item,
20798 "A global %s '%s' does already exist",
20799 WXS_ITEM_TYPE_NAME(item),
20800 xmlSchemaGetComponentQName(&str, item));
Daniel Veillarddee23482008-04-11 12:58:43 +000020801 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020802 }
20803 }
20804 /*
20805 * Process imported/included schemas.
20806 */
20807 if (bucket->relations != NULL) {
20808 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20809 do {
20810 if ((rel->bucket != NULL) &&
20811 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20812 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20813 return(-1);
20814 }
20815 rel = rel->next;
20816 } while (rel != NULL);
20817 }
20818 return(0);
20819}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020820
20821static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020822xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20823 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020824{
20825 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20826 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020827 int nbItems, i, ret = 0;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020828 xmlSchemaBucketPtr oldbucket = con->bucket;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020829 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020830
20831#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20832
20833 if ((con->pending == NULL) ||
20834 (con->pending->nbItems == 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000020835 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020836
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020837 /*
20838 * Since xmlSchemaFixupComplexType() will create new particles
20839 * (local components), and those particle components need a bucket
20840 * on the constructor, we'll assure here that the constructor has
20841 * a bucket.
Daniel Veillarddee23482008-04-11 12:58:43 +000020842 * TODO: Think about storing locals _only_ on the main bucket.
20843 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020844 if (con->bucket == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020845 con->bucket = rootBucket;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020846
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020847 /* TODO:
20848 * SPEC (src-redefine):
20849 * (6.2) "If it has no such self-reference, then all of the
20850 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000020851
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020852 * (6.2.2) The {model group} of the model group definition which
20853 * corresponds to it per XML Representation of Model Group
Jan Pokorný761c9e92013-11-29 23:26:27 +010020854 * Definition Schema Components ($3.7.2) must be a `valid
20855 * restriction` of the {model group} of that model group definition
20856 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020857 */
20858 xmlSchemaCheckSRCRedefineFirst(pctxt);
20859
20860 /*
20861 * Add global components to the schemata's hash tables.
Daniel Veillarddee23482008-04-11 12:58:43 +000020862 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020863 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020864
20865 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020866 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20867 nbItems = con->pending->nbItems;
20868 /*
20869 * Now that we have parsed *all* the schema document(s) and converted
20870 * them to schema components, we can resolve references, apply component
20871 * constraints, create the FSA from the content model, etc.
Daniel Veillarddee23482008-04-11 12:58:43 +000020872 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020873 /*
20874 * Resolve references of..
20875 *
20876 * 1. element declarations:
20877 * - the type definition
20878 * - the substitution group affiliation
20879 * 2. simple/complex types:
20880 * - the base type definition
20881 * - the memberTypes of union types
20882 * - the itemType of list types
20883 * 3. attributes declarations and attribute uses:
20884 * - the type definition
20885 * - if an attribute use, then the attribute declaration
20886 * 4. attribute group references:
20887 * - the attribute group definition
20888 * 5. particles:
20889 * - the term of the particle (e.g. a model group)
20890 * 6. IDC key-references:
20891 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020892 * 7. Attribute prohibitions which had a "ref" attribute.
Daniel Veillarddee23482008-04-11 12:58:43 +000020893 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020894 for (i = 0; i < nbItems; i++) {
20895 item = items[i];
20896 switch (item->type) {
20897 case XML_SCHEMA_TYPE_ELEMENT:
20898 xmlSchemaResolveElementReferences(
20899 (xmlSchemaElementPtr) item, pctxt);
20900 FIXHFAILURE;
20901 break;
20902 case XML_SCHEMA_TYPE_COMPLEX:
20903 case XML_SCHEMA_TYPE_SIMPLE:
20904 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020905 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020906 FIXHFAILURE;
20907 break;
20908 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020909 xmlSchemaResolveAttrTypeReferences(
20910 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020911 FIXHFAILURE;
20912 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020913 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20914 xmlSchemaResolveAttrUseReferences(
20915 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020916 FIXHFAILURE;
20917 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020918 case XML_SCHEMA_EXTRA_QNAMEREF:
Daniel Veillarddee23482008-04-11 12:58:43 +000020919 if ((WXS_QNAME_CAST item)->itemType ==
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020920 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20921 {
20922 xmlSchemaResolveAttrGroupReferences(
20923 WXS_QNAME_CAST item, pctxt);
20924 }
20925 FIXHFAILURE;
20926 break;
20927 case XML_SCHEMA_TYPE_SEQUENCE:
20928 case XML_SCHEMA_TYPE_CHOICE:
20929 case XML_SCHEMA_TYPE_ALL:
20930 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20931 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020932 FIXHFAILURE;
20933 break;
20934 case XML_SCHEMA_TYPE_IDC_KEY:
20935 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20936 case XML_SCHEMA_TYPE_IDC_KEYREF:
20937 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020938 (xmlSchemaIDCPtr) item, pctxt);
20939 FIXHFAILURE;
20940 break;
20941 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20942 /*
20943 * Handle attribue prohibition which had a
20944 * "ref" attribute.
20945 */
20946 xmlSchemaResolveAttrUseProhibReferences(
20947 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020948 FIXHFAILURE;
20949 break;
20950 default:
20951 break;
20952 }
20953 }
20954 if (pctxt->nberrors != 0)
20955 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000020956
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020957 /*
20958 * Now that all references are resolved we
20959 * can check for circularity of...
Daniel Veillarddee23482008-04-11 12:58:43 +000020960 * 1. the base axis of type definitions
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020961 * 2. nested model group definitions
20962 * 3. nested attribute group definitions
20963 * TODO: check for circual substitution groups.
20964 */
20965 for (i = 0; i < nbItems; i++) {
20966 item = items[i];
20967 /*
20968 * Let's better stop on the first error here.
20969 */
20970 switch (item->type) {
20971 case XML_SCHEMA_TYPE_COMPLEX:
20972 case XML_SCHEMA_TYPE_SIMPLE:
20973 xmlSchemaCheckTypeDefCircular(
20974 (xmlSchemaTypePtr) item, pctxt);
20975 FIXHFAILURE;
20976 if (pctxt->nberrors != 0)
20977 goto exit_error;
20978 break;
20979 case XML_SCHEMA_TYPE_GROUP:
20980 xmlSchemaCheckGroupDefCircular(
20981 (xmlSchemaModelGroupDefPtr) item, pctxt);
20982 FIXHFAILURE;
20983 if (pctxt->nberrors != 0)
20984 goto exit_error;
20985 break;
20986 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20987 xmlSchemaCheckAttrGroupCircular(
20988 (xmlSchemaAttributeGroupPtr) item, pctxt);
20989 FIXHFAILURE;
20990 if (pctxt->nberrors != 0)
20991 goto exit_error;
20992 break;
20993 default:
20994 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000020995 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020996 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020997 if (pctxt->nberrors != 0)
20998 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020999 /*
21000 * Model group definition references:
21001 * Such a reference is reflected by a particle at the component
21002 * level. Until now the 'term' of such particles pointed
21003 * to the model group definition; this was done, in order to
21004 * ease circularity checks. Now we need to set the 'term' of
21005 * such particles to the model group of the model group definition.
21006 */
21007 for (i = 0; i < nbItems; i++) {
21008 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021009 switch (item->type) {
21010 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillarddee23482008-04-11 12:58:43 +000021011 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021012 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21013 WXS_MODEL_GROUP_CAST item);
21014 break;
21015 default:
21016 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021017 }
21018 }
21019 if (pctxt->nberrors != 0)
21020 goto exit_error;
21021 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021022 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021023 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021024 for (i = 0; i < nbItems; i++) {
21025 item = items[i];
21026 switch (item->type) {
21027 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21028 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21029 WXS_ATTR_GROUP_HAS_REFS(item))
21030 {
21031 xmlSchemaAttributeGroupExpandRefs(pctxt,
21032 WXS_ATTR_GROUP_CAST item);
21033 FIXHFAILURE;
21034 }
21035 break;
21036 default:
21037 break;
21038 }
21039 }
21040 if (pctxt->nberrors != 0)
21041 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021042 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021043 * First compute the variety of simple types. This is needed as
21044 * a seperate step, since otherwise we won't be able to detect
21045 * circular union types in all cases.
21046 */
21047 for (i = 0; i < nbItems; i++) {
21048 item = items[i];
21049 switch (item->type) {
21050 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021051 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021052 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21053 (xmlSchemaTypePtr) item);
21054 FIXHFAILURE;
21055 }
21056 break;
21057 default:
21058 break;
21059 }
21060 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021061 if (pctxt->nberrors != 0)
21062 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021063 /*
21064 * Detect circular union types. Note that this needs the variety to
21065 * be already computed.
21066 */
21067 for (i = 0; i < nbItems; i++) {
21068 item = items[i];
21069 switch (item->type) {
21070 case XML_SCHEMA_TYPE_SIMPLE:
21071 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021072 xmlSchemaCheckUnionTypeDefCircular(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021073 (xmlSchemaTypePtr) item);
21074 FIXHFAILURE;
21075 }
21076 break;
21077 default:
21078 break;
21079 }
21080 }
21081 if (pctxt->nberrors != 0)
21082 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021083
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021084 /*
21085 * Do the complete type fixup for simple types.
21086 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021087 for (i = 0; i < nbItems; i++) {
21088 item = items[i];
21089 switch (item->type) {
21090 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021091 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21092 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21093 FIXHFAILURE;
21094 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021095 break;
21096 default:
21097 break;
21098 }
21099 }
21100 if (pctxt->nberrors != 0)
21101 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021102 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021103 * At this point we need build and check all simple types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021104 */
21105 /*
21106 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021107 */
21108 for (i = 0; i < nbItems; i++) {
21109 item = items[i];
21110 switch (item->type) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021111 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021112 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21113 FIXHFAILURE;
Daniel Veillarddee23482008-04-11 12:58:43 +000021114 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021115 default:
21116 break;
21117 }
21118 }
21119 if (pctxt->nberrors != 0)
21120 goto exit_error;
21121 /*
21122 * Apply constraints for attribute uses.
Daniel Veillarddee23482008-04-11 12:58:43 +000021123 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021124 for (i = 0; i < nbItems; i++) {
21125 item = items[i];
21126 switch (item->type) {
21127 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21128 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21129 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21130 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021131 FIXHFAILURE;
21132 }
21133 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021134 default:
21135 break;
21136 }
21137 }
21138 if (pctxt->nberrors != 0)
21139 goto exit_error;
21140
21141 /*
21142 * Apply constraints for attribute group definitions.
21143 */
21144 for (i = 0; i < nbItems; i++) {
21145 item = items[i];
21146 switch (item->type) {
21147 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21148 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21149 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21150 {
21151 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21152 FIXHFAILURE;
21153 }
21154 break;
21155 default:
21156 break;
21157 }
21158 }
21159 if (pctxt->nberrors != 0)
21160 goto exit_error;
21161
21162 /*
21163 * Apply constraints for redefinitions.
21164 */
21165 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21166 xmlSchemaCheckSRCRedefineSecond(pctxt);
21167 if (pctxt->nberrors != 0)
21168 goto exit_error;
21169
Daniel Veillarddee23482008-04-11 12:58:43 +000021170 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021171 * Complex types are builded and checked.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021172 */
21173 for (i = 0; i < nbItems; i++) {
21174 item = con->pending->items[i];
21175 switch (item->type) {
21176 case XML_SCHEMA_TYPE_COMPLEX:
21177 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21178 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21179 FIXHFAILURE;
21180 }
21181 break;
21182 default:
21183 break;
21184 }
21185 }
21186 if (pctxt->nberrors != 0)
21187 goto exit_error;
21188
21189 /*
21190 * The list could have changed, since xmlSchemaFixupComplexType()
21191 * will create particles and model groups in some cases.
21192 */
21193 items = (xmlSchemaTreeItemPtr *) con->pending->items;
Daniel Veillarddee23482008-04-11 12:58:43 +000021194 nbItems = con->pending->nbItems;
21195
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021196 /*
21197 * Apply some constraints for element declarations.
21198 */
21199 for (i = 0; i < nbItems; i++) {
21200 item = items[i];
21201 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021202 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021203 elemDecl = (xmlSchemaElementPtr) item;
Daniel Veillarddee23482008-04-11 12:58:43 +000021204
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021205 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21206 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021207 xmlSchemaCheckElementDeclComponent(
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021208 (xmlSchemaElementPtr) elemDecl, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021209 FIXHFAILURE;
21210 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021211
21212#ifdef WXS_ELEM_DECL_CONS_ENABLED
21213 /*
21214 * Schema Component Constraint: Element Declarations Consistent
21215 * Apply this constraint to local types of element declarations.
21216 */
21217 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21218 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21219 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21220 {
21221 xmlSchemaCheckElementDeclConsistent(pctxt,
21222 WXS_BASIC_CAST elemDecl,
21223 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21224 NULL, NULL, 0);
21225 }
21226#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021227 break;
21228 default:
21229 break;
21230 }
21231 }
21232 if (pctxt->nberrors != 0)
21233 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021234
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021235 /*
21236 * Finally we can build the automaton from the content model of
21237 * complex types.
21238 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021239
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021240 for (i = 0; i < nbItems; i++) {
21241 item = items[i];
21242 switch (item->type) {
21243 case XML_SCHEMA_TYPE_COMPLEX:
21244 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021245 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021246 break;
21247 default:
21248 break;
21249 }
21250 }
21251 if (pctxt->nberrors != 0)
21252 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021253 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021254 * URGENT TODO: cos-element-consistent
Daniel Veillarddee23482008-04-11 12:58:43 +000021255 */
21256 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021257
Daniel Veillarddee23482008-04-11 12:58:43 +000021258exit_error:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021259 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021260 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021261
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021262exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021263 ret = -1;
21264
21265exit:
21266 /*
21267 * Reset the constructor. This is needed for XSI acquisition, since
21268 * those items will be processed over and over again for every XSI
21269 * if not cleared here.
21270 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021271 con->bucket = oldbucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000021272 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021273 if (con->substGroups != NULL) {
21274 xmlHashFree(con->substGroups,
21275 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21276 con->substGroups = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000021277 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021278 if (con->redefs != NULL) {
21279 xmlSchemaRedefListFree(con->redefs);
21280 con->redefs = NULL;
21281 }
21282 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021283}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021284/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021285 * xmlSchemaParse:
21286 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021287 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021288 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000021289 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000021290 *
21291 * Returns the internal XML Schema structure built from the resource or
21292 * NULL in case of error
21293 */
21294xmlSchemaPtr
21295xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21296{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021297 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021298 xmlSchemaBucketPtr bucket = NULL;
21299 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021300
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021301 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021302 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021303 * the API; i.e. not automatically by the validated instance document.
21304 */
21305
Daniel Veillard4255d502002-04-16 15:50:10 +000021306 xmlSchemaInitTypes();
21307
Daniel Veillard6045c902002-10-09 21:13:59 +000021308 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021309 return (NULL);
21310
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021311 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021312 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021313 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021314 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021315
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021316 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021317 mainSchema = xmlSchemaNewSchema(ctxt);
21318 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021319 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021320 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021321 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021322 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021323 if (ctxt->constructor == NULL) {
21324 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21325 if (ctxt->constructor == NULL)
21326 return(NULL);
21327 /* Take ownership of the constructor to be able to free it. */
21328 ctxt->ownsConstructor = 1;
21329 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021330 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021331 /*
21332 * Locate and add the schema document.
21333 */
21334 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21335 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21336 NULL, NULL, &bucket);
21337 if (res == -1)
21338 goto exit_failure;
21339 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021340 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021341
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021342 if (bucket == NULL) {
21343 /* TODO: Error code, actually we failed to *locate* the schema. */
Daniel Veillarddee23482008-04-11 12:58:43 +000021344 if (ctxt->URL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021345 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21346 NULL, NULL,
21347 "Failed to locate the main schema resource at '%s'",
21348 ctxt->URL, NULL);
21349 else
21350 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21351 NULL, NULL,
21352 "Failed to locate the main schema resource",
21353 NULL, NULL);
21354 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021355 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021356 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021357 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021358 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021359 if (ctxt->nberrors != 0)
21360 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021361
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021362 mainSchema->doc = bucket->doc;
21363 mainSchema->preserve = ctxt->preserve;
Daniel Veillarddee23482008-04-11 12:58:43 +000021364
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021365 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021366
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021367 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021368 goto exit_failure;
21369
21370 /*
21371 * TODO: This is not nice, since we cannot distinguish from the
21372 * result if there was an internal error or not.
21373 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021374exit:
21375 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021376 if (mainSchema) {
21377 xmlSchemaFree(mainSchema);
21378 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021379 }
21380 if (ctxt->constructor) {
21381 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21382 ctxt->constructor = NULL;
21383 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021384 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021385 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021386 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021387 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021388exit_failure:
Daniel Veillarddee23482008-04-11 12:58:43 +000021389 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021390 * Quite verbose, but should catch internal errors, which were
21391 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021392 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021393 if (mainSchema) {
21394 xmlSchemaFree(mainSchema);
21395 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021396 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021397 if (ctxt->constructor) {
21398 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21399 ctxt->constructor = NULL;
21400 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021401 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021402 PERROR_INT2("xmlSchemaParse",
Daniel Veillarddee23482008-04-11 12:58:43 +000021403 "An internal error occured");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021404 ctxt->schema = NULL;
21405 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021406}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021407
Daniel Veillard4255d502002-04-16 15:50:10 +000021408/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021409 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021410 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021411 * @err: the error callback
21412 * @warn: the warning callback
21413 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021414 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021415 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021416 */
21417void
21418xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021419 xmlSchemaValidityErrorFunc err,
21420 xmlSchemaValidityWarningFunc warn, void *ctx)
21421{
Daniel Veillard4255d502002-04-16 15:50:10 +000021422 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021423 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021424 ctxt->error = err;
21425 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021426 ctxt->errCtxt = ctx;
21427 if (ctxt->vctxt != NULL)
21428 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21429}
21430
21431/**
21432 * xmlSchemaSetParserStructuredErrors:
21433 * @ctxt: a schema parser context
21434 * @serror: the structured error function
21435 * @ctx: the functions context
21436 *
21437 * Set the structured error callback
21438 */
21439void
21440xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21441 xmlStructuredErrorFunc serror,
21442 void *ctx)
21443{
21444 if (ctxt == NULL)
21445 return;
21446 ctxt->serror = serror;
21447 ctxt->errCtxt = ctx;
21448 if (ctxt->vctxt != NULL)
21449 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021450}
21451
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021452/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021453 * xmlSchemaGetParserErrors:
21454 * @ctxt: a XMl-Schema parser context
21455 * @err: the error callback result
21456 * @warn: the warning callback result
21457 * @ctx: contextual data for the callbacks result
21458 *
21459 * Get the callback information used to handle errors for a parser context
21460 *
21461 * Returns -1 in case of failure, 0 otherwise
21462 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021463int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021464xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021465 xmlSchemaValidityErrorFunc * err,
21466 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021467{
21468 if (ctxt == NULL)
21469 return(-1);
21470 if (err != NULL)
21471 *err = ctxt->error;
21472 if (warn != NULL)
21473 *warn = ctxt->warning;
21474 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021475 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021476 return(0);
21477}
21478
21479/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021480 * xmlSchemaFacetTypeToString:
21481 * @type: the facet type
21482 *
21483 * Convert the xmlSchemaTypeType to a char string.
21484 *
21485 * Returns the char string representation of the facet type if the
21486 * type is a facet and an "Internal Error" string otherwise.
21487 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021488static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021489xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21490{
21491 switch (type) {
21492 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021493 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021494 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021495 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021496 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021497 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021498 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021499 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021500 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021501 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021502 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021503 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021504 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021505 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021506 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021507 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021508 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021509 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021510 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021511 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021512 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021513 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021514 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021515 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021516 default:
21517 break;
21518 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021519 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021520}
21521
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021522static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021523xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21524{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021525 /*
21526 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021527 * from xsd:string.
21528 */
21529 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021530 /*
21531 * Note that we assume a whitespace of preserve for anySimpleType.
21532 */
21533 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21534 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21535 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021536 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021537 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021538 else {
21539 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010021540 * For all `atomic` datatypes other than string (and types `derived`
21541 * by `restriction` from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021542 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021543 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021544 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021545 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021546 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021547 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021548 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021549 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021550 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021551 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021552 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021553 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021554 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021555 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21556 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21557 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21558 return (XML_SCHEMA_WHITESPACE_REPLACE);
21559 else
21560 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021562 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021563}
21564
Daniel Veillard4255d502002-04-16 15:50:10 +000021565/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021566 * *
21567 * Simple type validation *
21568 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021569 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021570
Daniel Veillard4255d502002-04-16 15:50:10 +000021571
21572/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021573 * *
21574 * DOM Validation code *
21575 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021576 ************************************************************************/
21577
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021578/**
21579 * xmlSchemaAssembleByLocation:
21580 * @pctxt: a schema parser context
21581 * @vctxt: a schema validation context
21582 * @schema: the existing schema
21583 * @node: the node that fired the assembling
21584 * @nsName: the namespace name of the new schema
21585 * @location: the location of the schema
21586 *
21587 * Expands an existing schema by an additional schema.
21588 *
21589 * Returns 0 if the new schema is correct, a positive error code
21590 * number otherwise and -1 in case of an internal or API error.
21591 */
21592static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021593xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021594 xmlSchemaPtr schema,
21595 xmlNodePtr node,
21596 const xmlChar *nsName,
21597 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021598{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021599 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021600 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021601 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021602
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021603 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021604 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021605
21606 if (vctxt->pctxt == NULL) {
21607 VERROR_INT("xmlSchemaAssembleByLocation",
21608 "no parser context available");
21609 return(-1);
21610 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021611 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021612 if (pctxt->constructor == NULL) {
21613 PERROR_INT("xmlSchemaAssembleByLocation",
21614 "no constructor");
21615 return(-1);
21616 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021617 /*
21618 * Acquire the schema document.
21619 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021620 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21621 location, node);
21622 /*
21623 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21624 * the process will automatically change this to
21625 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21626 */
21627 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Daniel Veillarddee23482008-04-11 12:58:43 +000021628 location, NULL, NULL, 0, node, NULL, nsName,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021629 &bucket);
21630 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021631 return(ret);
21632 if (bucket == NULL) {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021633 /*
21634 * Generate a warning that the document could not be located.
21635 */
21636 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21637 node, NULL,
21638 "The document at location '%s' could not be acquired",
21639 location, NULL, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021640 return(ret);
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021641 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021642 /*
21643 * The first located schema will be handled as if all other
21644 * schemas imported by XSI were imported by this first schema.
21645 */
21646 if ((bucket != NULL) &&
21647 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21648 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21649 /*
21650 * TODO: Is this handled like an import? I.e. is it not an error
21651 * if the schema cannot be located?
21652 */
21653 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21654 return(0);
21655 /*
21656 * We will reuse the parser context for every schema imported
21657 * directly via XSI. So reset the context.
21658 */
21659 pctxt->nberrors = 0;
21660 pctxt->err = 0;
21661 pctxt->doc = bucket->doc;
Daniel Veillarddee23482008-04-11 12:58:43 +000021662
21663 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021664 if (ret == -1) {
21665 pctxt->doc = NULL;
21666 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021667 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021668 /* Paranoid error channelling. */
21669 if ((ret == 0) && (pctxt->nberrors != 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000021670 ret = pctxt->err;
21671 if (pctxt->nberrors == 0) {
21672 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021673 * Only bother to fixup pending components, if there was
21674 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021675 * For every XSI acquired schema (and its sub-schemata) we will
21676 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021677 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021678 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021679 ret = pctxt->err;
21680 /*
21681 * Not nice, but we need somehow to channel the schema parser
21682 * error to the validation context.
21683 */
21684 if ((ret != 0) && (vctxt->err == 0))
21685 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021686 vctxt->nberrors += pctxt->nberrors;
21687 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000021688 /* Add to validation error sum. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021689 vctxt->nberrors += pctxt->nberrors;
21690 }
21691 pctxt->doc = NULL;
21692 return(ret);
21693exit_failure:
21694 pctxt->doc = NULL;
21695 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021696}
21697
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021698static xmlSchemaAttrInfoPtr
Daniel Veillarddee23482008-04-11 12:58:43 +000021699xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021700 int metaType)
21701{
21702 if (vctxt->nbAttrInfos == 0)
21703 return (NULL);
21704 {
21705 int i;
21706 xmlSchemaAttrInfoPtr iattr;
21707
21708 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21709 iattr = vctxt->attrInfos[i];
21710 if (iattr->metaType == metaType)
21711 return (iattr);
21712 }
21713
21714 }
21715 return (NULL);
21716}
21717
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021718/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021719 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021720 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021721 *
21722 * Expands an existing schema by an additional schema using
21723 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21724 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21725 * must be set to 1.
21726 *
21727 * Returns 0 if the new schema is correct, a positive error code
21728 * number otherwise and -1 in case of an internal or API error.
21729 */
21730static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021731xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021732{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021733 const xmlChar *cur, *end;
21734 const xmlChar *nsname = NULL, *location;
21735 int count = 0;
21736 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021737 xmlSchemaAttrInfoPtr iattr;
21738
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021739 /*
21740 * Parse the value; we will assume an even number of values
21741 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021742 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021743 * URGENT TODO: !! This needs to work for both
21744 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21745 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021746 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021747 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21748 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21749 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021750 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021751 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21752 if (iattr == NULL)
21753 return (0);
21754 cur = iattr->value;
21755 do {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021756 /*
21757 * TODO: Move the string parsing mechanism away from here.
21758 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021759 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021760 /*
21761 * Get the namespace name.
21762 */
21763 while (IS_BLANK_CH(*cur))
21764 cur++;
21765 end = cur;
21766 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21767 end++;
21768 if (end == cur)
21769 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021770 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021771 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021772 cur = end;
21773 }
21774 /*
21775 * Get the URI.
21776 */
21777 while (IS_BLANK_CH(*cur))
21778 cur++;
21779 end = cur;
21780 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21781 end++;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021782 if (end == cur) {
21783 if (iattr->metaType ==
21784 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21785 {
21786 /*
21787 * If using @schemaLocation then tuples are expected.
21788 * I.e. the namespace name *and* the document's URI.
Daniel Veillarddee23482008-04-11 12:58:43 +000021789 */
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021790 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21791 iattr->node, NULL,
21792 "The value must consist of tuples: the target namespace "
21793 "name and the document's URI", NULL, NULL, NULL);
21794 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021795 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021796 }
21797 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021798 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021799 cur = end;
21800 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21801 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021802 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021803 VERROR_INT("xmlSchemaAssembleByXSI",
21804 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021805 return (-1);
21806 }
21807 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021808 return (ret);
21809}
21810
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021811static const xmlChar *
21812xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21813 const xmlChar *prefix)
21814{
21815 if (vctxt->sax != NULL) {
21816 int i, j;
21817 xmlSchemaNodeInfoPtr inode;
Daniel Veillarddee23482008-04-11 12:58:43 +000021818
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021819 for (i = vctxt->depth; i >= 0; i--) {
21820 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21821 inode = vctxt->elemInfos[i];
21822 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21823 if (((prefix == NULL) &&
21824 (inode->nsBindings[j] == NULL)) ||
21825 ((prefix != NULL) && xmlStrEqual(prefix,
21826 inode->nsBindings[j]))) {
21827
21828 /*
21829 * Note that the namespace bindings are already
21830 * in a string dict.
21831 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021832 return (inode->nsBindings[j+1]);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021833 }
21834 }
21835 }
21836 }
21837 return (NULL);
Daniel Veillard438ebbd2008-05-12 12:58:46 +000021838#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021839 } else if (vctxt->reader != NULL) {
21840 xmlChar *nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +000021841
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021842 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21843 if (nsName != NULL) {
21844 const xmlChar *ret;
21845
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021846 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21847 xmlFree(nsName);
21848 return (ret);
21849 } else
21850 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021851#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021852 } else {
21853 xmlNsPtr ns;
21854
21855 if ((vctxt->inode->node == NULL) ||
21856 (vctxt->inode->node->doc == NULL)) {
21857 VERROR_INT("xmlSchemaLookupNamespace",
21858 "no node or node's doc avaliable");
21859 return (NULL);
21860 }
21861 ns = xmlSearchNs(vctxt->inode->node->doc,
21862 vctxt->inode->node, prefix);
21863 if (ns != NULL)
21864 return (ns->href);
21865 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021866 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021867}
21868
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021869/*
21870* This one works on the schema of the validation context.
21871*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021872static int
Daniel Veillarddee23482008-04-11 12:58:43 +000021873xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021874 xmlSchemaPtr schema,
21875 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021876 const xmlChar *value,
21877 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021878 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021879{
21880 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021881
21882 if (vctxt && (vctxt->schema == NULL)) {
21883 VERROR_INT("xmlSchemaValidateNotation",
21884 "a schema is needed on the validation context");
21885 return (-1);
21886 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021887 ret = xmlValidateQName(value, 1);
21888 if (ret != 0)
21889 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021890 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021891 xmlChar *localName = NULL;
21892 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021893
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021894 localName = xmlSplitQName2(value, &prefix);
21895 if (prefix != NULL) {
21896 const xmlChar *nsName = NULL;
21897
Daniel Veillarddee23482008-04-11 12:58:43 +000021898 if (vctxt != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021899 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21900 else if (node != NULL) {
21901 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21902 if (ns != NULL)
21903 nsName = ns->href;
21904 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021905 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021906 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021907 return (1);
21908 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021909 if (nsName == NULL) {
21910 xmlFree(prefix);
21911 xmlFree(localName);
21912 return (1);
21913 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021914 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Daniel Veillard77fbc3e2008-03-24 14:06:19 +000021915 if ((valNeeded) && (val != NULL)) {
21916 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21917 xmlStrdup(nsName));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021918 if (*val == NULL)
21919 ret = -1;
21920 }
21921 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021922 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021923 xmlFree(prefix);
21924 xmlFree(localName);
21925 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021926 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021927 if (valNeeded && (val != NULL)) {
21928 (*val) = xmlSchemaNewNOTATIONValue(
21929 BAD_CAST xmlStrdup(value), NULL);
21930 if (*val == NULL)
21931 ret = -1;
21932 }
21933 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021934 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021935 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021936 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021937 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021938}
21939
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021940static int
21941xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21942 const xmlChar* lname,
21943 const xmlChar* nsname)
21944{
21945 int i;
21946
21947 lname = xmlDictLookup(vctxt->dict, lname, -1);
21948 if (lname == NULL)
21949 return(-1);
21950 if (nsname != NULL) {
21951 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21952 if (nsname == NULL)
21953 return(-1);
21954 }
21955 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21956 if ((vctxt->nodeQNames->items [i] == lname) &&
21957 (vctxt->nodeQNames->items[i +1] == nsname))
21958 /* Already there */
21959 return(i);
21960 }
21961 /* Add new entry. */
21962 i = vctxt->nodeQNames->nbItems;
21963 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21964 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21965 return(i);
21966}
21967
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021968/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021969 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021970 * Validation of identity-constraints (IDC) *
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021971 * *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021972 ************************************************************************/
21973
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021974/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021975 * xmlSchemaAugmentIDC:
21976 * @idcDef: the IDC definition
21977 *
21978 * Creates an augmented IDC definition item.
21979 *
21980 * Returns the item, or NULL on internal errors.
21981 */
21982static void
21983xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21984 xmlSchemaValidCtxtPtr vctxt)
21985{
21986 xmlSchemaIDCAugPtr aidc;
21987
21988 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21989 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021990 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021991 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21992 NULL);
21993 return;
21994 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021995 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021996 aidc->def = idcDef;
21997 aidc->next = NULL;
21998 if (vctxt->aidcs == NULL)
21999 vctxt->aidcs = aidc;
22000 else {
22001 aidc->next = vctxt->aidcs;
22002 vctxt->aidcs = aidc;
22003 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022004 /*
22005 * Save if we have keyrefs at all.
22006 */
22007 if ((vctxt->hasKeyrefs == 0) &&
22008 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22009 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022010}
22011
22012/**
Daniel Veillard3888f472007-08-23 09:29:03 +000022013 * xmlSchemaAugmentImportedIDC:
22014 * @imported: the imported schema
22015 *
22016 * Creates an augmented IDC definition for the imported schema.
22017 */
22018static void
22019xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22020 if (imported->schema->idcDef != NULL) {
22021 xmlHashScan(imported->schema->idcDef ,
22022 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22023 }
22024}
22025
22026/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022027 * xmlSchemaIDCNewBinding:
22028 * @idcDef: the IDC definition of this binding
22029 *
22030 * Creates a new IDC binding.
22031 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022032 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022033 */
22034static xmlSchemaPSVIIDCBindingPtr
22035xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22036{
22037 xmlSchemaPSVIIDCBindingPtr ret;
22038
22039 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22040 sizeof(xmlSchemaPSVIIDCBinding));
22041 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022042 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022043 "allocating a PSVI IDC binding item", NULL);
22044 return (NULL);
22045 }
22046 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22047 ret->definition = idcDef;
22048 return (ret);
22049}
22050
22051/**
22052 * xmlSchemaIDCStoreNodeTableItem:
22053 * @vctxt: the WXS validation context
22054 * @item: the IDC node table item
22055 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022056 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022057 * They are stored to avoid copying them if IDC node-tables are merged
22058 * with corresponding parent IDC node-tables (bubbling).
22059 *
22060 * Returns 0 if succeeded, -1 on internal errors.
22061 */
22062static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022063xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022064 xmlSchemaPSVIIDCNodePtr item)
22065{
22066 /*
22067 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022068 */
22069 if (vctxt->idcNodes == NULL) {
22070 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022071 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22072 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022073 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022074 "allocating the IDC node table item list", NULL);
22075 return (-1);
22076 }
22077 vctxt->sizeIdcNodes = 20;
22078 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22079 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022080 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22081 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022082 sizeof(xmlSchemaPSVIIDCNodePtr));
22083 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022084 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022085 "re-allocating the IDC node table item list", NULL);
22086 return (-1);
22087 }
22088 }
22089 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022090
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022091 return (0);
22092}
22093
22094/**
22095 * xmlSchemaIDCStoreKey:
22096 * @vctxt: the WXS validation context
22097 * @item: the IDC key
22098 *
22099 * The validation context is used to store an IDC key.
22100 *
22101 * Returns 0 if succeeded, -1 on internal errors.
22102 */
22103static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022104xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022105 xmlSchemaPSVIIDCKeyPtr key)
22106{
22107 /*
22108 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022109 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022110 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022111 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022112 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22113 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022114 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022115 "allocating the IDC key storage list", NULL);
22116 return (-1);
22117 }
22118 vctxt->sizeIdcKeys = 40;
22119 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22120 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022121 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22122 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022123 sizeof(xmlSchemaPSVIIDCKeyPtr));
22124 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022125 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022126 "re-allocating the IDC key storage list", NULL);
22127 return (-1);
22128 }
22129 }
22130 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022131
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022132 return (0);
22133}
22134
22135/**
22136 * xmlSchemaIDCAppendNodeTableItem:
22137 * @bind: the IDC binding
22138 * @ntItem: the node-table item
22139 *
22140 * Appends the IDC node-table item to the binding.
22141 *
22142 * Returns 0 on success and -1 on internal errors.
22143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022144static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022145xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22146 xmlSchemaPSVIIDCNodePtr ntItem)
22147{
22148 if (bind->nodeTable == NULL) {
22149 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022150 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022151 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22152 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022153 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022154 "allocating an array of IDC node-table items", NULL);
22155 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022156 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022157 } else if (bind->sizeNodes <= bind->nbNodes) {
22158 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022159 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22160 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022161 sizeof(xmlSchemaPSVIIDCNodePtr));
22162 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022163 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022164 "re-allocating an array of IDC node-table items", NULL);
22165 return(-1);
22166 }
22167 }
22168 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022169 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022170}
22171
22172/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022173 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022174 * @vctxt: the WXS validation context
22175 * @matcher: the IDC matcher
22176 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022177 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022178 * of the given matcher. If none found, a new one is created
22179 * and added to the IDC table.
22180 *
22181 * Returns an IDC binding or NULL on internal errors.
22182 */
22183static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022184xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022185 xmlSchemaIDCMatcherPtr matcher)
22186{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022187 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022188
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022189 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022190
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022191 if (ielem->idcTable == NULL) {
22192 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22193 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022194 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022195 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022196 } else {
22197 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022198
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022199 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022200 do {
22201 if (bind->definition == matcher->aidc->def)
22202 return(bind);
22203 if (bind->next == NULL) {
22204 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22205 if (bind->next == NULL)
22206 return (NULL);
22207 return(bind->next);
22208 }
22209 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022210 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022211 }
22212 return (NULL);
22213}
22214
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022215static xmlSchemaItemListPtr
22216xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22217 xmlSchemaIDCMatcherPtr matcher)
22218{
22219 if (matcher->targets == NULL)
22220 matcher->targets = xmlSchemaItemListCreate();
22221 return(matcher->targets);
22222}
22223
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022224/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022225 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022226 * @key: the IDC key
22227 *
22228 * Frees an IDC key together with its compiled value.
22229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022230static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022231xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022233 if (key->val != NULL)
22234 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022235 xmlFree(key);
22236}
22237
22238/**
22239 * xmlSchemaIDCFreeBinding:
22240 *
22241 * Frees an IDC binding. Note that the node table-items
22242 * are not freed.
22243 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022244static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022245xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22246{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022247 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022248 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022249 if (bind->dupls != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000022250 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022251 xmlFree(bind);
22252}
22253
22254/**
22255 * xmlSchemaIDCFreeIDCTable:
22256 * @bind: the first IDC binding in the list
22257 *
22258 * Frees an IDC table, i.e. all the IDC bindings in the list.
22259 */
22260static void
22261xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22262{
22263 xmlSchemaPSVIIDCBindingPtr prev;
22264
22265 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022266 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022267 bind = bind->next;
22268 xmlSchemaIDCFreeBinding(prev);
22269 }
22270}
22271
22272/**
22273 * xmlSchemaIDCFreeMatcherList:
22274 * @matcher: the first IDC matcher in the list
22275 *
22276 * Frees a list of IDC matchers.
22277 */
22278static void
22279xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22280{
22281 xmlSchemaIDCMatcherPtr next;
22282
22283 while (matcher != NULL) {
22284 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022285 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022286 int i;
22287 for (i = 0; i < matcher->sizeKeySeqs; i++)
22288 if (matcher->keySeqs[i] != NULL)
22289 xmlFree(matcher->keySeqs[i]);
Daniel Veillarddee23482008-04-11 12:58:43 +000022290 xmlFree(matcher->keySeqs);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022291 }
22292 if (matcher->targets != NULL) {
22293 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22294 int i;
22295 xmlSchemaPSVIIDCNodePtr idcNode;
22296 /*
22297 * Node-table items for keyrefs are not stored globally
22298 * to the validation context, since they are not bubbled.
22299 * We need to free them here.
22300 */
22301 for (i = 0; i < matcher->targets->nbItems; i++) {
22302 idcNode =
22303 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22304 xmlFree(idcNode->keys);
22305 xmlFree(idcNode);
22306 }
22307 }
22308 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022309 }
22310 xmlFree(matcher);
22311 matcher = next;
22312 }
22313}
22314
22315/**
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022316 * xmlSchemaIDCReleaseMatcherList:
22317 * @vctxt: the WXS validation context
22318 * @matcher: the first IDC matcher in the list
22319 *
22320 * Caches a list of IDC matchers for reuse.
22321 */
22322static void
22323xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22324 xmlSchemaIDCMatcherPtr matcher)
22325{
22326 xmlSchemaIDCMatcherPtr next;
22327
22328 while (matcher != NULL) {
22329 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022330 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022331 int i;
22332 /*
22333 * Don't free the array, but only the content.
22334 */
22335 for (i = 0; i < matcher->sizeKeySeqs; i++)
22336 if (matcher->keySeqs[i] != NULL) {
22337 xmlFree(matcher->keySeqs[i]);
22338 matcher->keySeqs[i] = NULL;
22339 }
22340 }
22341 if (matcher->targets) {
22342 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22343 int i;
22344 xmlSchemaPSVIIDCNodePtr idcNode;
22345 /*
22346 * Node-table items for keyrefs are not stored globally
22347 * to the validation context, since they are not bubbled.
22348 * We need to free them here.
22349 */
22350 for (i = 0; i < matcher->targets->nbItems; i++) {
22351 idcNode =
22352 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22353 xmlFree(idcNode->keys);
22354 xmlFree(idcNode);
22355 }
22356 }
22357 xmlSchemaItemListFree(matcher->targets);
22358 matcher->targets = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022359 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022360 matcher->next = NULL;
22361 /*
22362 * Cache the matcher.
22363 */
22364 if (vctxt->idcMatcherCache != NULL)
22365 matcher->nextCached = vctxt->idcMatcherCache;
22366 vctxt->idcMatcherCache = matcher;
22367
22368 matcher = next;
22369 }
22370}
22371
22372/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022373 * xmlSchemaIDCAddStateObject:
22374 * @vctxt: the WXS validation context
22375 * @matcher: the IDC matcher
22376 * @sel: the XPath information
22377 * @parent: the parent "selector" state object if any
22378 * @type: "selector" or "field"
22379 *
22380 * Creates/reuses and activates state objects for the given
22381 * XPath information; if the XPath expression consists of unions,
22382 * multiple state objects are created for every unioned expression.
22383 *
22384 * Returns 0 on success and -1 on internal errors.
22385 */
22386static int
22387xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22388 xmlSchemaIDCMatcherPtr matcher,
22389 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022390 int type)
22391{
22392 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022393
22394 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022395 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022396 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022397 if (vctxt->xpathStatePool != NULL) {
22398 sto = vctxt->xpathStatePool;
22399 vctxt->xpathStatePool = sto->next;
22400 sto->next = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022401 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022402 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022403 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022404 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022405 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22406 if (sto == NULL) {
22407 xmlSchemaVErrMemory(NULL,
22408 "allocating an IDC state object", NULL);
22409 return (-1);
22410 }
22411 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
Daniel Veillarddee23482008-04-11 12:58:43 +000022412 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022413 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000022414 * Add to global list.
22415 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022416 if (vctxt->xpathStates != NULL)
22417 sto->next = vctxt->xpathStates;
22418 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022419
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022420 /*
22421 * Free the old xpath validation context.
22422 */
22423 if (sto->xpathCtxt != NULL)
22424 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22425
22426 /*
22427 * Create a new XPath (pattern) validation context.
22428 */
22429 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22430 (xmlPatternPtr) sel->xpathComp);
22431 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022432 VERROR_INT("xmlSchemaIDCAddStateObject",
22433 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022434 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000022435 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022436 sto->type = type;
22437 sto->depth = vctxt->depth;
22438 sto->matcher = matcher;
22439 sto->sel = sel;
22440 sto->nbHistory = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000022441
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022442#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022443 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22444 sto->sel->xpath);
22445#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022446 return (0);
22447}
22448
22449/**
22450 * xmlSchemaXPathEvaluate:
22451 * @vctxt: the WXS validation context
22452 * @nodeType: the nodeType of the current node
22453 *
22454 * Evaluates all active XPath state objects.
22455 *
22456 * Returns the number of IC "field" state objects which resolved to
22457 * this node, 0 if none resolved and -1 on internal errors.
22458 */
22459static int
22460xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022461 xmlElementType nodeType)
22462{
22463 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022464 int res, resolved = 0, depth = vctxt->depth;
Daniel Veillarddee23482008-04-11 12:58:43 +000022465
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022466 if (vctxt->xpathStates == NULL)
22467 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022468
22469 if (nodeType == XML_ATTRIBUTE_NODE)
22470 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022471#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022472 {
22473 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022474 xmlGenericError(xmlGenericErrorContext,
22475 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022476 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22477 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022478 FREE_AND_NULL(str)
22479 }
22480#endif
22481 /*
22482 * Process all active XPath state objects.
22483 */
22484 first = vctxt->xpathStates;
22485 sto = first;
22486 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022487#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022488 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Daniel Veillarddee23482008-04-11 12:58:43 +000022489 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022490 sto->matcher->aidc->def->name, sto->sel->xpath);
22491 else
Daniel Veillarddee23482008-04-11 12:58:43 +000022492 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022493 sto->matcher->aidc->def->name, sto->sel->xpath);
22494#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022495 if (nodeType == XML_ELEMENT_NODE)
22496 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022497 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022498 else
22499 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022500 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022501
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022502 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022503 VERROR_INT("xmlSchemaXPathEvaluate",
22504 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022505 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022506 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022507 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022508 goto next_sto;
22509 /*
22510 * Full match.
22511 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022512#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022513 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022514 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022515#endif
22516 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022517 * Register a match in the state object history.
22518 */
22519 if (sto->history == NULL) {
22520 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22521 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022522 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022523 "allocating the state object history", NULL);
22524 return(-1);
22525 }
Daniel Veillard6f9b0872006-08-12 14:09:01 +000022526 sto->sizeHistory = 5;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022527 } else if (sto->sizeHistory <= sto->nbHistory) {
22528 sto->sizeHistory *= 2;
22529 sto->history = (int *) xmlRealloc(sto->history,
22530 sto->sizeHistory * sizeof(int));
22531 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022532 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022533 "re-allocating the state object history", NULL);
22534 return(-1);
22535 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022536 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022537 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022538
22539#ifdef DEBUG_IDC
22540 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22541 vctxt->depth);
22542#endif
22543
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022544 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22545 xmlSchemaIDCSelectPtr sel;
22546 /*
22547 * Activate state objects for the IDC fields of
22548 * the IDC selector.
22549 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022550#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022551 xmlGenericError(xmlGenericErrorContext, "IDC: "
22552 "activating field states\n");
22553#endif
22554 sel = sto->matcher->aidc->def->fields;
22555 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022556 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22557 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22558 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022559 sel = sel->next;
22560 }
22561 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22562 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022563 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022564 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022565#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022566 xmlGenericError(xmlGenericErrorContext,
22567 "IDC: key found\n");
22568#endif
22569 /*
22570 * Notify that the character value of this node is
22571 * needed.
22572 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022573 if (resolved == 0) {
22574 if ((vctxt->inode->flags &
22575 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22576 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22577 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022578 resolved++;
22579 }
22580next_sto:
22581 if (sto->next == NULL) {
22582 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022583 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022584 */
22585 head = first;
22586 sto = vctxt->xpathStates;
22587 } else
22588 sto = sto->next;
22589 }
22590 return (resolved);
22591}
22592
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022593static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022594xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022595 xmlChar **buf,
22596 xmlSchemaPSVIIDCKeyPtr *seq,
22597 int count)
22598{
22599 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022600 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022601
22602 *buf = xmlStrdup(BAD_CAST "[");
22603 for (i = 0; i < count; i++) {
22604 *buf = xmlStrcat(*buf, BAD_CAST "'");
Daniel Veillarddee23482008-04-11 12:58:43 +000022605 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022606 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22607 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022608 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022609 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022610 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022611 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22612 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022613 *buf = xmlStrcat(*buf, BAD_CAST "???");
22614 }
22615 if (i < count -1)
22616 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22617 else
22618 *buf = xmlStrcat(*buf, BAD_CAST "'");
22619 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022620 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022621 value = NULL;
22622 }
22623 }
22624 *buf = xmlStrcat(*buf, BAD_CAST "]");
22625
22626 return (BAD_CAST *buf);
22627}
22628
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022629/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022630 * xmlSchemaXPathPop:
22631 * @vctxt: the WXS validation context
22632 *
22633 * Pops all XPath states.
22634 *
22635 * Returns 0 on success and -1 on internal errors.
22636 */
22637static int
22638xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22639{
22640 xmlSchemaIDCStateObjPtr sto;
22641 int res;
22642
22643 if (vctxt->xpathStates == NULL)
22644 return(0);
22645 sto = vctxt->xpathStates;
22646 do {
22647 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22648 if (res == -1)
22649 return (-1);
22650 sto = sto->next;
22651 } while (sto != NULL);
22652 return(0);
22653}
22654
22655/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022656 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022657 * @vctxt: the WXS validation context
22658 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022659 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022660 *
22661 * Processes and pops the history items of the IDC state objects.
22662 * IDC key-sequences are validated/created on IDC bindings.
Daniel Veillarddee23482008-04-11 12:58:43 +000022663 *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022664 * Returns 0 on success and -1 on internal errors.
22665 */
22666static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022667xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022668 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022669{
22670 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022671 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022672 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022673 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022674
22675 if (vctxt->xpathStates == NULL)
22676 return (0);
22677 sto = vctxt->xpathStates;
22678
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022679#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022680 {
22681 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022682 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022683 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022684 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22685 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022686 FREE_AND_NULL(str)
22687 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022688#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022689 /*
22690 * Evaluate the state objects.
22691 */
22692 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022693 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22694 if (res == -1) {
22695 VERROR_INT("xmlSchemaXPathProcessHistory",
22696 "calling xmlStreamPop()");
22697 return (-1);
22698 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022699#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022700 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22701 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022702#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022703 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022704 goto deregister_check;
22705
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022706 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022707
22708 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022709 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022710 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022711 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022712 sto = sto->next;
22713 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000022714 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022715 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022716 /*
22717 * NOTE: According to
22718 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22719 * ... the simple-content of complex types is also allowed.
22720 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022721
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022722 if (WXS_IS_COMPLEX(type)) {
22723 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22724 /*
22725 * Sanity check for complex types with simple content.
22726 */
22727 simpleType = type->contentTypeDef;
22728 if (simpleType == NULL) {
22729 VERROR_INT("xmlSchemaXPathProcessHistory",
22730 "field resolves to a CT with simple content "
22731 "but the CT is missing the ST definition");
22732 return (-1);
22733 }
22734 } else
22735 simpleType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022736 } else
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022737 simpleType = type;
22738 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022739 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022740
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022741 /*
22742 * Not qualified if the field resolves to a node of non
22743 * simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000022744 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022745 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +000022746 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022747 WXS_BASIC_CAST sto->matcher->aidc->def,
22748 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022749 "non-simple type",
22750 sto->sel->xpath,
22751 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22752 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022753 sto->nbHistory--;
22754 goto deregister_check;
22755 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022756
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022757 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022758 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022759 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022760 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022761 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022762 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022763 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022764 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022765 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022766 sto->nbHistory--;
22767 goto deregister_check;
22768 } else {
22769 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22770 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022771 int pos, idx;
Daniel Veillarddee23482008-04-11 12:58:43 +000022772
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022773 /*
22774 * The key will be anchored on the matcher's list of
22775 * key-sequences. The position in this list is determined
22776 * by the target node's depth relative to the matcher's
22777 * depth of creation (i.e. the depth of the scope element).
Daniel Veillarddee23482008-04-11 12:58:43 +000022778 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022779 * Element Depth Pos List-entries
22780 * <scope> 0 NULL
22781 * <bar> 1 NULL
22782 * <target/> 2 2 target
22783 * <bar>
22784 * </scope>
22785 *
22786 * The size of the list is only dependant on the depth of
22787 * the tree.
22788 * An entry will be NULLed in selector_leave, i.e. when
Daniel Veillarddee23482008-04-11 12:58:43 +000022789 * we hit the target's
22790 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022791 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022792 idx = sto->sel->index;
Daniel Veillarddee23482008-04-11 12:58:43 +000022793
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022794 /*
22795 * Create/grow the array of key-sequences.
22796 */
22797 if (matcher->keySeqs == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022798 if (pos > 9)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022799 matcher->sizeKeySeqs = pos * 2;
22800 else
22801 matcher->sizeKeySeqs = 10;
Daniel Veillarddee23482008-04-11 12:58:43 +000022802 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022803 xmlMalloc(matcher->sizeKeySeqs *
Daniel Veillarddee23482008-04-11 12:58:43 +000022804 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22805 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022806 xmlSchemaVErrMemory(NULL,
22807 "allocating an array of key-sequences",
22808 NULL);
22809 return(-1);
22810 }
22811 memset(matcher->keySeqs, 0,
22812 matcher->sizeKeySeqs *
22813 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Daniel Veillarddee23482008-04-11 12:58:43 +000022814 } else if (pos >= matcher->sizeKeySeqs) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022815 int i = matcher->sizeKeySeqs;
Daniel Veillarddee23482008-04-11 12:58:43 +000022816
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022817 matcher->sizeKeySeqs *= 2;
22818 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22819 xmlRealloc(matcher->keySeqs,
22820 matcher->sizeKeySeqs *
22821 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022822 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022823 xmlSchemaVErrMemory(NULL,
22824 "reallocating an array of key-sequences",
22825 NULL);
22826 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022827 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022828 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022829 * The array needs to be NULLed.
22830 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022831 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022832 for (; i < matcher->sizeKeySeqs; i++)
22833 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022834 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022835
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022836 /*
22837 * Get/create the key-sequence.
22838 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022839 keySeq = matcher->keySeqs[pos];
22840 if (keySeq == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022841 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022842 } else if (keySeq[idx] != NULL) {
22843 xmlChar *str = NULL;
22844 /*
22845 * cvc-identity-constraint:
Jan Pokorný761c9e92013-11-29 23:26:27 +010022846 * 3 For each node in the `target node set` all
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022847 * of the {fields}, with that node as the context
22848 * node, evaluate to either an empty node-set or
22849 * a node-set with exactly one member, which must
22850 * have a simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000022851 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022852 * The key was already set; report an error.
22853 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022854 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022855 XML_SCHEMAV_CVC_IDC, NULL,
22856 WXS_BASIC_CAST matcher->aidc->def,
22857 "The XPath '%s' of a field of %s evaluates to a "
22858 "node-set with more than one member",
22859 sto->sel->xpath,
22860 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22861 FREE_AND_NULL(str);
22862 sto->nbHistory--;
22863 goto deregister_check;
22864 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000022865 goto create_key;
22866
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022867create_sequence:
22868 /*
22869 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022870 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022871 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
Daniel Veillarddee23482008-04-11 12:58:43 +000022872 matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022873 sizeof(xmlSchemaPSVIIDCKeyPtr));
22874 if (keySeq == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022875 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022876 "allocating an IDC key-sequence", NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000022877 return(-1);
22878 }
22879 memset(keySeq, 0, matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022880 sizeof(xmlSchemaPSVIIDCKeyPtr));
22881 matcher->keySeqs[pos] = keySeq;
22882create_key:
22883 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022884 * Create a key once per node only.
Daniel Veillarddee23482008-04-11 12:58:43 +000022885 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022886 if (key == NULL) {
22887 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22888 sizeof(xmlSchemaPSVIIDCKey));
22889 if (key == NULL) {
22890 xmlSchemaVErrMemory(NULL,
22891 "allocating a IDC key", NULL);
22892 xmlFree(keySeq);
22893 matcher->keySeqs[pos] = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022894 return(-1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022895 }
22896 /*
22897 * Consume the compiled value.
22898 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022899 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022900 key->val = vctxt->inode->val;
22901 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022902 /*
22903 * Store the key in a global list.
22904 */
22905 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22906 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022907 return (-1);
22908 }
22909 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022910 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022911 }
22912 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022913
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022914 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022915 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022916 xmlSchemaPSVIIDCNodePtr ntItem;
22917 xmlSchemaIDCMatcherPtr matcher;
22918 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022919 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022920 int pos, i, j, nbKeys;
22921 /*
22922 * Here we have the following scenario:
22923 * An IDC 'selector' state object resolved to a target node,
Daniel Veillarddee23482008-04-11 12:58:43 +000022924 * during the time this target node was in the
22925 * ancestor-or-self axis, the 'field' state object(s) looked
22926 * out for matching nodes to create a key-sequence for this
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022927 * target node. Now we are back to this target node and need
Daniel Veillarddee23482008-04-11 12:58:43 +000022928 * to put the key-sequence, together with the target node
22929 * itself, into the node-table of the corresponding IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022930 * binding.
22931 */
22932 matcher = sto->matcher;
22933 idc = matcher->aidc->def;
22934 nbKeys = idc->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000022935 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022936 /*
22937 * Check if the matcher has any key-sequences at all, plus
22938 * if it has a key-sequence for the current target node.
Daniel Veillarddee23482008-04-11 12:58:43 +000022939 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022940 if ((matcher->keySeqs == NULL) ||
22941 (matcher->sizeKeySeqs <= pos)) {
22942 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22943 goto selector_key_error;
22944 else
22945 goto selector_leave;
22946 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022947
22948 keySeq = &(matcher->keySeqs[pos]);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022949 if (*keySeq == NULL) {
22950 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22951 goto selector_key_error;
22952 else
22953 goto selector_leave;
22954 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022955
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022956 for (i = 0; i < nbKeys; i++) {
22957 if ((*keySeq)[i] == NULL) {
22958 /*
22959 * Not qualified, if not all fields did resolve.
22960 */
22961 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22962 /*
22963 * All fields of a "key" IDC must resolve.
22964 */
22965 goto selector_key_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000022966 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022967 goto selector_leave;
22968 }
22969 }
22970 /*
22971 * All fields did resolve.
22972 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022973
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022974 /*
22975 * 4.1 If the {identity-constraint category} is unique(/key),
Jan Pokorný761c9e92013-11-29 23:26:27 +010022976 * then no two members of the `qualified node set` have
22977 * `key-sequences` whose members are pairwise equal, as
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022978 * defined by Equal in [XML Schemas: Datatypes].
22979 *
22980 * Get the IDC binding from the matcher and check for
22981 * duplicate key-sequences.
22982 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022983#if 0
22984 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22985#endif
22986 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Daniel Veillarddee23482008-04-11 12:58:43 +000022987 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022988 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022989 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Daniel Veillarddee23482008-04-11 12:58:43 +000022990
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022991 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022992 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022993 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022994 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022995 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022996 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022997 bkeySeq =
22998 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022999 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023000 ckey = (*keySeq)[j];
Daniel Veillarddee23482008-04-11 12:58:43 +000023001 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023002 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023003 if (res == -1) {
23004 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023005 } else if (res == 0) {
23006 /*
23007 * One of the keys differs, so the key-sequence
23008 * won't be equal; get out.
23009 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023010 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023011 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023012 }
23013 if (res == 1) {
23014 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023015 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023016 */
23017 break;
23018 }
23019 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023020 } while (i < targets->nbItems);
23021 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023022 xmlChar *str = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023023 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023024 * TODO: Try to report the key-sequence.
23025 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023026 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023027 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023028 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023029 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023030 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023031 (*keySeq), nbKeys),
23032 xmlSchemaGetIDCDesignation(&strB, idc));
23033 FREE_AND_NULL(str);
23034 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023035 goto selector_leave;
23036 }
23037 }
23038 /*
23039 * Add a node-table item to the IDC binding.
23040 */
23041 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23042 sizeof(xmlSchemaPSVIIDCNode));
23043 if (ntItem == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023044 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023045 "allocating an IDC node-table item", NULL);
23046 xmlFree(*keySeq);
23047 *keySeq = NULL;
23048 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023049 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023050 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Daniel Veillarddee23482008-04-11 12:58:43 +000023051
23052 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023053 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023054 */
23055 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23056 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23057 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023058 xmlFree(*keySeq);
23059 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023060 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023061 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023062 ntItem->nodeQNameID = -1;
23063 } else {
23064 /*
23065 * Save a cached QName for this node on the IDC node, to be
23066 * able to report it, even if the node is not saved.
23067 */
23068 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23069 vctxt->inode->localName, vctxt->inode->nsName);
23070 if (ntItem->nodeQNameID == -1) {
23071 xmlFree(ntItem);
23072 xmlFree(*keySeq);
23073 *keySeq = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023074 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023075 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023076 }
23077 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023078 * Init the node-table item: Save the node, position and
23079 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023080 */
23081 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023082 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023083 ntItem->keys = *keySeq;
23084 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023085#if 0
Daniel Veillarddee23482008-04-11 12:58:43 +000023086 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023087#endif
23088 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023089 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023090 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023091 * Free the item, since keyref items won't be
23092 * put on a global list.
23093 */
23094 xmlFree(ntItem->keys);
23095 xmlFree(ntItem);
23096 }
23097 return (-1);
23098 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023099
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023100 goto selector_leave;
23101selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023102 {
23103 xmlChar *str = NULL;
23104 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010023105 * 4.2.1 (KEY) The `target node set` and the
23106 * `qualified node set` are equal, that is, every
23107 * member of the `target node set` is also a member
23108 * of the `qualified node set` and vice versa.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023109 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023110 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023111 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023112 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023113 "Not all fields of %s evaluate to a node",
23114 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23115 FREE_AND_NULL(str);
23116 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023117selector_leave:
23118 /*
23119 * Free the key-sequence if not added to the IDC table.
23120 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023121 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023122 xmlFree(*keySeq);
23123 *keySeq = NULL;
23124 }
23125 } /* if selector */
Daniel Veillarddee23482008-04-11 12:58:43 +000023126
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023127 sto->nbHistory--;
23128
23129deregister_check:
23130 /*
23131 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023132 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023133 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023134#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023135 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23136 sto->sel->xpath);
23137#endif
23138 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023139 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023140 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023141 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023142 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023143 nextsto = sto->next;
23144 /*
23145 * Unlink from the list of active XPath state objects.
23146 */
23147 vctxt->xpathStates = sto->next;
23148 sto->next = vctxt->xpathStatePool;
23149 /*
23150 * Link it to the pool of reusable state objects.
23151 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023152 vctxt->xpathStatePool = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023153 sto = nextsto;
23154 } else
23155 sto = sto->next;
23156 } /* while (sto != NULL) */
23157 return (0);
23158}
23159
23160/**
23161 * xmlSchemaIDCRegisterMatchers:
23162 * @vctxt: the WXS validation context
23163 * @elemDecl: the element declaration
23164 *
23165 * Creates helper objects to evaluate IDC selectors/fields
23166 * successively.
23167 *
23168 * Returns 0 if OK and -1 on internal errors.
23169 */
23170static int
23171xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23172 xmlSchemaElementPtr elemDecl)
23173{
23174 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23175 xmlSchemaIDCPtr idc, refIdc;
23176 xmlSchemaIDCAugPtr aidc;
Daniel Veillarddee23482008-04-11 12:58:43 +000023177
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023178 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23179 if (idc == NULL)
23180 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000023181
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023182#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023183 {
23184 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023185 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023186 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023187 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23188 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023189 FREE_AND_NULL(str)
23190 }
23191#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023192 if (vctxt->inode->idcMatchers != NULL) {
23193 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23194 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023195 return (-1);
23196 }
23197 do {
23198 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23199 /*
23200 * Since IDCs bubbles are expensive we need to know the
23201 * depth at which the bubbles should stop; this will be
23202 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023203 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023204 * be -1, indicating that no bubbles are needed.
23205 */
23206 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23207 if (refIdc != NULL) {
23208 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023209 * Remember that we have keyrefs on this node.
23210 */
23211 vctxt->inode->hasKeyrefs = 1;
23212 /*
23213 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023214 */
23215 aidc = vctxt->aidcs;
23216 while (aidc != NULL) {
23217 if (aidc->def == refIdc)
23218 break;
23219 aidc = aidc->next;
23220 }
23221 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023222 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023223 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023224 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023225 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023226 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023227 if ((aidc->keyrefDepth == -1) ||
23228 (vctxt->depth < aidc->keyrefDepth))
23229 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023230 }
23231 }
23232 /*
23233 * Lookup the augmented IDC item for the IDC definition.
23234 */
23235 aidc = vctxt->aidcs;
23236 while (aidc != NULL) {
23237 if (aidc->def == idc)
23238 break;
23239 aidc = aidc->next;
23240 }
23241 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023242 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23243 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023244 return (-1);
23245 }
23246 /*
23247 * Create an IDC matcher for every IDC definition.
23248 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023249 if (vctxt->idcMatcherCache != NULL) {
23250 /*
23251 * Reuse a cached matcher.
23252 */
23253 matcher = vctxt->idcMatcherCache;
23254 vctxt->idcMatcherCache = matcher->nextCached;
23255 matcher->nextCached = NULL;
23256 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000023257 matcher = (xmlSchemaIDCMatcherPtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023258 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23259 if (matcher == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023260 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023261 "allocating an IDC matcher", NULL);
23262 return (-1);
23263 }
23264 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023265 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023266 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023267 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023268 else
23269 last->next = matcher;
23270 last = matcher;
23271
23272 matcher->type = IDC_MATCHER;
Daniel Veillarddee23482008-04-11 12:58:43 +000023273 matcher->depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023274 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023275 matcher->idcType = aidc->def->type;
Daniel Veillarddee23482008-04-11 12:58:43 +000023276#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023277 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
Daniel Veillarddee23482008-04-11 12:58:43 +000023278#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023279 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023280 * Init the automaton state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023281 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023282 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023283 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023284 return (-1);
23285
23286 idc = idc->next;
23287 } while (idc != NULL);
23288 return (0);
23289}
23290
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023291static int
23292xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23293 xmlSchemaNodeInfoPtr ielem)
23294{
23295 xmlSchemaPSVIIDCBindingPtr bind;
23296 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23297 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23298 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023299
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023300 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23301 /* vctxt->createIDCNodeTables */
23302 while (matcher != NULL) {
23303 /*
23304 * Skip keyref IDCs and empty IDC target-lists.
23305 */
23306 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23307 WXS_ILIST_IS_EMPTY(matcher->targets))
23308 {
23309 matcher = matcher->next;
23310 continue;
23311 }
23312 /*
23313 * If we _want_ the IDC node-table to be created in any case
23314 * then do so. Otherwise create them only if keyrefs need them.
23315 */
23316 if ((! vctxt->createIDCNodeTables) &&
23317 ((matcher->aidc->keyrefDepth == -1) ||
23318 (matcher->aidc->keyrefDepth > vctxt->depth)))
23319 {
23320 matcher = matcher->next;
23321 continue;
23322 }
23323 /*
23324 * Get/create the IDC binding on this element for the IDC definition.
23325 */
23326 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23327
23328 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23329 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23330 nbDupls = bind->dupls->nbItems;
23331 } else {
23332 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023333 nbDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023334 }
23335 if (bind->nodeTable != NULL) {
23336 nbNodeTable = bind->nbNodes;
23337 } else {
23338 nbNodeTable = 0;
23339 }
23340
23341 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23342 /*
23343 * Transfer all IDC target-nodes to the IDC node-table.
23344 */
23345 bind->nodeTable =
Daniel Veillarddee23482008-04-11 12:58:43 +000023346 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023347 bind->sizeNodes = matcher->targets->sizeItems;
23348 bind->nbNodes = matcher->targets->nbItems;
23349
23350 matcher->targets->items = NULL;
23351 matcher->targets->sizeItems = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023352 matcher->targets->nbItems = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023353 } else {
23354 /*
23355 * Compare the key-sequences and add to the IDC node-table.
23356 */
23357 nbTargets = matcher->targets->nbItems;
Daniel Veillarddee23482008-04-11 12:58:43 +000023358 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023359 nbFields = matcher->aidc->def->nbFields;
23360 i = 0;
23361 do {
23362 keys = targets[i]->keys;
Daniel Veillarddee23482008-04-11 12:58:43 +000023363 if (nbDupls) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023364 /*
23365 * Search in already found duplicates first.
23366 */
23367 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023368 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023369 if (nbFields == 1) {
23370 res = xmlSchemaAreValuesEqual(keys[0]->val,
23371 dupls[j]->keys[0]->val);
23372 if (res == -1)
23373 goto internal_error;
23374 if (res == 1) {
23375 /*
23376 * Equal key-sequence.
23377 */
23378 goto next_target;
23379 }
23380 } else {
23381 res = 0;
23382 ntkeys = dupls[j]->keys;
23383 for (k = 0; k < nbFields; k++) {
23384 res = xmlSchemaAreValuesEqual(keys[k]->val,
23385 ntkeys[k]->val);
23386 if (res == -1)
23387 goto internal_error;
23388 if (res == 0) {
23389 /*
23390 * One of the keys differs.
23391 */
23392 break;
23393 }
23394 }
23395 if (res == 1) {
23396 /*
23397 * Equal key-sequence found.
23398 */
23399 goto next_target;
23400 }
23401 }
23402 j++;
Daniel Veillarddee23482008-04-11 12:58:43 +000023403 } while (j < nbDupls);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023404 }
23405 if (nbNodeTable) {
23406 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023407 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023408 if (nbFields == 1) {
23409 res = xmlSchemaAreValuesEqual(keys[0]->val,
23410 bind->nodeTable[j]->keys[0]->val);
23411 if (res == -1)
23412 goto internal_error;
23413 if (res == 0) {
23414 /*
23415 * The key-sequence differs.
23416 */
23417 goto next_node_table_entry;
23418 }
23419 } else {
23420 res = 0;
23421 ntkeys = bind->nodeTable[j]->keys;
23422 for (k = 0; k < nbFields; k++) {
23423 res = xmlSchemaAreValuesEqual(keys[k]->val,
23424 ntkeys[k]->val);
23425 if (res == -1)
23426 goto internal_error;
23427 if (res == 0) {
23428 /*
23429 * One of the keys differs.
23430 */
23431 goto next_node_table_entry;
23432 }
23433 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023434 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023435 /*
23436 * Add the duplicate to the list of duplicates.
23437 */
23438 if (bind->dupls == NULL) {
23439 bind->dupls = xmlSchemaItemListCreate();
23440 if (bind->dupls == NULL)
23441 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023442 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023443 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23444 goto internal_error;
23445 /*
23446 * Remove the duplicate entry from the IDC node-table.
23447 */
23448 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23449 bind->nbNodes--;
23450
23451 goto next_target;
23452
23453next_node_table_entry:
23454 j++;
23455 } while (j < nbNodeTable);
23456 }
23457 /*
23458 * If everything is fine, then add the IDC target-node to
23459 * the IDC node-table.
23460 */
23461 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23462 goto internal_error;
23463
23464next_target:
23465 i++;
23466 } while (i < nbTargets);
23467 }
23468 matcher = matcher->next;
23469 }
23470 return(0);
23471
23472internal_error:
23473 return(-1);
23474}
23475
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023476/**
Daniel Veillarddee23482008-04-11 12:58:43 +000023477 * xmlSchemaBubbleIDCNodeTables:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023478 * @depth: the current tree depth
23479 *
Daniel Veillarddee23482008-04-11 12:58:43 +000023480 * Merges IDC bindings of an element at @depth into the corresponding IDC
23481 * bindings of its parent element. If a duplicate note-table entry is found,
23482 * both, the parent node-table entry and child entry are discarded from the
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023483 * node-table of the parent.
23484 *
23485 * Returns 0 if OK and -1 on internal errors.
23486 */
23487static int
23488xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23489{
23490 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023491 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23492 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023493 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023494 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023495
Daniel Veillarddee23482008-04-11 12:58:43 +000023496 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023497 if (bind == NULL) {
23498 /* Fine, no table, no bubbles. */
23499 return (0);
23500 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023501
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023502 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23503 /*
23504 * Walk all bindings; create new or add to existing bindings.
23505 * Remove duplicate key-sequences.
23506 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023507 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023508
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023509 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23510 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023511 /*
23512 * Check if the key/unique IDC table needs to be bubbled.
23513 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023514 if (! vctxt->createIDCNodeTables) {
23515 aidc = vctxt->aidcs;
23516 do {
23517 if (aidc->def == bind->definition) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023518 if ((aidc->keyrefDepth == -1) ||
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023519 (aidc->keyrefDepth >= vctxt->depth)) {
23520 goto next_binding;
23521 }
23522 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023523 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023524 aidc = aidc->next;
23525 } while (aidc != NULL);
23526 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023527
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023528 if (parTable != NULL)
23529 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023530 /*
23531 * Search a matching parent binding for the
23532 * IDC definition.
23533 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023534 while (parBind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023535 if (parBind->definition == bind->definition)
23536 break;
23537 parBind = parBind->next;
23538 }
23539
23540 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023541 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023542 * Compare every node-table entry of the child node,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023543 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023544 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023545 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023546
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023547 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23548 oldDupls = parBind->dupls->nbItems;
23549 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23550 } else {
23551 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023552 oldDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023553 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023554
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023555 parNodes = parBind->nodeTable;
23556 nbFields = bind->definition->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000023557
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023558 for (i = 0; i < bind->nbNodes; i++) {
23559 node = bind->nodeTable[i];
23560 if (node == NULL)
23561 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023562 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023563 * ...with every key-sequence of the parent node, already
23564 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023565 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023566 if (oldDupls) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023567 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023568 while (j < oldDupls) {
23569 if (nbFields == 1) {
23570 ret = xmlSchemaAreValuesEqual(
23571 node->keys[0]->val,
23572 dupls[j]->keys[0]->val);
23573 if (ret == -1)
23574 goto internal_error;
23575 if (ret == 0) {
23576 j++;
23577 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023578 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023579 } else {
23580 parNode = dupls[j];
23581 for (k = 0; k < nbFields; k++) {
23582 ret = xmlSchemaAreValuesEqual(
23583 node->keys[k]->val,
23584 parNode->keys[k]->val);
23585 if (ret == -1)
23586 goto internal_error;
23587 if (ret == 0)
23588 break;
23589 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023590 }
23591 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023592 /* Duplicate found. */
23593 break;
23594 j++;
23595 }
23596 if (j != oldDupls) {
23597 /* Duplicate found. Skip this entry. */
23598 continue;
23599 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023600 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023601 /*
23602 * ... and with every key-sequence of the parent node.
23603 */
23604 if (oldNum) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023605 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023606 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023607 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023608 if (nbFields == 1) {
23609 ret = xmlSchemaAreValuesEqual(
23610 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023611 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023612 if (ret == -1)
23613 goto internal_error;
23614 if (ret == 0) {
23615 j++;
23616 continue;
23617 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023618 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023619 for (k = 0; k < nbFields; k++) {
23620 ret = xmlSchemaAreValuesEqual(
23621 node->keys[k]->val,
23622 parNode->keys[k]->val);
23623 if (ret == -1)
23624 goto internal_error;
23625 if (ret == 0)
23626 break;
23627 }
23628 }
23629 if (ret == 1)
23630 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023631 break;
23632 j++;
23633 }
23634 if (j != oldNum) {
23635 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023636 * Handle duplicates. Move the duplicate in
23637 * the parent's node-table to the list of
23638 * duplicates.
Daniel Veillarddee23482008-04-11 12:58:43 +000023639 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023640 oldNum--;
23641 parBind->nbNodes--;
23642 /*
23643 * Move last old item to pos of duplicate.
23644 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023645 parNodes[j] = parNodes[oldNum];
Daniel Veillarddee23482008-04-11 12:58:43 +000023646
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023647 if (parBind->nbNodes != oldNum) {
23648 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023649 * If new items exist, move last new item to
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023650 * last of old items.
23651 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023652 parNodes[oldNum] =
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023653 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023654 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023655 if (parBind->dupls == NULL) {
23656 parBind->dupls = xmlSchemaItemListCreate();
23657 if (parBind->dupls == NULL)
23658 goto internal_error;
23659 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023660 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023661 } else {
23662 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023663 * Add the node-table entry (node and key-sequence) of
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023664 * the child node to the node table of the parent node.
23665 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023666 if (parBind->nodeTable == NULL) {
23667 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023668 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023669 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023670 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023671 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023672 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023673 }
23674 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023675 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023676 parBind->sizeNodes *= 2;
Daniel Veillarddee23482008-04-11 12:58:43 +000023677 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23678 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023679 sizeof(xmlSchemaPSVIIDCNodePtr));
23680 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023681 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023682 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023683 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023684 }
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023685 }
23686 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023687 /*
23688 * Append the new node-table entry to the 'new node-table
23689 * entries' section.
23690 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023691 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023692 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023693
Daniel Veillarddee23482008-04-11 12:58:43 +000023694 }
23695
23696 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023697 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023698 /*
23699 * No binding for the IDC was found: create a new one and
23700 * copy all node-tables.
23701 */
23702 parBind = xmlSchemaIDCNewBinding(bind->definition);
23703 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023704 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023705
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023706 /*
23707 * TODO: Hmm, how to optimize the initial number of
23708 * allocated entries?
23709 */
23710 if (bind->nbNodes != 0) {
23711 /*
23712 * Add all IDC node-table entries.
23713 */
23714 if (! vctxt->psviExposeIDCNodeTables) {
23715 /*
23716 * Just move the entries.
23717 * NOTE: this is quite save here, since
23718 * all the keyref lookups have already been
23719 * performed.
23720 */
23721 parBind->nodeTable = bind->nodeTable;
23722 bind->nodeTable = NULL;
23723 parBind->sizeNodes = bind->sizeNodes;
23724 bind->sizeNodes = 0;
23725 parBind->nbNodes = bind->nbNodes;
23726 bind->nbNodes = 0;
23727 } else {
23728 /*
23729 * Copy the entries.
23730 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023731 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023732 xmlMalloc(bind->nbNodes *
23733 sizeof(xmlSchemaPSVIIDCNodePtr));
23734 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023735 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023736 "allocating an array of IDC node-table "
23737 "items", NULL);
23738 xmlSchemaIDCFreeBinding(parBind);
23739 goto internal_error;
23740 }
23741 parBind->sizeNodes = bind->nbNodes;
23742 parBind->nbNodes = bind->nbNodes;
23743 memcpy(parBind->nodeTable, bind->nodeTable,
23744 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23745 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023746 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023747 if (bind->dupls) {
23748 /*
23749 * Move the duplicates.
23750 */
23751 if (parBind->dupls != NULL)
23752 xmlSchemaItemListFree(parBind->dupls);
23753 parBind->dupls = bind->dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023754 bind->dupls = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023755 }
Daniel Veillard76d36452009-09-07 11:19:33 +020023756 if (parTable != NULL) {
23757 if (*parTable == NULL)
23758 *parTable = parBind;
23759 else {
23760 parBind->next = *parTable;
23761 *parTable = parBind;
23762 }
23763 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023764 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023765
23766next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023767 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023768 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023769 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023770
23771internal_error:
23772 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023773}
23774
23775/**
23776 * xmlSchemaCheckCVCIDCKeyRef:
23777 * @vctxt: the WXS validation context
23778 * @elemDecl: the element declaration
23779 *
23780 * Check the cvc-idc-keyref constraints.
23781 */
23782static int
23783xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23784{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023785 xmlSchemaIDCMatcherPtr matcher;
23786 xmlSchemaPSVIIDCBindingPtr bind;
Daniel Veillarddee23482008-04-11 12:58:43 +000023787
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023788 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023789 /*
23790 * Find a keyref.
23791 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023792 while (matcher != NULL) {
23793 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23794 matcher->targets &&
23795 matcher->targets->nbItems)
23796 {
23797 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023798 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023799 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023800
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023801 nbFields = matcher->aidc->def->nbFields;
23802
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023803 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023804 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023805 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023806 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023807 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023808 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023809 bind->definition)
23810 break;
23811 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023812 }
23813 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023814 /*
23815 * Search for a matching key-sequences.
23816 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023817 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023818 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023819 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023820 if (bind != NULL) {
23821 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023822 for (j = 0; j < bind->nbNodes; j++) {
23823 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023824 for (k = 0; k < nbFields; k++) {
23825 res = xmlSchemaAreValuesEqual(keys[k]->val,
23826 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023827 if (res == 0)
23828 break;
23829 else if (res == -1) {
23830 return (-1);
23831 }
23832 }
23833 if (res == 1) {
23834 /*
23835 * Match found.
23836 */
23837 break;
23838 }
23839 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023840 if ((res == 0) && hasDupls) {
23841 /*
23842 * Search in duplicates
23843 */
23844 for (j = 0; j < bind->dupls->nbItems; j++) {
23845 keys = ((xmlSchemaPSVIIDCNodePtr)
23846 bind->dupls->items[j])->keys;
23847 for (k = 0; k < nbFields; k++) {
23848 res = xmlSchemaAreValuesEqual(keys[k]->val,
23849 refKeys[k]->val);
23850 if (res == 0)
23851 break;
23852 else if (res == -1) {
23853 return (-1);
23854 }
23855 }
23856 if (res == 1) {
23857 /*
23858 * Match in duplicates found.
23859 */
23860 xmlChar *str = NULL, *strB = NULL;
23861 xmlSchemaKeyrefErr(vctxt,
23862 XML_SCHEMAV_CVC_IDC, refNode,
23863 (xmlSchemaTypePtr) matcher->aidc->def,
23864 "More than one match found for "
23865 "key-sequence %s of keyref '%s'",
23866 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23867 refNode->keys, nbFields),
23868 xmlSchemaGetComponentQName(&strB,
23869 matcher->aidc->def));
23870 FREE_AND_NULL(str);
23871 FREE_AND_NULL(strB);
23872 break;
23873 }
23874 }
23875 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023876 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023877
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023878 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023879 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023880 xmlSchemaKeyrefErr(vctxt,
23881 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023882 (xmlSchemaTypePtr) matcher->aidc->def,
23883 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023884 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023885 refNode->keys, nbFields),
23886 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023887 FREE_AND_NULL(str);
23888 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023889 }
23890 }
23891 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023892 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023893 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023894 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023895 return (0);
23896}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023897
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023898/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080023899 * *
23900 * XML Reader validation code *
23901 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023902 ************************************************************************/
23903
23904static xmlSchemaAttrInfoPtr
23905xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023906{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023907 xmlSchemaAttrInfoPtr iattr;
23908 /*
23909 * Grow/create list of attribute infos.
23910 */
23911 if (vctxt->attrInfos == NULL) {
23912 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23913 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23914 vctxt->sizeAttrInfos = 1;
23915 if (vctxt->attrInfos == NULL) {
23916 xmlSchemaVErrMemory(vctxt,
23917 "allocating attribute info list", NULL);
23918 return (NULL);
23919 }
23920 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23921 vctxt->sizeAttrInfos++;
23922 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23923 xmlRealloc(vctxt->attrInfos,
23924 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23925 if (vctxt->attrInfos == NULL) {
23926 xmlSchemaVErrMemory(vctxt,
23927 "re-allocating attribute info list", NULL);
23928 return (NULL);
23929 }
23930 } else {
23931 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23932 if (iattr->localName != NULL) {
23933 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23934 "attr info not cleared");
23935 return (NULL);
23936 }
23937 iattr->nodeType = XML_ATTRIBUTE_NODE;
23938 return (iattr);
23939 }
23940 /*
23941 * Create an attribute info.
23942 */
23943 iattr = (xmlSchemaAttrInfoPtr)
23944 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23945 if (iattr == NULL) {
23946 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23947 return (NULL);
23948 }
23949 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23950 iattr->nodeType = XML_ATTRIBUTE_NODE;
23951 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23952
23953 return (iattr);
23954}
23955
23956static int
23957xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23958 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023959 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023960 const xmlChar *localName,
Daniel Veillarddee23482008-04-11 12:58:43 +000023961 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023962 int ownedNames,
23963 xmlChar *value,
23964 int ownedValue)
23965{
23966 xmlSchemaAttrInfoPtr attr;
23967
23968 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23969 if (attr == NULL) {
23970 VERROR_INT("xmlSchemaPushAttribute",
23971 "calling xmlSchemaGetFreshAttrInfo()");
23972 return (-1);
23973 }
23974 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023975 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023976 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23977 attr->localName = localName;
23978 attr->nsName = nsName;
23979 if (ownedNames)
23980 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23981 /*
23982 * Evaluate if it's an XSI attribute.
23983 */
23984 if (nsName != NULL) {
23985 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23986 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023987 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023988 }
23989 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23990 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23991 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23992 }
23993 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23994 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23995 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23996 }
23997 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23998 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23999 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24000 }
24001 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24002 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24003 }
24004 }
24005 attr->value = value;
24006 if (ownedValue)
24007 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24008 if (attr->metaType != 0)
24009 attr->state = XML_SCHEMAS_ATTR_META;
24010 return (0);
24011}
24012
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024013/**
24014 * xmlSchemaClearElemInfo:
24015 * @vctxt: the WXS validation context
24016 * @ielem: the element information item
24017 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024018static void
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024019xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24020 xmlSchemaNodeInfoPtr ielem)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024021{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024022 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000024023 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024024 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24025 FREE_AND_NULL(ielem->localName);
24026 FREE_AND_NULL(ielem->nsName);
24027 } else {
24028 ielem->localName = NULL;
24029 ielem->nsName = NULL;
24030 }
24031 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24032 FREE_AND_NULL(ielem->value);
24033 } else {
24034 ielem->value = NULL;
24035 }
24036 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024037 /*
24038 * PSVI TODO: Be careful not to free it when the value is
24039 * exposed via PSVI.
24040 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024041 xmlSchemaFreeValue(ielem->val);
24042 ielem->val = NULL;
24043 }
24044 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024045 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024046 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24047 * Does it work?
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024048 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024049 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24050#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024051 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024052#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024053 ielem->idcMatchers = NULL;
24054 }
24055 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024056 /*
24057 * OPTIMIZE TODO: Use a pool of IDC tables??.
24058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024059 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24060 ielem->idcTable = NULL;
24061 }
24062 if (ielem->regexCtxt != NULL) {
24063 xmlRegFreeExecCtxt(ielem->regexCtxt);
24064 ielem->regexCtxt = NULL;
24065 }
24066 if (ielem->nsBindings != NULL) {
24067 xmlFree((xmlChar **)ielem->nsBindings);
24068 ielem->nsBindings = NULL;
24069 ielem->nbNsBindings = 0;
24070 ielem->sizeNsBindings = 0;
24071 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024072}
24073
24074/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024075 * xmlSchemaGetFreshElemInfo:
24076 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024077 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024078 * Creates/reuses and initializes the element info item for
24079 * the currect tree depth.
24080 *
24081 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024082 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024083static xmlSchemaNodeInfoPtr
24084xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024085{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024086 xmlSchemaNodeInfoPtr info = NULL;
24087
24088 if (vctxt->depth > vctxt->sizeElemInfos) {
24089 VERROR_INT("xmlSchemaGetFreshElemInfo",
24090 "inconsistent depth encountered");
24091 return (NULL);
24092 }
24093 if (vctxt->elemInfos == NULL) {
24094 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24095 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24096 if (vctxt->elemInfos == NULL) {
24097 xmlSchemaVErrMemory(vctxt,
24098 "allocating the element info array", NULL);
24099 return (NULL);
24100 }
24101 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24102 vctxt->sizeElemInfos = 10;
24103 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24104 int i = vctxt->sizeElemInfos;
24105
24106 vctxt->sizeElemInfos *= 2;
24107 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24108 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24109 sizeof(xmlSchemaNodeInfoPtr));
24110 if (vctxt->elemInfos == NULL) {
24111 xmlSchemaVErrMemory(vctxt,
24112 "re-allocating the element info array", NULL);
24113 return (NULL);
24114 }
24115 /*
24116 * We need the new memory to be NULLed.
24117 * TODO: Use memset instead?
24118 */
24119 for (; i < vctxt->sizeElemInfos; i++)
24120 vctxt->elemInfos[i] = NULL;
24121 } else
24122 info = vctxt->elemInfos[vctxt->depth];
24123
24124 if (info == NULL) {
24125 info = (xmlSchemaNodeInfoPtr)
24126 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24127 if (info == NULL) {
24128 xmlSchemaVErrMemory(vctxt,
24129 "allocating an element info", NULL);
24130 return (NULL);
24131 }
24132 vctxt->elemInfos[vctxt->depth] = info;
24133 } else {
24134 if (info->localName != NULL) {
24135 VERROR_INT("xmlSchemaGetFreshElemInfo",
24136 "elem info has not been cleared");
24137 return (NULL);
24138 }
24139 }
24140 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24141 info->nodeType = XML_ELEMENT_NODE;
24142 info->depth = vctxt->depth;
24143
24144 return (info);
24145}
24146
24147#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24148#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24149#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24150
24151static int
24152xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24153 xmlNodePtr node,
24154 xmlSchemaTypePtr type,
24155 xmlSchemaValType valType,
24156 const xmlChar * value,
24157 xmlSchemaValPtr val,
24158 unsigned long length,
24159 int fireErrors)
24160{
24161 int ret, error = 0;
24162
24163 xmlSchemaTypePtr tmpType;
24164 xmlSchemaFacetLinkPtr facetLink;
24165 xmlSchemaFacetPtr facet;
24166 unsigned long len = 0;
24167 xmlSchemaWhitespaceValueType ws;
24168
24169 /*
24170 * In Libxml2, derived built-in types have currently no explicit facets.
24171 */
24172 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024173 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024174
24175 /*
24176 * NOTE: Do not jump away, if the facetSet of the given type is
24177 * empty: until now, "pattern" and "enumeration" facets of the
24178 * *base types* need to be checked as well.
24179 */
24180 if (type->facetSet == NULL)
24181 goto pattern_and_enum;
24182
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024183 if (! WXS_IS_ATOMIC(type)) {
24184 if (WXS_IS_LIST(type))
24185 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024186 else
24187 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024188 }
Scott Graham58b84e12015-06-30 10:47:16 +080024189
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024190 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024191 * Whitespace handling is only of importance for string-based
24192 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024193 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024194 tmpType = xmlSchemaGetPrimitiveType(type);
24195 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024196 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024197 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24198 } else
24199 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
Scott Graham58b84e12015-06-30 10:47:16 +080024200
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024201 /*
24202 * If the value was not computed (for string or
24203 * anySimpleType based types), then use the provided
24204 * type.
24205 */
Scott Graham58b84e12015-06-30 10:47:16 +080024206 if (val != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024207 valType = xmlSchemaGetValType(val);
Daniel Veillarddee23482008-04-11 12:58:43 +000024208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024209 ret = 0;
24210 for (facetLink = type->facetSet; facetLink != NULL;
24211 facetLink = facetLink->next) {
24212 /*
24213 * Skip the pattern "whiteSpace": it is used to
24214 * format the character content beforehand.
24215 */
24216 switch (facetLink->facet->type) {
24217 case XML_SCHEMA_FACET_WHITESPACE:
24218 case XML_SCHEMA_FACET_PATTERN:
24219 case XML_SCHEMA_FACET_ENUMERATION:
24220 continue;
24221 case XML_SCHEMA_FACET_LENGTH:
24222 case XML_SCHEMA_FACET_MINLENGTH:
24223 case XML_SCHEMA_FACET_MAXLENGTH:
24224 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24225 valType, value, val, &len, ws);
24226 break;
24227 default:
24228 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24229 valType, value, val, ws);
24230 break;
24231 }
24232 if (ret < 0) {
24233 AERROR_INT("xmlSchemaValidateFacets",
24234 "validating against a atomic type facet");
24235 return (-1);
24236 } else if (ret > 0) {
24237 if (fireErrors)
24238 xmlSchemaFacetErr(actxt, ret, node,
24239 value, len, type, facetLink->facet, NULL, NULL, NULL);
24240 else
24241 return (ret);
24242 if (error == 0)
24243 error = ret;
24244 }
24245 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024246 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024247
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024248WXS_IS_LIST:
24249 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024250 goto pattern_and_enum;
24251 /*
24252 * "length", "minLength" and "maxLength" of list types.
24253 */
24254 ret = 0;
24255 for (facetLink = type->facetSet; facetLink != NULL;
24256 facetLink = facetLink->next) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024257
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024258 switch (facetLink->facet->type) {
24259 case XML_SCHEMA_FACET_LENGTH:
24260 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillarddee23482008-04-11 12:58:43 +000024261 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024262 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24263 value, length, NULL);
24264 break;
24265 default:
24266 continue;
24267 }
24268 if (ret < 0) {
24269 AERROR_INT("xmlSchemaValidateFacets",
24270 "validating against a list type facet");
24271 return (-1);
24272 } else if (ret > 0) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024273 if (fireErrors)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024274 xmlSchemaFacetErr(actxt, ret, node,
24275 value, length, type, facetLink->facet, NULL, NULL, NULL);
24276 else
24277 return (ret);
24278 if (error == 0)
24279 error = ret;
24280 }
24281 ret = 0;
24282 }
24283
24284pattern_and_enum:
24285 if (error >= 0) {
24286 int found = 0;
24287 /*
24288 * Process enumerations. Facet values are in the value space
24289 * of the defining type's base type. This seems to be a bug in the
24290 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24291 * Only the first set of enumerations in the ancestor-or-self axis
24292 * is used for validation.
24293 */
24294 ret = 0;
24295 tmpType = type;
24296 do {
24297 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24298 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24299 continue;
24300 found = 1;
24301 ret = xmlSchemaAreValuesEqual(facet->val, val);
24302 if (ret == 1)
24303 break;
24304 else if (ret < 0) {
24305 AERROR_INT("xmlSchemaValidateFacets",
24306 "validating against an enumeration facet");
24307 return (-1);
24308 }
24309 }
24310 if (ret != 0)
24311 break;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +000024312 /*
24313 * Break on the first set of enumerations. Any additional
24314 * enumerations which might be existent on the ancestors
24315 * of the current type are restricted by this set; thus
24316 * *must* *not* be taken into account.
24317 */
24318 if (found)
24319 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024320 tmpType = tmpType->baseType;
24321 } while ((tmpType != NULL) &&
24322 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24323 if (found && (ret == 0)) {
24324 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24325 if (fireErrors) {
24326 xmlSchemaFacetErr(actxt, ret, node,
24327 value, 0, type, NULL, NULL, NULL, NULL);
24328 } else
24329 return (ret);
24330 if (error == 0)
24331 error = ret;
24332 }
24333 }
24334
24335 if (error >= 0) {
24336 int found;
24337 /*
24338 * Process patters. Pattern facets are ORed at type level
24339 * and ANDed if derived. Walk the base type axis.
24340 */
24341 tmpType = type;
24342 facet = NULL;
24343 do {
24344 found = 0;
24345 for (facetLink = tmpType->facetSet; facetLink != NULL;
24346 facetLink = facetLink->next) {
24347 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24348 continue;
24349 found = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000024350 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024351 * NOTE that for patterns, @value needs to be the
24352 * normalized vaule.
24353 */
24354 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24355 if (ret == 1)
24356 break;
24357 else if (ret < 0) {
24358 AERROR_INT("xmlSchemaValidateFacets",
24359 "validating against a pattern facet");
24360 return (-1);
24361 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000024362 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024363 * Save the last non-validating facet.
24364 */
24365 facet = facetLink->facet;
24366 }
24367 }
24368 if (found && (ret != 1)) {
24369 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24370 if (fireErrors) {
24371 xmlSchemaFacetErr(actxt, ret, node,
24372 value, 0, type, facet, NULL, NULL, NULL);
24373 } else
24374 return (ret);
24375 if (error == 0)
24376 error = ret;
24377 break;
24378 }
24379 tmpType = tmpType->baseType;
24380 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24381 }
24382
24383 return (error);
24384}
Daniel Veillarddee23482008-04-11 12:58:43 +000024385
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024386static xmlChar *
24387xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24388 const xmlChar *value)
24389{
Daniel Veillarddee23482008-04-11 12:58:43 +000024390 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024391 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24392 return (xmlSchemaCollapseString(value));
24393 case XML_SCHEMA_WHITESPACE_REPLACE:
24394 return (xmlSchemaWhiteSpaceReplace(value));
24395 default:
24396 return (NULL);
24397 }
24398}
24399
24400static int
24401xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24402 const xmlChar *value,
24403 xmlSchemaValPtr *val,
24404 int valNeeded)
24405{
24406 int ret;
24407 const xmlChar *nsName;
24408 xmlChar *local, *prefix = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000024409
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024410 ret = xmlValidateQName(value, 1);
24411 if (ret != 0) {
24412 if (ret == -1) {
24413 VERROR_INT("xmlSchemaValidateQName",
24414 "calling xmlValidateQName()");
24415 return (-1);
24416 }
24417 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24418 }
24419 /*
24420 * NOTE: xmlSplitQName2 will always return a duplicated
24421 * strings.
24422 */
24423 local = xmlSplitQName2(value, &prefix);
24424 if (local == NULL)
24425 local = xmlStrdup(value);
24426 /*
24427 * OPTIMIZE TODO: Use flags for:
24428 * - is there any namespace binding?
24429 * - is there a default namespace?
24430 */
24431 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
Daniel Veillarddee23482008-04-11 12:58:43 +000024432
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024433 if (prefix != NULL) {
24434 xmlFree(prefix);
24435 /*
24436 * A namespace must be found if the prefix is
24437 * NOT NULL.
24438 */
24439 if (nsName == NULL) {
24440 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024441 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024442 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024443 "The QName value '%s' has no "
24444 "corresponding namespace declaration in "
24445 "scope", value, NULL);
24446 if (local != NULL)
24447 xmlFree(local);
24448 return (ret);
24449 }
24450 }
24451 if (valNeeded && val) {
24452 if (nsName != NULL)
24453 *val = xmlSchemaNewQNameValue(
24454 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24455 else
24456 *val = xmlSchemaNewQNameValue(NULL,
24457 BAD_CAST local);
24458 } else
24459 xmlFree(local);
24460 return (0);
24461}
24462
24463/*
24464* cvc-simple-type
24465*/
24466static int
24467xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24468 xmlNodePtr node,
24469 xmlSchemaTypePtr type,
24470 const xmlChar *value,
24471 xmlSchemaValPtr *retVal,
24472 int fireErrors,
24473 int normalize,
24474 int isNormalized)
24475{
24476 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24477 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024478 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024479 xmlChar *normValue = NULL;
24480
24481#define NORMALIZE(atype) \
24482 if ((! isNormalized) && \
24483 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24484 normValue = xmlSchemaNormalizeValue(atype, value); \
24485 if (normValue != NULL) \
24486 value = normValue; \
24487 isNormalized = 1; \
24488 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024489
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024490 if ((retVal != NULL) && (*retVal != NULL)) {
24491 xmlSchemaFreeValue(*retVal);
24492 *retVal = NULL;
24493 }
24494 /*
24495 * 3.14.4 Simple Type Definition Validation Rules
24496 * Validation Rule: String Valid
24497 */
24498 /*
24499 * 1 It is schema-valid with respect to that definition as defined
24500 * by Datatype Valid in [XML Schemas: Datatypes].
24501 */
24502 /*
24503 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
Jan Pokorný761c9e92013-11-29 23:26:27 +010024504 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24505 * the string must be a `declared entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024506 */
24507 /*
24508 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
Jan Pokorný761c9e92013-11-29 23:26:27 +010024509 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24510 * then every whitespace-delimited substring of the string must be a `declared
24511 * entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024512 */
24513 /*
24514 * 2.3 otherwise no further condition applies.
24515 */
24516 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24517 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024518 if (value == NULL)
24519 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024520 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024521 xmlSchemaTypePtr biType; /* The built-in type. */
24522 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024523 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24524 * a literal in the `lexical space` of {base type definition}"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024525 */
24526 /*
24527 * Whitespace-normalize.
24528 */
24529 NORMALIZE(type);
24530 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24531 /*
24532 * Get the built-in type.
24533 */
24534 biType = type->baseType;
24535 while ((biType != NULL) &&
24536 (biType->type != XML_SCHEMA_TYPE_BASIC))
24537 biType = biType->baseType;
24538
24539 if (biType == NULL) {
24540 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24541 "could not get the built-in type");
24542 goto internal_error;
24543 }
24544 } else
24545 biType = type;
24546 /*
24547 * NOTATIONs need to be processed here, since they need
24548 * to lookup in the hashtable of NOTATION declarations of the schema.
24549 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024550 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24551 switch (biType->builtInType) {
24552 case XML_SCHEMAS_NOTATION:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024553 ret = xmlSchemaValidateNotation(
24554 (xmlSchemaValidCtxtPtr) actxt,
24555 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24556 NULL, value, &val, valNeeded);
24557 break;
24558 case XML_SCHEMAS_QNAME:
24559 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24560 value, &val, valNeeded);
24561 break;
24562 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024563 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024564 if (valNeeded)
24565 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024566 value, &val, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024567 else
24568 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024569 value, NULL, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024570 break;
24571 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024572 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24573 switch (biType->builtInType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024574 case XML_SCHEMAS_NOTATION:
24575 ret = xmlSchemaValidateNotation(NULL,
24576 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24577 value, &val, valNeeded);
24578 break;
24579 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024580 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024581 if (valNeeded)
24582 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24583 value, &val, node);
24584 else
24585 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24586 value, NULL, node);
24587 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024589 } else {
24590 /*
24591 * Validation via a public API is not implemented yet.
24592 */
24593 TODO
24594 goto internal_error;
24595 }
24596 if (ret != 0) {
24597 if (ret < 0) {
24598 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24599 "validating against a built-in type");
24600 goto internal_error;
24601 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024602 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024603 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24604 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024605 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024606 }
24607 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24608 /*
24609 * Check facets.
24610 */
24611 ret = xmlSchemaValidateFacets(actxt, node, type,
24612 (xmlSchemaValType) biType->builtInType, value, val,
24613 0, fireErrors);
24614 if (ret != 0) {
24615 if (ret < 0) {
24616 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24617 "validating facets of atomic simple type");
24618 goto internal_error;
24619 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024620 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024621 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24622 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024623 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024624 }
24625 }
24626 if (fireErrors && (ret > 0))
24627 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024628 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024629
24630 xmlSchemaTypePtr itemType;
24631 const xmlChar *cur, *end;
24632 xmlChar *tmpValue = NULL;
24633 unsigned long len = 0;
24634 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
Jan Pokorný761c9e92013-11-29 23:26:27 +010024635 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24636 * of white space separated tokens, each of which `match`es a literal
24637 * in the `lexical space` of {item type definition}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024638 */
24639 /*
24640 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24641 * the list type has an enum or pattern facet.
24642 */
24643 NORMALIZE(type);
24644 /*
24645 * VAL TODO: Optimize validation of empty values.
24646 * VAL TODO: We do not have computed values for lists.
24647 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024648 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024649 cur = value;
24650 do {
24651 while (IS_BLANK_CH(*cur))
24652 cur++;
24653 end = cur;
24654 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24655 end++;
24656 if (end == cur)
24657 break;
24658 tmpValue = xmlStrndup(cur, end - cur);
24659 len++;
24660
24661 if (valNeeded)
24662 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24663 tmpValue, &curVal, fireErrors, 0, 1);
24664 else
24665 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24666 tmpValue, NULL, fireErrors, 0, 1);
24667 FREE_AND_NULL(tmpValue);
24668 if (curVal != NULL) {
24669 /*
24670 * Add to list of computed values.
24671 */
24672 if (val == NULL)
24673 val = curVal;
24674 else
24675 xmlSchemaValueAppend(prevVal, curVal);
24676 prevVal = curVal;
24677 curVal = NULL;
24678 }
24679 if (ret != 0) {
24680 if (ret < 0) {
24681 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24682 "validating an item of list simple type");
24683 goto internal_error;
24684 }
24685 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24686 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024688 cur = end;
24689 } while (*cur != 0);
24690 FREE_AND_NULL(tmpValue);
24691 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24692 /*
24693 * Apply facets (pattern, enumeration).
24694 */
24695 ret = xmlSchemaValidateFacets(actxt, node, type,
24696 XML_SCHEMAS_UNKNOWN, value, val,
24697 len, fireErrors);
24698 if (ret != 0) {
24699 if (ret < 0) {
24700 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24701 "validating facets of list simple type");
24702 goto internal_error;
24703 }
24704 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24705 }
24706 }
24707 if (fireErrors && (ret > 0)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024708 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024709 * Report the normalized value.
24710 */
24711 normalize = 1;
24712 NORMALIZE(type);
24713 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24714 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024715 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024716 xmlSchemaTypeLinkPtr memberLink;
24717 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024718 * TODO: For all datatypes `derived` by `union` whiteSpace does
24719 * not apply directly; however, the normalization behavior of `union`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024720 * types is controlled by the value of whiteSpace on that one of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010024721 * `memberTypes` against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024722 *
24723 * This means that the value is normalized by the first validating
24724 * member type, then the facets of the union type are applied. This
24725 * needs changing of the value!
24726 */
24727
24728 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024729 * 1.2.3 if {variety} is `union` then the string must `match` a
24730 * literal in the `lexical space` of at least one member of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024731 * {member type definitions}
24732 */
24733 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24734 if (memberLink == NULL) {
24735 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24736 "union simple type has no member types");
24737 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000024738 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024739 /*
24740 * Always normalize union type values, since we currently
24741 * cannot store the whitespace information with the value
24742 * itself; otherwise a later value-comparison would be
24743 * not possible.
24744 */
24745 while (memberLink != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024746 if (valNeeded)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024747 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24748 memberLink->type, value, &val, 0, 1, 0);
24749 else
24750 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24751 memberLink->type, value, NULL, 0, 1, 0);
24752 if (ret <= 0)
24753 break;
24754 memberLink = memberLink->next;
24755 }
24756 if (ret != 0) {
24757 if (ret < 0) {
24758 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24759 "validating members of union simple type");
24760 goto internal_error;
24761 }
24762 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24763 }
24764 /*
24765 * Apply facets (pattern, enumeration).
24766 */
24767 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24768 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024769 * The normalization behavior of `union` types is controlled by
24770 * the value of whiteSpace on that one of the `memberTypes`
24771 * against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024772 */
24773 NORMALIZE(memberLink->type);
24774 ret = xmlSchemaValidateFacets(actxt, node, type,
24775 XML_SCHEMAS_UNKNOWN, value, val,
24776 0, fireErrors);
24777 if (ret != 0) {
24778 if (ret < 0) {
24779 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24780 "validating facets of union simple type");
24781 goto internal_error;
24782 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024783 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024784 }
24785 }
24786 if (fireErrors && (ret > 0))
24787 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24788 }
24789
24790 if (normValue != NULL)
24791 xmlFree(normValue);
24792 if (ret == 0) {
24793 if (retVal != NULL)
24794 *retVal = val;
24795 else if (val != NULL)
24796 xmlSchemaFreeValue(val);
24797 } else if (val != NULL)
24798 xmlSchemaFreeValue(val);
24799 return (ret);
24800internal_error:
24801 if (normValue != NULL)
24802 xmlFree(normValue);
24803 if (val != NULL)
24804 xmlSchemaFreeValue(val);
24805 return (-1);
24806}
24807
24808static int
24809xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24810 const xmlChar *value,
24811 const xmlChar **nsName,
24812 const xmlChar **localName)
24813{
24814 int ret = 0;
24815
24816 if ((nsName == NULL) || (localName == NULL))
24817 return (-1);
24818 *nsName = NULL;
24819 *localName = NULL;
24820
24821 ret = xmlValidateQName(value, 1);
24822 if (ret == -1)
24823 return (-1);
24824 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024825 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024826 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24827 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24828 return (1);
24829 }
24830 {
24831 xmlChar *local = NULL;
24832 xmlChar *prefix;
24833
24834 /*
24835 * NOTE: xmlSplitQName2 will return a duplicated
24836 * string.
24837 */
24838 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024839 if (local == NULL)
24840 *localName = xmlDictLookup(vctxt->dict, value, -1);
24841 else {
24842 *localName = xmlDictLookup(vctxt->dict, local, -1);
24843 xmlFree(local);
24844 }
24845
24846 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24847
24848 if (prefix != NULL) {
24849 xmlFree(prefix);
24850 /*
24851 * A namespace must be found if the prefix is NOT NULL.
24852 */
24853 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024854 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024855 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024856 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024857 "The QName value '%s' has no "
24858 "corresponding namespace declaration in scope",
24859 value, NULL);
24860 return (2);
24861 }
24862 }
24863 }
24864 return (0);
24865}
24866
24867static int
24868xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24869 xmlSchemaAttrInfoPtr iattr,
24870 xmlSchemaTypePtr *localType,
24871 xmlSchemaElementPtr elemDecl)
24872{
24873 int ret = 0;
24874 /*
24875 * cvc-elt (3.3.4) : (4)
24876 * AND
24877 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24878 * (1.2.1.2.1) - (1.2.1.2.4)
24879 * Handle 'xsi:type'.
24880 */
24881 if (localType == NULL)
24882 return (-1);
24883 *localType = NULL;
24884 if (iattr == NULL)
24885 return (0);
24886 else {
24887 const xmlChar *nsName = NULL, *local = NULL;
24888 /*
24889 * TODO: We should report a *warning* that the type was overriden
24890 * by the instance.
24891 */
24892 ACTIVATE_ATTRIBUTE(iattr);
24893 /*
24894 * (cvc-elt) (3.3.4) : (4.1)
24895 * (cvc-assess-elt) (1.2.1.2.2)
24896 */
24897 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24898 &nsName, &local);
24899 if (ret != 0) {
24900 if (ret < 0) {
24901 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24902 "calling xmlSchemaQNameExpand() to validate the "
24903 "attribute 'xsi:type'");
24904 goto internal_error;
24905 }
24906 goto exit;
24907 }
24908 /*
24909 * (cvc-elt) (3.3.4) : (4.2)
24910 * (cvc-assess-elt) (1.2.1.2.3)
24911 */
24912 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24913 if (*localType == NULL) {
24914 xmlChar *str = NULL;
24915
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024916 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024917 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024918 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024919 "The QName value '%s' of the xsi:type attribute does not "
24920 "resolve to a type definition",
24921 xmlSchemaFormatQName(&str, nsName, local), NULL);
24922 FREE_AND_NULL(str);
24923 ret = vctxt->err;
24924 goto exit;
24925 }
24926 if (elemDecl != NULL) {
24927 int set = 0;
24928
24929 /*
24930 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
Jan Pokorný761c9e92013-11-29 23:26:27 +010024931 * "The `local type definition` must be validly
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024932 * derived from the {type definition} given the union of
24933 * the {disallowed substitutions} and the {type definition}'s
24934 * {prohibited substitutions}, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010024935 * Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024936 * (if it is a complex type definition),
24937 * or given {disallowed substitutions} as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010024938 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024939 * definition)."
24940 *
24941 * {disallowed substitutions}: the "block" on the element decl.
24942 * {prohibited substitutions}: the "block" on the type def.
24943 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024944 /*
24945 * OPTIMIZE TODO: We could map types already evaluated
24946 * to be validly derived from other types to avoid checking
24947 * this over and over for the same types.
24948 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024949 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24950 (elemDecl->subtypes->flags &
24951 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24952 set |= SUBSET_EXTENSION;
24953
24954 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24955 (elemDecl->subtypes->flags &
24956 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24957 set |= SUBSET_RESTRICTION;
24958
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024959 /*
24960 * REMOVED and CHANGED since this produced a parser context
24961 * which adds to the string dict of the schema. So this would
24962 * change the schema and we don't want this. We don't need
24963 * the parser context anymore.
24964 *
24965 * if ((vctxt->pctxt == NULL) &&
24966 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24967 * return (-1);
24968 */
24969
24970 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024971 elemDecl->subtypes, set) != 0) {
24972 xmlChar *str = NULL;
24973
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024974 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024975 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24976 "The type definition '%s', specified by xsi:type, is "
24977 "blocked or not validly derived from the type definition "
24978 "of the element declaration",
24979 xmlSchemaFormatQName(&str,
24980 (*localType)->targetNamespace,
24981 (*localType)->name),
24982 NULL);
24983 FREE_AND_NULL(str);
24984 ret = vctxt->err;
24985 *localType = NULL;
24986 }
24987 }
24988 }
24989exit:
24990 ACTIVATE_ELEM;
24991 return (ret);
24992internal_error:
24993 ACTIVATE_ELEM;
24994 return (-1);
24995}
24996
24997static int
24998xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24999{
25000 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Daniel Veillard14b56432006-03-09 18:41:40 +000025001 xmlSchemaTypePtr actualType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025002
25003 /*
25004 * cvc-elt (3.3.4) : 1
25005 */
25006 if (elemDecl == NULL) {
25007 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25008 "No matching declaration available");
25009 return (vctxt->err);
25010 }
Daniel Veillard14b56432006-03-09 18:41:40 +000025011 actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025012 /*
25013 * cvc-elt (3.3.4) : 2
25014 */
25015 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25016 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25017 "The element declaration is abstract");
25018 return (vctxt->err);
25019 }
25020 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025021 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25022 "The type definition is absent");
25023 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025024 }
25025 if (vctxt->nbAttrInfos != 0) {
25026 int ret;
25027 xmlSchemaAttrInfoPtr iattr;
25028 /*
25029 * cvc-elt (3.3.4) : 3
25030 * Handle 'xsi:nil'.
25031 */
25032 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25033 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25034 if (iattr) {
25035 ACTIVATE_ATTRIBUTE(iattr);
25036 /*
25037 * Validate the value.
25038 */
25039 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025040 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025041 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25042 iattr->value, &(iattr->val), 1, 0, 0);
25043 ACTIVATE_ELEM;
25044 if (ret < 0) {
25045 VERROR_INT("xmlSchemaValidateElemDecl",
25046 "calling xmlSchemaVCheckCVCSimpleType() to "
25047 "validate the attribute 'xsi:nil'");
25048 return (-1);
25049 }
25050 if (ret == 0) {
25051 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25052 /*
25053 * cvc-elt (3.3.4) : 3.1
25054 */
25055 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25056 "The element is not 'nillable'");
25057 /* Does not return an error on purpose. */
25058 } else {
25059 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25060 /*
25061 * cvc-elt (3.3.4) : 3.2.2
25062 */
25063 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25064 (elemDecl->value != NULL)) {
25065 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25066 "The element cannot be 'nilled' because "
25067 "there is a fixed value constraint defined "
25068 "for it");
25069 /* Does not return an error on purpose. */
25070 } else
25071 vctxt->inode->flags |=
25072 XML_SCHEMA_ELEM_INFO_NILLED;
25073 }
25074 }
25075 }
25076 }
25077 /*
25078 * cvc-elt (3.3.4) : 4
25079 * Handle 'xsi:type'.
25080 */
25081 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25082 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25083 if (iattr) {
25084 xmlSchemaTypePtr localType = NULL;
25085
25086 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25087 elemDecl);
25088 if (ret != 0) {
25089 if (ret == -1) {
25090 VERROR_INT("xmlSchemaValidateElemDecl",
25091 "calling xmlSchemaProcessXSIType() to "
25092 "process the attribute 'xsi:type'");
25093 return (-1);
25094 }
25095 /* Does not return an error on purpose. */
25096 }
25097 if (localType != NULL) {
25098 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25099 actualType = localType;
25100 }
25101 }
25102 }
25103 /*
25104 * IDC: Register identity-constraint XPath matchers.
25105 */
25106 if ((elemDecl->idcs != NULL) &&
25107 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25108 return (-1);
25109 /*
25110 * No actual type definition.
25111 */
25112 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025113 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25114 "The type definition is absent");
25115 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025116 }
25117 /*
25118 * Remember the actual type definition.
25119 */
25120 vctxt->inode->typeDef = actualType;
25121
25122 return (0);
25123}
25124
25125static int
25126xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25127{
25128 xmlSchemaAttrInfoPtr iattr;
25129 int ret = 0, i;
25130
25131 /*
25132 * SPEC cvc-type (3.1.1)
25133 * "The attributes of must be empty, excepting those whose namespace
25134 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25135 * whose local name is one of type, nil, schemaLocation or
25136 * noNamespaceSchemaLocation."
25137 */
25138 if (vctxt->nbAttrInfos == 0)
25139 return (0);
25140 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25141 iattr = vctxt->attrInfos[i];
25142 if (! iattr->metaType) {
25143 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025144 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025145 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25146 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25147 }
25148 }
25149 ACTIVATE_ELEM
25150 return (ret);
25151}
25152
25153/*
25154* Cleanup currently used attribute infos.
25155*/
25156static void
25157xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25158{
25159 int i;
25160 xmlSchemaAttrInfoPtr attr;
25161
25162 if (vctxt->nbAttrInfos == 0)
25163 return;
25164 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25165 attr = vctxt->attrInfos[i];
25166 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25167 if (attr->localName != NULL)
25168 xmlFree((xmlChar *) attr->localName);
25169 if (attr->nsName != NULL)
25170 xmlFree((xmlChar *) attr->nsName);
25171 }
25172 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25173 if (attr->value != NULL)
25174 xmlFree((xmlChar *) attr->value);
25175 }
25176 if (attr->val != NULL) {
25177 xmlSchemaFreeValue(attr->val);
25178 attr->val = NULL;
25179 }
25180 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25181 }
25182 vctxt->nbAttrInfos = 0;
25183}
25184
25185/*
25186* 3.4.4 Complex Type Definition Validation Rules
25187* Element Locally Valid (Complex Type) (cvc-complex-type)
25188* 3.2.4 Attribute Declaration Validation Rules
25189* Validation Rule: Attribute Locally Valid (cvc-attribute)
25190* Attribute Locally Valid (Use) (cvc-au)
25191*
25192* Only "assessed" attribute information items will be visible to
25193* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25194*/
25195static int
25196xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25197{
Daniel Veillarddee23482008-04-11 12:58:43 +000025198 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025199 xmlSchemaItemListPtr attrUseList;
25200 xmlSchemaAttributeUsePtr attrUse = NULL;
25201 xmlSchemaAttributePtr attrDecl = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000025202 xmlSchemaAttrInfoPtr iattr, tmpiattr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025203 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025204 int xpathRes = 0, res, wildIDs = 0, fixed;
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025205 xmlNodePtr defAttrOwnerElem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025206
25207 /*
25208 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025209 * (1) "The declaration must not be `absent` (see Missing
25210 * Sub-components ($5.3) for how this can fail to be
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025211 * the case)."
25212 * (2) "Its {type definition} must not be absent."
25213 *
25214 * NOTE (1) + (2): This is not handled here, since we currently do not
25215 * allow validation against schemas which have missing sub-components.
25216 *
25217 * SPEC (cvc-complex-type)
25218 * (3) "For each attribute information item in the element information
25219 * item's [attributes] excepting those whose [namespace name] is
25220 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25221 * [local name] is one of type, nil, schemaLocation or
25222 * noNamespaceSchemaLocation, the appropriate case among the following
25223 * must be true:
25224 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025225 */
25226 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25227 /*
25228 * @nbAttrs is the number of attributes present in the instance.
25229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025230 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025231 if (attrUseList != NULL)
25232 nbUses = attrUseList->nbItems;
25233 else
25234 nbUses = 0;
25235 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025236 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025237 attrUse = attrUseList->items[i];
25238 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25239 for (j = 0; j < nbAttrs; j++) {
25240 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025241 /*
25242 * SPEC (cvc-complex-type) (3)
25243 * Skip meta attributes.
25244 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025245 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025246 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025247 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025248 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025249 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025250 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025251 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025252 continue;
25253 found = 1;
25254 /*
25255 * SPEC (cvc-complex-type)
25256 * (3.1) "If there is among the {attribute uses} an attribute
25257 * use with an {attribute declaration} whose {name} matches
25258 * the attribute information item's [local name] and whose
25259 * {target namespace} is identical to the attribute information
Jan Pokorný761c9e92013-11-29 23:26:27 +010025260 * item's [namespace name] (where an `absent` {target namespace}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025261 * is taken to be identical to a [namespace name] with no value),
Jan Pokorný761c9e92013-11-29 23:26:27 +010025262 * then the attribute information must be `valid` with respect
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025263 * to that attribute use as per Attribute Locally Valid (Use)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025264 * ($3.5.4). In this case the {attribute declaration} of that
25265 * attribute use is the `context-determined declaration` for the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025266 * attribute information item with respect to Schema-Validity
Jan Pokorný761c9e92013-11-29 23:26:27 +010025267 * Assessment (Attribute) ($3.2.4) and
25268 * Assessment Outcome (Attribute) ($3.2.5).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025269 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025270 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25271 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025272 /*
25273 * Context-determined declaration.
25274 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025275 iattr->decl = attrDecl;
25276 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025277 break;
25278 }
25279
25280 if (found)
25281 continue;
25282
25283 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25284 /*
25285 * Handle non-existent, required attributes.
25286 *
25287 * SPEC (cvc-complex-type)
25288 * (4) "The {attribute declaration} of each attribute use in
25289 * the {attribute uses} whose {required} is true matches one
25290 * of the attribute information items in the element information
25291 * item's [attributes] as per clause 3.1 above."
25292 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025293 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25294 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025295 VERROR_INT(
25296 "xmlSchemaVAttributesComplex",
25297 "calling xmlSchemaGetFreshAttrInfo()");
25298 return (-1);
25299 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025300 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25301 tmpiattr->use = attrUse;
Daniel Veillarddee23482008-04-11 12:58:43 +000025302 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025303 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25304 ((attrUse->defValue != NULL) ||
25305 (attrDecl->defValue != NULL))) {
25306 /*
25307 * Handle non-existent, optional, default/fixed attributes.
25308 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025309 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25310 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025311 VERROR_INT(
25312 "xmlSchemaVAttributesComplex",
25313 "calling xmlSchemaGetFreshAttrInfo()");
25314 return (-1);
25315 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025316 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25317 tmpiattr->use = attrUse;
25318 tmpiattr->decl = attrDecl;
25319 tmpiattr->typeDef = attrDecl->subtypes;
25320 tmpiattr->localName = attrDecl->name;
25321 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025322 }
25323 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025324
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025325 if (vctxt->nbAttrInfos == 0)
25326 return (0);
25327 /*
25328 * Validate against the wildcard.
25329 */
25330 if (type->attributeWildcard != NULL) {
25331 /*
25332 * SPEC (cvc-complex-type)
25333 * (3.2.1) "There must be an {attribute wildcard}."
25334 */
25335 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025336 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025337 /*
25338 * SPEC (cvc-complex-type) (3)
25339 * Skip meta attributes.
25340 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025341 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025342 continue;
25343 /*
25344 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025345 * (3.2.2) "The attribute information item must be `valid` with
25346 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025347 *
25348 * SPEC Item Valid (Wildcard) (cvc-wildcard)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025349 * "... its [namespace name] must be `valid` with respect to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025350 * the wildcard constraint, as defined in Wildcard allows
Jan Pokorný761c9e92013-11-29 23:26:27 +010025351 * Namespace Name ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025352 */
25353 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025354 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025355 /*
25356 * Handle processContents.
25357 *
25358 * SPEC (cvc-wildcard):
25359 * processContents | context-determined declaration:
25360 * "strict" "mustFind"
25361 * "lax" "none"
25362 * "skip" "skip"
25363 */
25364 if (type->attributeWildcard->processContents ==
25365 XML_SCHEMAS_ANY_SKIP) {
25366 /*
25367 * context-determined declaration = "skip"
25368 *
25369 * SPEC PSVI Assessment Outcome (Attribute)
25370 * [validity] = "notKnown"
25371 * [validation attempted] = "none"
25372 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025373 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025374 continue;
25375 }
25376 /*
25377 * Find an attribute declaration.
25378 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025379 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25380 iattr->localName, iattr->nsName);
25381 if (iattr->decl != NULL) {
25382 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025383 /*
25384 * SPEC (cvc-complex-type)
25385 * (5) "Let [Definition:] the wild IDs be the set of
25386 * all attribute information item to which clause 3.2
Jan Pokorný761c9e92013-11-29 23:26:27 +010025387 * applied and whose `validation` resulted in a
25388 * `context-determined declaration` of mustFind or no
25389 * `context-determined declaration` at all, and whose
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025390 * [local name] and [namespace name] resolve (as
Jan Pokorný761c9e92013-11-29 23:26:27 +010025391 * defined by QName resolution (Instance) ($3.15.4)) to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025392 * an attribute declaration whose {type definition} is
25393 * or is derived from ID. Then all of the following
25394 * must be true:"
25395 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025396 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025397 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025398 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025399 /*
25400 * SPEC (5.1) "There must be no more than one
Jan Pokorný761c9e92013-11-29 23:26:27 +010025401 * item in `wild IDs`."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025402 */
25403 if (wildIDs != 0) {
25404 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025405 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025406 TODO
25407 continue;
25408 }
25409 wildIDs++;
25410 /*
25411 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025412 * (5.2) "If `wild IDs` is non-empty, there must not
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025413 * be any attribute uses among the {attribute uses}
25414 * whose {attribute declaration}'s {type definition}
25415 * is or is derived from ID."
25416 */
Daniel Veillard2cdd17e2009-07-27 21:16:13 +020025417 if (attrUseList != NULL) {
25418 for (j = 0; j < attrUseList->nbItems; j++) {
25419 if (xmlSchemaIsDerivedFromBuiltInType(
25420 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25421 XML_SCHEMAS_ID)) {
25422 /* URGENT VAL TODO: implement */
25423 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25424 TODO
25425 break;
25426 }
25427 }
25428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025429 }
25430 } else if (type->attributeWildcard->processContents ==
25431 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025432 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025433 /*
25434 * SPEC PSVI Assessment Outcome (Attribute)
25435 * [validity] = "notKnown"
25436 * [validation attempted] = "none"
25437 */
25438 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025439 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025440 }
25441 }
25442 }
25443 }
25444
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025445 if (vctxt->nbAttrInfos == 0)
25446 return (0);
25447
25448 /*
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025449 * Get the owner element; needed for creation of default attributes.
25450 * This fixes bug #341337, reported by David Grohmann.
25451 */
25452 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25453 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25454 if (ielem && ielem->node && ielem->node->doc)
25455 defAttrOwnerElem = ielem->node;
25456 }
25457 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025458 * Validate values, create default attributes, evaluate IDCs.
25459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025460 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025461 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025462 /*
25463 * VAL TODO: Note that we won't try to resolve IDCs to
25464 * "lax" and "skip" validated attributes. Check what to
25465 * do in this case.
25466 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025467 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25468 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025469 continue;
25470 /*
25471 * VAL TODO: What to do if the type definition is missing?
25472 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025473 if (iattr->typeDef == NULL) {
25474 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025475 continue;
25476 }
25477
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025478 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025479 fixed = 0;
25480 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025481
25482 if (vctxt->xpathStates != NULL) {
25483 /*
25484 * Evaluate IDCs.
25485 */
25486 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25487 XML_ATTRIBUTE_NODE);
25488 if (xpathRes == -1) {
25489 VERROR_INT("xmlSchemaVAttributesComplex",
25490 "calling xmlSchemaXPathEvaluate()");
25491 goto internal_error;
25492 }
25493 }
25494
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025495 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025496 /*
25497 * Default/fixed attributes.
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025498 * We need the value only if we need to resolve IDCs or
25499 * will create default attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025500 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025501 if ((xpathRes) || (defAttrOwnerElem)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025502 if (iattr->use->defValue != NULL) {
25503 iattr->value = (xmlChar *) iattr->use->defValue;
25504 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025505 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025506 iattr->value = (xmlChar *) iattr->decl->defValue;
25507 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025508 }
25509 /*
25510 * IDCs will consume the precomputed default value,
25511 * so we need to clone it.
25512 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025513 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025514 VERROR_INT("xmlSchemaVAttributesComplex",
25515 "default/fixed value on an attribute use was "
25516 "not precomputed");
25517 goto internal_error;
25518 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025519 iattr->val = xmlSchemaCopyValue(iattr->val);
25520 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025521 VERROR_INT("xmlSchemaVAttributesComplex",
25522 "calling xmlSchemaCopyValue()");
25523 goto internal_error;
25524 }
25525 }
25526 /*
25527 * PSVI: Add the default attribute to the current element.
25528 * VAL TODO: Should we use the *normalized* value? This currently
25529 * uses the *initial* value.
25530 */
Daniel Veillarddee23482008-04-11 12:58:43 +000025531
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025532 if (defAttrOwnerElem) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025533 xmlChar *normValue;
25534 const xmlChar *value;
25535
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025536 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025537 /*
25538 * Normalize the value.
25539 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025540 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25541 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025542 if (normValue != NULL)
25543 value = BAD_CAST normValue;
25544
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025545 if (iattr->nsName == NULL) {
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025546 if (xmlNewProp(defAttrOwnerElem,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025547 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025548 VERROR_INT("xmlSchemaVAttributesComplex",
Alex Henrie73c50802015-10-26 18:33:14 +080025549 "calling xmlNewProp()");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025550 if (normValue != NULL)
25551 xmlFree(normValue);
25552 goto internal_error;
25553 }
25554 } else {
25555 xmlNsPtr ns;
25556
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025557 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25558 defAttrOwnerElem, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025559 if (ns == NULL) {
25560 xmlChar prefix[12];
25561 int counter = 0;
25562
25563 /*
25564 * Create a namespace declaration on the validation
25565 * root node if no namespace declaration is in scope.
25566 */
25567 do {
25568 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025569 ns = xmlSearchNs(defAttrOwnerElem->doc,
25570 defAttrOwnerElem, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025571 if (counter > 1000) {
25572 VERROR_INT(
25573 "xmlSchemaVAttributesComplex",
25574 "could not compute a ns prefix for a "
25575 "default/fixed attribute");
25576 if (normValue != NULL)
25577 xmlFree(normValue);
25578 goto internal_error;
25579 }
25580 } while (ns != NULL);
25581 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025582 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025583 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025584 /*
25585 * TODO:
25586 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25587 * If we have QNames: do we need to ensure there's a
25588 * prefix defined for the QName?
25589 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025590 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025591 }
25592 if (normValue != NULL)
25593 xmlFree(normValue);
25594 }
25595 /*
25596 * Go directly to IDC evaluation.
25597 */
25598 goto eval_idcs;
25599 }
25600 /*
25601 * Validate the value.
25602 */
25603 if (vctxt->value != NULL) {
25604 /*
25605 * Free last computed value; just for safety reasons.
25606 */
25607 xmlSchemaFreeValue(vctxt->value);
25608 vctxt->value = NULL;
25609 }
25610 /*
25611 * Note that the attribute *use* can be unavailable, if
25612 * the attribute was a wild attribute.
25613 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025614 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25615 ((iattr->use != NULL) &&
25616 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025617 fixed = 1;
25618 else
25619 fixed = 0;
25620 /*
25621 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025622 * (3) "The item's `normalized value` must be locally `valid`
Daniel Veillarddee23482008-04-11 12:58:43 +000025623 * with respect to that {type definition} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010025624 * String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025625 *
25626 * VAL TODO: Do we already have the
25627 * "normalized attribute value" here?
25628 */
25629 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025630 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025631 /*
25632 * Request a computed value.
25633 */
25634 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025635 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025636 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025637 1, 1, 0);
25638 } else {
25639 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025640 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025641 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025642 1, 0, 0);
25643 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025645 if (res != 0) {
25646 if (res == -1) {
25647 VERROR_INT("xmlSchemaVAttributesComplex",
25648 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25649 goto internal_error;
25650 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025651 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025652 /*
25653 * SPEC PSVI Assessment Outcome (Attribute)
25654 * [validity] = "invalid"
25655 */
25656 goto eval_idcs;
25657 }
25658
Daniel Veillarddee23482008-04-11 12:58:43 +000025659 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025660 /*
25661 * SPEC Attribute Locally Valid (Use) (cvc-au)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025662 * "For an attribute information item to be `valid`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025663 * with respect to an attribute use its *normalized*
Jan Pokorný761c9e92013-11-29 23:26:27 +010025664 * value must match the *canonical* lexical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025665 * representation of the attribute use's {value
25666 * constraint}value, if it is present and fixed."
25667 *
25668 * VAL TODO: The requirement for the *canonical* value
25669 * will be removed in XML Schema 1.1.
25670 */
25671 /*
25672 * SPEC Attribute Locally Valid (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025673 * (4) "The item's *actual* value must match the *value* of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025674 * the {value constraint}, if it is present and fixed."
25675 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025676 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025677 /* VAL TODO: A value was not precomputed. */
25678 TODO
25679 goto eval_idcs;
25680 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025681 if ((iattr->use != NULL) &&
25682 (iattr->use->defValue != NULL)) {
25683 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025684 /* VAL TODO: A default value was not precomputed. */
25685 TODO
25686 goto eval_idcs;
25687 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025688 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025689 /*
25690 if (xmlSchemaCompareValuesWhtsp(attr->val,
25691 (xmlSchemaWhitespaceValueType) ws,
25692 attr->use->defVal,
25693 (xmlSchemaWhitespaceValueType) ws) != 0) {
25694 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025695 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25696 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025697 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025698 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025699 /* VAL TODO: A default value was not precomputed. */
25700 TODO
25701 goto eval_idcs;
25702 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025703 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025704 /*
25705 if (xmlSchemaCompareValuesWhtsp(attr->val,
25706 (xmlSchemaWhitespaceValueType) ws,
25707 attrDecl->defVal,
25708 (xmlSchemaWhitespaceValueType) ws) != 0) {
25709 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025710 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25711 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025712 }
25713 /*
25714 * [validity] = "valid"
25715 */
25716 }
25717eval_idcs:
25718 /*
25719 * Evaluate IDCs.
25720 */
25721 if (xpathRes) {
25722 if (xmlSchemaXPathProcessHistory(vctxt,
25723 vctxt->depth +1) == -1) {
25724 VERROR_INT("xmlSchemaVAttributesComplex",
25725 "calling xmlSchemaXPathEvaluate()");
25726 goto internal_error;
25727 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025728 } else if (vctxt->xpathStates != NULL)
25729 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025730 }
25731
25732 /*
25733 * Report errors.
25734 */
25735 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025736 iattr = vctxt->attrInfos[i];
25737 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25738 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25739 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25740 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025741 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025742 ACTIVATE_ATTRIBUTE(iattr);
25743 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025744 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25745 xmlChar *str = NULL;
25746 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025747 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025748 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25749 "The attribute '%s' is required but missing",
25750 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025751 iattr->decl->targetNamespace,
25752 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025753 NULL);
25754 FREE_AND_NULL(str)
25755 break;
25756 }
25757 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25758 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25759 "The type definition is absent");
25760 break;
25761 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025762 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025763 XML_SCHEMAV_CVC_AU, NULL, NULL,
25764 "The value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000025765 "value constraint '%s'",
25766 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025767 break;
25768 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25769 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25770 "No matching global attribute declaration available, but "
25771 "demanded by the strict wildcard");
25772 break;
25773 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025774 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025775 break;
25776 /*
25777 * MAYBE VAL TODO: One might report different error messages
25778 * for the following errors.
25779 */
25780 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025781 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025782 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025783 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025784 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025785 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025786 }
25787 break;
25788 default:
25789 break;
25790 }
25791 }
25792
25793 ACTIVATE_ELEM;
25794 return (0);
25795internal_error:
25796 ACTIVATE_ELEM;
25797 return (-1);
25798}
25799
25800static int
25801xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25802 int *skip)
25803{
25804 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25805 /*
25806 * The namespace of the element was already identified to be
25807 * matching the wildcard.
25808 */
25809 if ((skip == NULL) || (wild == NULL) ||
25810 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25811 VERROR_INT("xmlSchemaValidateElemWildcard",
25812 "bad arguments");
25813 return (-1);
25814 }
25815 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025816 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25817 /*
25818 * URGENT VAL TODO: Either we need to position the stream to the
25819 * next sibling, or walk the whole subtree.
25820 */
25821 *skip = 1;
25822 return (0);
25823 }
25824 {
25825 xmlSchemaElementPtr decl = NULL;
25826
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025827 decl = xmlSchemaGetElem(vctxt->schema,
Daniel Veillarddee23482008-04-11 12:58:43 +000025828 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025829 if (decl != NULL) {
25830 vctxt->inode->decl = decl;
25831 return (0);
25832 }
25833 }
25834 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25835 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025836 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025837 "No matching global element declaration available, but "
25838 "demanded by the strict wildcard");
25839 return (vctxt->err);
25840 }
25841 if (vctxt->nbAttrInfos != 0) {
25842 xmlSchemaAttrInfoPtr iattr;
25843 /*
25844 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25845 * (1.2.1.2.1) - (1.2.1.2.3 )
25846 *
25847 * Use the xsi:type attribute for the type definition.
25848 */
25849 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25850 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25851 if (iattr != NULL) {
25852 if (xmlSchemaProcessXSIType(vctxt, iattr,
25853 &(vctxt->inode->typeDef), NULL) == -1) {
25854 VERROR_INT("xmlSchemaValidateElemWildcard",
25855 "calling xmlSchemaProcessXSIType() to "
25856 "process the attribute 'xsi:nil'");
25857 return (-1);
25858 }
25859 /*
25860 * Don't return an error on purpose.
25861 */
25862 return (0);
25863 }
25864 }
25865 /*
25866 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25867 *
25868 * Fallback to "anyType".
25869 */
25870 vctxt->inode->typeDef =
25871 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25872 return (0);
25873}
25874
25875/*
25876* xmlSchemaCheckCOSValidDefault:
25877*
25878* This will be called if: not nilled, no content and a default/fixed
25879* value is provided.
25880*/
25881
25882static int
25883xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25884 const xmlChar *value,
25885 xmlSchemaValPtr *val)
Daniel Veillarddee23482008-04-11 12:58:43 +000025886{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025887 int ret = 0;
25888 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25889
25890 /*
25891 * cos-valid-default:
25892 * Schema Component Constraint: Element Default Valid (Immediate)
Daniel Veillarddee23482008-04-11 12:58:43 +000025893 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025894 * definition the appropriate case among the following must be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000025895 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025896 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025897 /*
25898 * Complex type.
25899 *
25900 * SPEC (2.1) "its {content type} must be a simple type definition
25901 * or mixed."
25902 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010025903 * type}'s particle must be `emptiable` as defined by
25904 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025905 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025906 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25907 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25908 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025909 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25910 /* NOTE that this covers (2.2.2) as well. */
25911 VERROR(ret, NULL,
25912 "For a string to be a valid default, the type definition "
25913 "must be a simple type or a complex type with simple content "
25914 "or mixed content and a particle emptiable");
25915 return(ret);
25916 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025918 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000025919 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010025920 * must be `valid` with respect to that definition as defined by String
25921 * Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025922 *
25923 * AND
25924 *
Daniel Veillarddee23482008-04-11 12:58:43 +000025925 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010025926 * string must be `valid` with respect to that simple type definition
25927 * as defined by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000025928 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025929 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025930
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025931 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025932 NULL, inode->typeDef, value, val, 1, 1, 0);
25933
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025934 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025935
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025936 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025937 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25938 }
25939 if (ret < 0) {
25940 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25941 "calling xmlSchemaVCheckCVCSimpleType()");
Daniel Veillarddee23482008-04-11 12:58:43 +000025942 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025943 return (ret);
25944}
25945
25946static void
25947xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25948 const xmlChar * name ATTRIBUTE_UNUSED,
25949 xmlSchemaElementPtr item,
25950 xmlSchemaNodeInfoPtr inode)
25951{
25952 inode->decl = item;
25953#ifdef DEBUG_CONTENT
25954 {
25955 xmlChar *str = NULL;
25956
25957 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25958 xmlGenericError(xmlGenericErrorContext,
25959 "AUTOMATON callback for '%s' [declaration]\n",
25960 xmlSchemaFormatQName(&str,
25961 inode->localName, inode->nsName));
25962 } else {
25963 xmlGenericError(xmlGenericErrorContext,
25964 "AUTOMATON callback for '%s' [wildcard]\n",
25965 xmlSchemaFormatQName(&str,
25966 inode->localName, inode->nsName));
25967
25968 }
25969 FREE_AND_NULL(str)
25970 }
25971#endif
25972}
25973
25974static int
25975xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Daniel Veillarddee23482008-04-11 12:58:43 +000025976{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025977 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25978 if (vctxt->inode == NULL) {
25979 VERROR_INT("xmlSchemaValidatorPushElem",
25980 "calling xmlSchemaGetFreshElemInfo()");
25981 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000025982 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025983 vctxt->nbAttrInfos = 0;
25984 return (0);
25985}
25986
25987static int
25988xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25989 xmlSchemaNodeInfoPtr inode,
25990 xmlSchemaTypePtr type,
25991 const xmlChar *value)
25992{
25993 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25994 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025995 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025996 type, value, &(inode->val), 1, 1, 0));
25997 else
25998 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025999 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026000 type, value, NULL, 1, 0, 0));
26001}
26002
26003
26004
Daniel Veillarddee23482008-04-11 12:58:43 +000026005/*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006* Process END of element.
26007*/
26008static int
26009xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26010{
26011 int ret = 0;
26012 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26013
26014 if (vctxt->nbAttrInfos != 0)
26015 xmlSchemaClearAttrInfos(vctxt);
26016 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26017 /*
26018 * This element was not expected;
26019 * we will not validate child elements of broken parents.
26020 * Skip validation of all content of the parent.
26021 */
26022 vctxt->skipDepth = vctxt->depth -1;
26023 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026024 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026025 if ((inode->typeDef == NULL) ||
26026 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26027 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026028 * 1. the type definition might be missing if the element was
26029 * error prone
26030 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026031 */
26032 goto end_elem;
26033 }
26034 /*
26035 * Check the content model.
26036 */
26037 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26038 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26039
26040 /*
26041 * Workaround for "anyType".
26042 */
26043 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
Daniel Veillarddee23482008-04-11 12:58:43 +000026044 goto character_content;
26045
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026046 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26047 xmlChar *values[10];
26048 int terminal, nbval = 10, nbneg;
26049
26050 if (inode->regexCtxt == NULL) {
26051 /*
26052 * Create the regex context.
26053 */
26054 inode->regexCtxt =
26055 xmlRegNewExecCtxt(inode->typeDef->contModel,
26056 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26057 vctxt);
26058 if (inode->regexCtxt == NULL) {
26059 VERROR_INT("xmlSchemaValidatorPopElem",
26060 "failed to create a regex context");
26061 goto internal_error;
26062 }
26063#ifdef DEBUG_AUTOMATA
26064 xmlGenericError(xmlGenericErrorContext,
26065 "AUTOMATON create on '%s'\n", inode->localName);
Daniel Veillarddee23482008-04-11 12:58:43 +000026066#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026067 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026068
26069 /*
26070 * Do not check further content if the node has been nilled
26071 */
26072 if (INODE_NILLED(inode)) {
26073 ret = 0;
26074#ifdef DEBUG_AUTOMATA
26075 xmlGenericError(xmlGenericErrorContext,
26076 "AUTOMATON succeeded on nilled '%s'\n",
26077 inode->localName);
26078#endif
26079 goto skip_nilled;
26080 }
26081
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026082 /*
26083 * Get hold of the still expected content, since a further
26084 * call to xmlRegExecPushString() will loose this information.
Daniel Veillarddee23482008-04-11 12:58:43 +000026085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026086 xmlRegExecNextValues(inode->regexCtxt,
26087 &nbval, &nbneg, &values[0], &terminal);
26088 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
Daniel Veillard65fcf272007-07-11 17:55:30 +000026089 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026090 /*
26091 * Still missing something.
26092 */
26093 ret = 1;
26094 inode->flags |=
26095 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026096 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026097 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26098 "Missing child element(s)",
26099 nbval, nbneg, values);
26100#ifdef DEBUG_AUTOMATA
26101 xmlGenericError(xmlGenericErrorContext,
26102 "AUTOMATON missing ERROR on '%s'\n",
26103 inode->localName);
26104#endif
26105 } else {
26106 /*
26107 * Content model is satisfied.
26108 */
26109 ret = 0;
26110#ifdef DEBUG_AUTOMATA
26111 xmlGenericError(xmlGenericErrorContext,
26112 "AUTOMATON succeeded on '%s'\n",
26113 inode->localName);
26114#endif
26115 }
26116
26117 }
26118 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026119
26120skip_nilled:
26121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026122 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26123 goto end_elem;
26124
26125character_content:
26126
26127 if (vctxt->value != NULL) {
26128 xmlSchemaFreeValue(vctxt->value);
26129 vctxt->value = NULL;
26130 }
26131 /*
26132 * Check character content.
26133 */
26134 if (inode->decl == NULL) {
26135 /*
26136 * Speedup if no declaration exists.
26137 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026138 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026139 ret = xmlSchemaVCheckINodeDataType(vctxt,
26140 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026141 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026142 ret = xmlSchemaVCheckINodeDataType(vctxt,
26143 inode, inode->typeDef->contentTypeDef,
26144 inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026145 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026146 if (ret < 0) {
26147 VERROR_INT("xmlSchemaValidatorPopElem",
26148 "calling xmlSchemaVCheckCVCSimpleType()");
26149 goto internal_error;
26150 }
26151 goto end_elem;
26152 }
26153 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026154 * cvc-elt (3.3.4) : 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026155 * The appropriate case among the following must be true:
26156 */
26157 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026158 * cvc-elt (3.3.4) : 5.1
26159 * If the declaration has a {value constraint},
26160 * the item has neither element nor character [children] and
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026161 * clause 3.2 has not applied, then all of the following must be true:
26162 */
26163 if ((inode->decl->value != NULL) &&
Daniel Veillarddee23482008-04-11 12:58:43 +000026164 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026165 (! INODE_NILLED(inode))) {
26166 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026167 * cvc-elt (3.3.4) : 5.1.1
Jan Pokorný761c9e92013-11-29 23:26:27 +010026168 * If the `actual type definition` is a `local type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026169 * then the canonical lexical representation of the {value constraint}
Jan Pokorný761c9e92013-11-29 23:26:27 +010026170 * value must be a valid default for the `actual type definition` as
26171 * defined in Element Default Valid (Immediate) ($3.3.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026172 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026173 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026174 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026175 * NOTE: Although the *canonical* value is stated, it is not
26176 * relevant if canonical or not. Additionally XML Schema 1.1
26177 * will removed this requirement as well.
26178 */
26179 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26180
26181 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26182 inode->decl->value, &(inode->val));
26183 if (ret != 0) {
26184 if (ret < 0) {
26185 VERROR_INT("xmlSchemaValidatorPopElem",
26186 "calling xmlSchemaCheckCOSValidDefault()");
26187 goto internal_error;
26188 }
26189 goto end_elem;
26190 }
26191 /*
26192 * Stop here, to avoid redundant validation of the value
26193 * (see following).
26194 */
26195 goto default_psvi;
Daniel Veillarddee23482008-04-11 12:58:43 +000026196 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026197 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026198 * cvc-elt (3.3.4) : 5.1.2
26199 * The element information item with the canonical lexical
26200 * representation of the {value constraint} value used as its
Jan Pokorný761c9e92013-11-29 23:26:27 +010026201 * `normalized value` must be `valid` with respect to the
26202 * `actual type definition` as defined by Element Locally Valid (Type)
26203 * ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026204 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026205 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026206 ret = xmlSchemaVCheckINodeDataType(vctxt,
26207 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026208 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026209 ret = xmlSchemaVCheckINodeDataType(vctxt,
26210 inode, inode->typeDef->contentTypeDef,
Daniel Veillarddee23482008-04-11 12:58:43 +000026211 inode->decl->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026212 }
26213 if (ret != 0) {
26214 if (ret < 0) {
26215 VERROR_INT("xmlSchemaValidatorPopElem",
26216 "calling xmlSchemaVCheckCVCSimpleType()");
26217 goto internal_error;
26218 }
26219 goto end_elem;
26220 }
26221
26222default_psvi:
26223 /*
26224 * PSVI: Create a text node on the instance element.
26225 */
26226 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26227 (inode->node != NULL)) {
26228 xmlNodePtr textChild;
26229 xmlChar *normValue;
26230 /*
26231 * VAL TODO: Normalize the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000026232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026233 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26234 inode->decl->value);
26235 if (normValue != NULL) {
26236 textChild = xmlNewText(BAD_CAST normValue);
26237 xmlFree(normValue);
26238 } else
26239 textChild = xmlNewText(inode->decl->value);
26240 if (textChild == NULL) {
26241 VERROR_INT("xmlSchemaValidatorPopElem",
26242 "calling xmlNewText()");
26243 goto internal_error;
26244 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000026245 xmlAddChild(inode->node, textChild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026246 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026247
26248 } else if (! INODE_NILLED(inode)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026249 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026250 * 5.2.1 The element information item must be `valid` with respect
26251 * to the `actual type definition` as defined by Element Locally
26252 * Valid (Type) ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026253 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026254 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026255 /*
26256 * SPEC (cvc-type) (3.1)
26257 * "If the type definition is a simple type definition, ..."
26258 * (3.1.3) "If clause 3.2 of Element Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026259 * (Element) ($3.3.4) did not apply, then the `normalized value`
26260 * must be `valid` with respect to the type definition as defined
26261 * by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026263 ret = xmlSchemaVCheckINodeDataType(vctxt,
26264 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026265 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026266 /*
26267 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26268 * definition, then the element information item must be
Jan Pokorný761c9e92013-11-29 23:26:27 +010026269 * `valid` with respect to the type definition as per
26270 * Element Locally Valid (Complex Type) ($3.4.4);"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026271 *
26272 * SPEC (cvc-complex-type) (2.2)
Daniel Veillarddee23482008-04-11 12:58:43 +000026273 * "If the {content type} is a simple type definition, ...
Jan Pokorný761c9e92013-11-29 23:26:27 +010026274 * the `normalized value` of the element information item is
26275 * `valid` with respect to that simple type definition as
26276 * defined by String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026277 */
26278 ret = xmlSchemaVCheckINodeDataType(vctxt,
26279 inode, inode->typeDef->contentTypeDef, inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026280 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026281 if (ret != 0) {
26282 if (ret < 0) {
26283 VERROR_INT("xmlSchemaValidatorPopElem",
26284 "calling xmlSchemaVCheckCVCSimpleType()");
26285 goto internal_error;
26286 }
26287 goto end_elem;
26288 }
26289 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026290 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026291 * not applied, all of the following must be true:
26292 */
26293 if ((inode->decl->value != NULL) &&
26294 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26295
26296 /*
26297 * TODO: We will need a computed value, when comparison is
26298 * done on computed values.
26299 */
26300 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026301 * 5.2.2.1 The element information item must have no element
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026302 * information item [children].
26303 */
26304 if (inode->flags &
26305 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26306 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26307 VERROR(ret, NULL,
26308 "The content must not containt element nodes since "
26309 "there is a fixed value constraint");
26310 goto end_elem;
26311 } else {
26312 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026313 * 5.2.2.2 The appropriate case among the following must
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026314 * be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000026315 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026316 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026317 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026318 * 5.2.2.2.1 If the {content type} of the `actual type
26319 * definition` is mixed, then the *initial value* of the
Daniel Veillarddee23482008-04-11 12:58:43 +000026320 * item must match the canonical lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026321 * of the {value constraint} value.
26322 *
Daniel Veillarddee23482008-04-11 12:58:43 +000026323 * ... the *initial value* of an element information
26324 * item is the string composed of, in order, the
26325 * [character code] of each character information item in
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026326 * the [children] of that element information item.
Daniel Veillarddee23482008-04-11 12:58:43 +000026327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026328 if (! xmlStrEqual(inode->value, inode->decl->value)){
Daniel Veillarddee23482008-04-11 12:58:43 +000026329 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026330 * VAL TODO: Report invalid & expected values as well.
26331 * VAL TODO: Implement the canonical stuff.
26332 */
26333 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000026334 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026335 ret, NULL, NULL,
26336 "The initial value '%s' does not match the fixed "
26337 "value constraint '%s'",
26338 inode->value, inode->decl->value);
26339 goto end_elem;
26340 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026341 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026342 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026343 * 5.2.2.2.2 If the {content type} of the `actual type
26344 * definition` is a simple type definition, then the
Daniel Veillarddee23482008-04-11 12:58:43 +000026345 * *actual value* of the item must match the canonical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026346 * lexical representation of the {value constraint} value.
26347 */
26348 /*
26349 * VAL TODO: *actual value* is the normalized value, impl.
26350 * this.
26351 * VAL TODO: Report invalid & expected values as well.
26352 * VAL TODO: Implement a comparison with the computed values.
26353 */
26354 if (! xmlStrEqual(inode->value,
26355 inode->decl->value)) {
26356 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026357 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026358 ret, NULL, NULL,
26359 "The actual value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000026360 "value constraint '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026361 inode->value,
26362 inode->decl->value);
26363 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026364 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026365 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026367 }
26368 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026369
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026370end_elem:
26371 if (vctxt->depth < 0) {
26372 /* TODO: raise error? */
26373 return (0);
26374 }
26375 if (vctxt->depth == vctxt->skipDepth)
26376 vctxt->skipDepth = -1;
26377 /*
26378 * Evaluate the history of XPath state objects.
Daniel Veillarddee23482008-04-11 12:58:43 +000026379 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026380 if (inode->appliedXPath &&
26381 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026382 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026383 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026384 * MAYBE TODO:
Jan Pokorný761c9e92013-11-29 23:26:27 +010026385 * SPEC (6) "The element information item must be `valid` with
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026386 * respect to each of the {identity-constraint definitions} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010026387 * Identity-constraint Satisfied ($3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026388 */
26389 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026390 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26391 * need to be built in any case.
26392 * We will currently build IDC node-tables and bubble them only if
26393 * keyrefs do exist.
26394 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026395
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026396 /*
26397 * Add the current IDC target-nodes to the IDC node-tables.
26398 */
26399 if ((inode->idcMatchers != NULL) &&
26400 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26401 {
26402 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26403 goto internal_error;
26404 }
26405 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026406 * Validate IDC keyrefs.
26407 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026408 if (vctxt->inode->hasKeyrefs)
26409 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26410 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026411 /*
26412 * Merge/free the IDC table.
26413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026414 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026415#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026416 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026417 inode->nsName,
26418 inode->localName,
26419 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026420#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026421 if ((vctxt->depth > 0) &&
26422 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26423 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026424 /*
26425 * Merge the IDC node table with the table of the parent node.
26426 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026427 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26428 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000026429 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026430 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026431 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026432 * Clear the current ielem.
26433 * VAL TODO: Don't free the PSVI IDC tables if they are
26434 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026435 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000026436 xmlSchemaClearElemInfo(vctxt, inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026437 /*
26438 * Skip further processing if we are on the validation root.
26439 */
26440 if (vctxt->depth == 0) {
26441 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026442 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026443 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026444 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026445 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026446 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026447 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026448 if (vctxt->aidcs != NULL) {
26449 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26450 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026451 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026452 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026453 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026454 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026455 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026456 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026457 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026458 }
26459 aidc = aidc->next;
26460 } while (aidc != NULL);
26461 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026462 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026463 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026464 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026465 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26466 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026468 return (ret);
26469
26470internal_error:
26471 vctxt->err = -1;
26472 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026473}
26474
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026475/*
26476* 3.4.4 Complex Type Definition Validation Rules
26477* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26478*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026479static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026480xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026481{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026482 xmlSchemaNodeInfoPtr pielem;
26483 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026484 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026486 if (vctxt->depth <= 0) {
26487 VERROR_INT("xmlSchemaValidateChildElem",
26488 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026489 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026490 }
26491 pielem = vctxt->elemInfos[vctxt->depth -1];
26492 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26493 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026494 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026495 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026497 if (INODE_NILLED(pielem)) {
26498 /*
26499 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26500 */
26501 ACTIVATE_PARENT_ELEM;
26502 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26503 VERROR(ret, NULL,
26504 "Neither character nor element content is allowed, "
26505 "because the element was 'nilled'");
26506 ACTIVATE_ELEM;
26507 goto unexpected_elem;
26508 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026509
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026510 ptype = pielem->typeDef;
26511
26512 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26513 /*
26514 * Workaround for "anyType": we have currently no content model
26515 * assigned for "anyType", so handle it explicitely.
26516 * "anyType" has an unbounded, lax "any" wildcard.
26517 */
26518 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26519 vctxt->inode->localName,
26520 vctxt->inode->nsName);
26521
26522 if (vctxt->inode->decl == NULL) {
26523 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026524 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026525 * Process "xsi:type".
26526 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026528 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26529 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26530 if (iattr != NULL) {
26531 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26532 &(vctxt->inode->typeDef), NULL);
26533 if (ret != 0) {
26534 if (ret == -1) {
26535 VERROR_INT("xmlSchemaValidateChildElem",
26536 "calling xmlSchemaProcessXSIType() to "
26537 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026538 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026540 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026542 } else {
26543 /*
26544 * Fallback to "anyType".
26545 *
26546 * SPEC (cvc-assess-elt)
Jan Pokorný761c9e92013-11-29 23:26:27 +010026547 * "If the item cannot be `strictly assessed`, [...]
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026548 * an element information item's schema validity may be laxly
Jan Pokorný761c9e92013-11-29 23:26:27 +010026549 * assessed if its `context-determined declaration` is not
26550 * skip by `validating` with respect to the `ur-type
26551 * definition` as per Element Locally Valid (Type) ($3.3.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026552 */
26553 vctxt->inode->typeDef =
26554 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026555 }
26556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026557 return (0);
26558 }
26559
26560 switch (ptype->contentType) {
26561 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026562 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026563 * SPEC (2.1) "If the {content type} is empty, then the
26564 * element information item has no character or element
26565 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026567 ACTIVATE_PARENT_ELEM
26568 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26569 VERROR(ret, NULL,
26570 "Element content is not allowed, "
26571 "because the content type is empty");
26572 ACTIVATE_ELEM
26573 goto unexpected_elem;
26574 break;
26575
26576 case XML_SCHEMA_CONTENT_MIXED:
26577 case XML_SCHEMA_CONTENT_ELEMENTS: {
26578 xmlRegExecCtxtPtr regexCtxt;
26579 xmlChar *values[10];
26580 int terminal, nbval = 10, nbneg;
26581
26582 /* VAL TODO: Optimized "anyType" validation.*/
26583
26584 if (ptype->contModel == NULL) {
26585 VERROR_INT("xmlSchemaValidateChildElem",
26586 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026587 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026589 /*
26590 * Safety belf for evaluation if the cont. model was already
26591 * examined to be invalid.
26592 */
26593 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26594 VERROR_INT("xmlSchemaValidateChildElem",
26595 "validating elem, but elem content is already invalid");
26596 return (-1);
26597 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026599 regexCtxt = pielem->regexCtxt;
26600 if (regexCtxt == NULL) {
26601 /*
26602 * Create the regex context.
26603 */
26604 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26605 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26606 vctxt);
26607 if (regexCtxt == NULL) {
26608 VERROR_INT("xmlSchemaValidateChildElem",
26609 "failed to create a regex context");
26610 return (-1);
26611 }
26612 pielem->regexCtxt = regexCtxt;
26613#ifdef DEBUG_AUTOMATA
26614 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26615 pielem->localName);
26616#endif
26617 }
26618
26619 /*
26620 * SPEC (2.4) "If the {content type} is element-only or mixed,
26621 * then the sequence of the element information item's
26622 * element information item [children], if any, taken in
Jan Pokorný761c9e92013-11-29 23:26:27 +010026623 * order, is `valid` with respect to the {content type}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026624 * particle, as defined in Element Sequence Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026625 * (Particle) ($3.9.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026626 */
26627 ret = xmlRegExecPushString2(regexCtxt,
26628 vctxt->inode->localName,
26629 vctxt->inode->nsName,
26630 vctxt->inode);
26631#ifdef DEBUG_AUTOMATA
26632 if (ret < 0)
26633 xmlGenericError(xmlGenericErrorContext,
26634 "AUTOMATON push ERROR for '%s' on '%s'\n",
26635 vctxt->inode->localName, pielem->localName);
26636 else
26637 xmlGenericError(xmlGenericErrorContext,
26638 "AUTOMATON push OK for '%s' on '%s'\n",
26639 vctxt->inode->localName, pielem->localName);
26640#endif
26641 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26642 VERROR_INT("xmlSchemaValidateChildElem",
26643 "calling xmlRegExecPushString2()");
26644 return (-1);
26645 }
26646 if (ret < 0) {
26647 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26648 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026649 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026650 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26651 "This element is not expected",
26652 nbval, nbneg, values);
26653 ret = vctxt->err;
26654 goto unexpected_elem;
26655 } else
26656 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026657 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026658 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026659 case XML_SCHEMA_CONTENT_SIMPLE:
26660 case XML_SCHEMA_CONTENT_BASIC:
26661 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026662 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026663 /*
26664 * SPEC (cvc-complex-type) (2.2)
26665 * "If the {content type} is a simple type definition, then
26666 * the element information item has no element information
26667 * item [children], ..."
26668 */
26669 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26670 VERROR(ret, NULL, "Element content is not allowed, "
26671 "because the content type is a simple type definition");
26672 } else {
26673 /*
26674 * SPEC (cvc-type) (3.1.2) "The element information item must
26675 * have no element information item [children]."
26676 */
26677 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26678 VERROR(ret, NULL, "Element content is not allowed, "
26679 "because the type definition is simple");
26680 }
26681 ACTIVATE_ELEM
26682 ret = vctxt->err;
26683 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026684 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026685
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026686 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026687 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026688 }
26689 return (ret);
26690unexpected_elem:
26691 /*
26692 * Pop this element and set the skipDepth to skip
26693 * all further content of the parent element.
26694 */
26695 vctxt->skipDepth = vctxt->depth;
26696 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26697 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26698 return (ret);
26699}
26700
26701#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26702#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26703#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26704
26705static int
26706xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26707 int nodeType, const xmlChar *value, int len,
26708 int mode, int *consumed)
26709{
26710 /*
26711 * Unfortunately we have to duplicate the text sometimes.
26712 * OPTIMIZE: Maybe we could skip it, if:
26713 * 1. content type is simple
26714 * 2. whitespace is "collapse"
26715 * 3. it consists of whitespace only
26716 *
26717 * Process character content.
26718 */
26719 if (consumed != NULL)
26720 *consumed = 0;
26721 if (INODE_NILLED(vctxt->inode)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026722 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026723 * SPEC cvc-elt (3.3.4 - 3.2.1)
26724 * "The element information item must have no character or
26725 * element information item [children]."
26726 */
26727 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26728 "Neither character nor element content is allowed "
26729 "because the element is 'nilled'");
26730 return (vctxt->err);
26731 }
26732 /*
26733 * SPEC (2.1) "If the {content type} is empty, then the
26734 * element information item has no character or element
26735 * information item [children]."
26736 */
26737 if (vctxt->inode->typeDef->contentType ==
Daniel Veillarddee23482008-04-11 12:58:43 +000026738 XML_SCHEMA_CONTENT_EMPTY) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026739 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26740 "Character content is not allowed, "
26741 "because the content type is empty");
26742 return (vctxt->err);
26743 }
26744
26745 if (vctxt->inode->typeDef->contentType ==
26746 XML_SCHEMA_CONTENT_ELEMENTS) {
26747 if ((nodeType != XML_TEXT_NODE) ||
26748 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026749 /*
26750 * SPEC cvc-complex-type (2.3)
26751 * "If the {content type} is element-only, then the
26752 * element information item has no character information
26753 * item [children] other than those whose [character
26754 * code] is defined as a white space in [XML 1.0 (Second
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026755 * Edition)]."
26756 */
26757 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26758 "Character content other than whitespace is not allowed "
26759 "because the content type is 'element-only'");
26760 return (vctxt->err);
26761 }
26762 return (0);
26763 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026764
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026765 if ((value == NULL) || (value[0] == 0))
26766 return (0);
26767 /*
26768 * Save the value.
26769 * NOTE that even if the content type is *mixed*, we need the
26770 * *initial value* for default/fixed value constraints.
26771 */
26772 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26773 ((vctxt->inode->decl == NULL) ||
26774 (vctxt->inode->decl->value == NULL)))
26775 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000026776
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026777 if (vctxt->inode->value == NULL) {
26778 /*
26779 * Set the value.
26780 */
26781 switch (mode) {
26782 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26783 /*
26784 * When working on a tree.
26785 */
26786 vctxt->inode->value = value;
26787 break;
26788 case XML_SCHEMA_PUSH_TEXT_CREATED:
26789 /*
26790 * When working with the reader.
26791 * The value will be freed by the element info.
26792 */
26793 vctxt->inode->value = value;
26794 if (consumed != NULL)
26795 *consumed = 1;
26796 vctxt->inode->flags |=
26797 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26798 break;
26799 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26800 /*
26801 * When working with SAX.
26802 * The value will be freed by the element info.
26803 */
26804 if (len != -1)
26805 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26806 else
26807 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26808 vctxt->inode->flags |=
26809 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26810 break;
26811 default:
26812 break;
26813 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026814 } else {
26815 if (len < 0)
26816 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026817 /*
26818 * Concat the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000026819 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026820 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026821 vctxt->inode->value = BAD_CAST xmlStrncat(
26822 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026823 } else {
26824 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026825 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026826 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26827 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026828 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026829
26830 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026831}
26832
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026833static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026834xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026835{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026836 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026837
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026838 if ((vctxt->skipDepth != -1) &&
26839 (vctxt->depth >= vctxt->skipDepth)) {
26840 VERROR_INT("xmlSchemaValidateElem",
26841 "in skip-state");
26842 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026843 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026844 if (vctxt->xsiAssemble) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026845 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026846 * We will stop validation if there was an error during
26847 * dynamic schema construction.
26848 * Note that we simply set @skipDepth to 0, this could
26849 * mean that a streaming document via SAX would be
26850 * still read to the end but it won't be validated any more.
26851 * TODO: If we are sure how to stop the validation at once
26852 * for all input scenarios, then this should be changed to
26853 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026854 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026855 ret = xmlSchemaAssembleByXSI(vctxt);
26856 if (ret != 0) {
26857 if (ret == -1)
26858 goto internal_error;
26859 vctxt->skipDepth = 0;
26860 return(ret);
26861 }
Jim Panettac84e8632010-11-03 21:05:18 +010026862 /*
26863 * Augment the IDC definitions for the main schema and all imported ones
26864 * NOTE: main schema is the first in the imported list
26865 */
26866 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026867 }
26868 if (vctxt->depth > 0) {
26869 /*
26870 * Validate this element against the content model
26871 * of the parent.
26872 */
26873 ret = xmlSchemaValidateChildElem(vctxt);
26874 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026875 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026876 VERROR_INT("xmlSchemaValidateElem",
26877 "calling xmlSchemaStreamValidateChildElement()");
26878 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026879 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026880 goto exit;
26881 }
26882 if (vctxt->depth == vctxt->skipDepth)
26883 goto exit;
26884 if ((vctxt->inode->decl == NULL) &&
26885 (vctxt->inode->typeDef == NULL)) {
26886 VERROR_INT("xmlSchemaValidateElem",
26887 "the child element was valid but neither the "
26888 "declaration nor the type was set");
26889 goto internal_error;
26890 }
26891 } else {
26892 /*
26893 * Get the declaration of the validation root.
26894 */
26895 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26896 vctxt->inode->localName,
26897 vctxt->inode->nsName);
26898 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026899 ret = XML_SCHEMAV_CVC_ELT_1;
26900 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026901 "No matching global declaration available "
26902 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026903 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026904 }
26905 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026906
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026907 if (vctxt->inode->decl == NULL)
26908 goto type_validation;
26909
26910 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26911 int skip;
26912 /*
26913 * Wildcards.
26914 */
26915 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26916 if (ret != 0) {
26917 if (ret < 0) {
26918 VERROR_INT("xmlSchemaValidateElem",
26919 "calling xmlSchemaValidateElemWildcard()");
26920 goto internal_error;
26921 }
26922 goto exit;
26923 }
26924 if (skip) {
26925 vctxt->skipDepth = vctxt->depth;
26926 goto exit;
26927 }
26928 /*
26929 * The declaration might be set by the wildcard validation,
26930 * when the processContents is "lax" or "strict".
26931 */
26932 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26933 /*
26934 * Clear the "decl" field to not confuse further processing.
26935 */
26936 vctxt->inode->decl = NULL;
26937 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026938 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026939 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026940 /*
26941 * Validate against the declaration.
26942 */
26943 ret = xmlSchemaValidateElemDecl(vctxt);
26944 if (ret != 0) {
26945 if (ret < 0) {
26946 VERROR_INT("xmlSchemaValidateElem",
26947 "calling xmlSchemaValidateElemDecl()");
26948 goto internal_error;
26949 }
26950 goto exit;
26951 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026952 /*
26953 * Validate against the type definition.
26954 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026955type_validation:
26956
26957 if (vctxt->inode->typeDef == NULL) {
26958 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26959 ret = XML_SCHEMAV_CVC_TYPE_1;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080026960 VERROR(ret, NULL,
26961 "The type definition is absent");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026962 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000026963 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026964 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26965 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26966 ret = XML_SCHEMAV_CVC_TYPE_2;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080026967 VERROR(ret, NULL,
26968 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026969 goto exit;
26970 }
26971 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026972 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026973 * during validation against the declaration. This must be done
26974 * _before_ attribute validation.
26975 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026976 if (vctxt->xpathStates != NULL) {
26977 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026978 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026979 if (ret == -1) {
26980 VERROR_INT("xmlSchemaValidateElem",
26981 "calling xmlSchemaXPathEvaluate()");
26982 goto internal_error;
26983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026984 }
26985 /*
26986 * Validate attributes.
26987 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026988 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026989 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026990 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026991
26992 ret = xmlSchemaVAttributesComplex(vctxt);
26993 }
26994 } else if (vctxt->nbAttrInfos != 0) {
26995
26996 ret = xmlSchemaVAttributesSimple(vctxt);
26997 }
26998 /*
26999 * Clear registered attributes.
27000 */
27001 if (vctxt->nbAttrInfos != 0)
27002 xmlSchemaClearAttrInfos(vctxt);
27003 if (ret == -1) {
27004 VERROR_INT("xmlSchemaValidateElem",
27005 "calling attributes validation");
27006 goto internal_error;
27007 }
27008 /*
27009 * Don't return an error if attributes are invalid on purpose.
27010 */
27011 ret = 0;
27012
27013exit:
27014 if (ret != 0)
27015 vctxt->skipDepth = vctxt->depth;
27016 return (ret);
27017internal_error:
27018 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027019}
27020
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027021#ifdef XML_SCHEMA_READER_ENABLED
27022static int
27023xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027024{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027025 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27026 int depth, nodeType, ret = 0, consumed;
27027 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027028
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027029 vctxt->depth = -1;
27030 ret = xmlTextReaderRead(vctxt->reader);
27031 /*
27032 * Move to the document element.
27033 */
27034 while (ret == 1) {
27035 nodeType = xmlTextReaderNodeType(vctxt->reader);
27036 if (nodeType == XML_ELEMENT_NODE)
27037 goto root_found;
27038 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027040 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027041
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027042root_found:
27043
27044 do {
27045 depth = xmlTextReaderDepth(vctxt->reader);
27046 nodeType = xmlTextReaderNodeType(vctxt->reader);
27047
27048 if (nodeType == XML_ELEMENT_NODE) {
Daniel Veillarddee23482008-04-11 12:58:43 +000027049
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027050 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027051 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27052 VERROR_INT("xmlSchemaVReaderWalk",
27053 "calling xmlSchemaValidatorPushElem()");
27054 goto internal_error;
27055 }
27056 ielem = vctxt->inode;
27057 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27058 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27059 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27060 /*
27061 * Is the element empty?
27062 */
27063 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27064 if (ret == -1) {
27065 VERROR_INT("xmlSchemaVReaderWalk",
27066 "calling xmlTextReaderIsEmptyElement()");
27067 goto internal_error;
27068 }
27069 if (ret) {
27070 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27071 }
27072 /*
27073 * Register attributes.
27074 */
27075 vctxt->nbAttrInfos = 0;
27076 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27077 if (ret == -1) {
27078 VERROR_INT("xmlSchemaVReaderWalk",
27079 "calling xmlTextReaderMoveToFirstAttribute()");
27080 goto internal_error;
27081 }
27082 if (ret == 1) {
27083 do {
27084 /*
27085 * VAL TODO: How do we know that the reader works on a
27086 * node tree, to be able to pass a node here?
27087 */
27088 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27089 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27090 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27091 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27092
27093 VERROR_INT("xmlSchemaVReaderWalk",
27094 "calling xmlSchemaValidatorPushAttribute()");
27095 goto internal_error;
27096 }
27097 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27098 if (ret == -1) {
27099 VERROR_INT("xmlSchemaVReaderWalk",
27100 "calling xmlTextReaderMoveToFirstAttribute()");
27101 goto internal_error;
27102 }
27103 } while (ret == 1);
27104 /*
27105 * Back to element position.
27106 */
27107 ret = xmlTextReaderMoveToElement(vctxt->reader);
27108 if (ret == -1) {
27109 VERROR_INT("xmlSchemaVReaderWalk",
27110 "calling xmlTextReaderMoveToElement()");
27111 goto internal_error;
27112 }
27113 }
27114 /*
27115 * Validate the element.
27116 */
27117 ret= xmlSchemaValidateElem(vctxt);
27118 if (ret != 0) {
27119 if (ret == -1) {
27120 VERROR_INT("xmlSchemaVReaderWalk",
27121 "calling xmlSchemaValidateElem()");
27122 goto internal_error;
27123 }
27124 goto exit;
27125 }
27126 if (vctxt->depth == vctxt->skipDepth) {
27127 int curDepth;
27128 /*
27129 * Skip all content.
27130 */
27131 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27132 ret = xmlTextReaderRead(vctxt->reader);
27133 curDepth = xmlTextReaderDepth(vctxt->reader);
27134 while ((ret == 1) && (curDepth != depth)) {
27135 ret = xmlTextReaderRead(vctxt->reader);
27136 curDepth = xmlTextReaderDepth(vctxt->reader);
27137 }
27138 if (ret < 0) {
27139 /*
27140 * VAL TODO: A reader error occured; what to do here?
27141 */
27142 ret = 1;
27143 goto exit;
27144 }
27145 }
27146 goto leave_elem;
27147 }
27148 /*
27149 * READER VAL TODO: Is an END_ELEM really never called
27150 * if the elem is empty?
27151 */
27152 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27153 goto leave_elem;
27154 } else if (nodeType == END_ELEM) {
27155 /*
27156 * Process END of element.
27157 */
27158leave_elem:
27159 ret = xmlSchemaValidatorPopElem(vctxt);
27160 if (ret != 0) {
27161 if (ret < 0) {
27162 VERROR_INT("xmlSchemaVReaderWalk",
27163 "calling xmlSchemaValidatorPopElem()");
27164 goto internal_error;
27165 }
27166 goto exit;
27167 }
27168 if (vctxt->depth >= 0)
27169 ielem = vctxt->inode;
27170 else
27171 ielem = NULL;
27172 } else if ((nodeType == XML_TEXT_NODE) ||
27173 (nodeType == XML_CDATA_SECTION_NODE) ||
27174 (nodeType == WHTSP) ||
27175 (nodeType == SIGN_WHTSP)) {
27176 /*
27177 * Process character content.
27178 */
27179 xmlChar *value;
27180
27181 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27182 nodeType = XML_TEXT_NODE;
27183
27184 value = xmlTextReaderValue(vctxt->reader);
27185 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27186 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27187 if (! consumed)
27188 xmlFree(value);
27189 if (ret == -1) {
27190 VERROR_INT("xmlSchemaVReaderWalk",
27191 "calling xmlSchemaVPushText()");
27192 goto internal_error;
27193 }
27194 } else if ((nodeType == XML_ENTITY_NODE) ||
27195 (nodeType == XML_ENTITY_REF_NODE)) {
27196 /*
27197 * VAL TODO: What to do with entities?
27198 */
27199 TODO
27200 }
27201 /*
27202 * Read next node.
27203 */
27204 ret = xmlTextReaderRead(vctxt->reader);
27205 } while (ret == 1);
27206
27207exit:
27208 return (ret);
27209internal_error:
27210 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027211}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027212#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000027213
27214/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027215 * *
27216 * SAX validation handlers *
27217 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027218 ************************************************************************/
27219
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027220/*
27221* Process text content.
27222*/
27223static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027224xmlSchemaSAXHandleText(void *ctx,
27225 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027226 int len)
27227{
27228 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27229
27230 if (vctxt->depth < 0)
27231 return;
27232 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27233 return;
27234 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27235 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27236 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27237 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27238 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27239 "calling xmlSchemaVPushText()");
27240 vctxt->err = -1;
27241 xmlStopParser(vctxt->parserCtxt);
27242 }
27243}
27244
27245/*
27246* Process CDATA content.
27247*/
27248static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027249xmlSchemaSAXHandleCDataSection(void *ctx,
27250 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027251 int len)
Daniel Veillarddee23482008-04-11 12:58:43 +000027252{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027253 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27254
27255 if (vctxt->depth < 0)
27256 return;
27257 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27258 return;
27259 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27260 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27261 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27262 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27263 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27264 "calling xmlSchemaVPushText()");
27265 vctxt->err = -1;
27266 xmlStopParser(vctxt->parserCtxt);
27267 }
27268}
27269
27270static void
27271xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27272 const xmlChar * name ATTRIBUTE_UNUSED)
27273{
27274 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27275
27276 if (vctxt->depth < 0)
27277 return;
27278 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27279 return;
27280 /* SAX VAL TODO: What to do here? */
27281 TODO
27282}
27283
27284static void
27285xmlSchemaSAXHandleStartElementNs(void *ctx,
Daniel Veillarddee23482008-04-11 12:58:43 +000027286 const xmlChar * localname,
27287 const xmlChar * prefix ATTRIBUTE_UNUSED,
27288 const xmlChar * URI,
27289 int nb_namespaces,
27290 const xmlChar ** namespaces,
27291 int nb_attributes,
27292 int nb_defaulted ATTRIBUTE_UNUSED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027293 const xmlChar ** attributes)
Daniel Veillarddee23482008-04-11 12:58:43 +000027294{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027295 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27296 int ret;
27297 xmlSchemaNodeInfoPtr ielem;
27298 int i, j;
Daniel Veillarddee23482008-04-11 12:58:43 +000027299
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027300 /*
27301 * SAX VAL TODO: What to do with nb_defaulted?
27302 */
27303 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027304 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027305 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027306 vctxt->depth++;
27307 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027308 return;
27309 /*
27310 * Push the element.
27311 */
27312 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27313 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27314 "calling xmlSchemaValidatorPushElem()");
27315 goto internal_error;
27316 }
27317 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027318 /*
27319 * TODO: Is this OK?
27320 */
27321 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027322 ielem->localName = localname;
27323 ielem->nsName = URI;
27324 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27325 /*
27326 * Register namespaces on the elem info.
Daniel Veillarddee23482008-04-11 12:58:43 +000027327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027328 if (nb_namespaces != 0) {
27329 /*
27330 * Although the parser builds its own namespace list,
27331 * we have no access to it, so we'll use an own one.
27332 */
Daniel Veillarddee23482008-04-11 12:58:43 +000027333 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027334 /*
27335 * Store prefix and namespace name.
Daniel Veillarddee23482008-04-11 12:58:43 +000027336 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027337 if (ielem->nsBindings == NULL) {
27338 ielem->nsBindings =
27339 (const xmlChar **) xmlMalloc(10 *
27340 sizeof(const xmlChar *));
27341 if (ielem->nsBindings == NULL) {
27342 xmlSchemaVErrMemory(vctxt,
27343 "allocating namespace bindings for SAX validation",
27344 NULL);
27345 goto internal_error;
27346 }
27347 ielem->nbNsBindings = 0;
27348 ielem->sizeNsBindings = 5;
27349 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27350 ielem->sizeNsBindings *= 2;
27351 ielem->nsBindings =
27352 (const xmlChar **) xmlRealloc(
27353 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027354 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027355 if (ielem->nsBindings == NULL) {
27356 xmlSchemaVErrMemory(vctxt,
27357 "re-allocating namespace bindings for SAX validation",
27358 NULL);
27359 goto internal_error;
27360 }
27361 }
27362
27363 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27364 if (namespaces[j+1][0] == 0) {
27365 /*
27366 * Handle xmlns="".
27367 */
27368 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27369 } else
27370 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27371 namespaces[j+1];
Daniel Veillarddee23482008-04-11 12:58:43 +000027372 ielem->nbNsBindings++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027373 }
27374 }
27375 /*
27376 * Register attributes.
27377 * SAX VAL TODO: We are not adding namespace declaration
27378 * attributes yet.
27379 */
27380 if (nb_attributes != 0) {
27381 xmlChar *value;
27382
27383 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27384 /*
Alex Henrief6599c52016-05-02 22:29:59 -060027385 * Duplicate the value, changing any &#38; to a literal ampersand.
27386 *
27387 * libxml2 differs from normal SAX here in that it escapes all ampersands
27388 * as &#38; instead of delivering the raw converted string. Changing the
27389 * behavior at this point would break applications that use this API, so
27390 * we are forced to work around it. There is no danger of accidentally
27391 * decoding some entity other than &#38; in this step because without
27392 * unescaped ampersands there can be no other entities in the string.
Daniel Veillarddee23482008-04-11 12:58:43 +000027393 */
Alex Henrief6599c52016-05-02 22:29:59 -060027394 value = xmlStringLenDecodeEntities(vctxt->parserCtxt, attributes[j+3],
27395 attributes[j+4] - attributes[j+3], XML_SUBSTITUTE_REF, 0, 0, 0);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027396 /*
27397 * TODO: Set the node line.
27398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027399 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027400 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027401 value, 1);
27402 if (ret == -1) {
27403 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27404 "calling xmlSchemaValidatorPushAttribute()");
27405 goto internal_error;
27406 }
27407 }
27408 }
27409 /*
27410 * Validate the element.
27411 */
27412 ret = xmlSchemaValidateElem(vctxt);
27413 if (ret != 0) {
27414 if (ret == -1) {
27415 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27416 "calling xmlSchemaValidateElem()");
27417 goto internal_error;
27418 }
27419 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000027420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027421
27422exit:
27423 return;
27424internal_error:
27425 vctxt->err = -1;
27426 xmlStopParser(vctxt->parserCtxt);
27427 return;
27428}
27429
27430static void
27431xmlSchemaSAXHandleEndElementNs(void *ctx,
27432 const xmlChar * localname ATTRIBUTE_UNUSED,
27433 const xmlChar * prefix ATTRIBUTE_UNUSED,
27434 const xmlChar * URI ATTRIBUTE_UNUSED)
27435{
27436 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27437 int res;
27438
27439 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027440 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027441 */
27442 if (vctxt->skipDepth != -1) {
27443 if (vctxt->depth > vctxt->skipDepth) {
27444 vctxt->depth--;
27445 return;
27446 } else
27447 vctxt->skipDepth = -1;
27448 }
27449 /*
27450 * SAX VAL TODO: Just a temporary check.
27451 */
27452 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27453 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27454 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27455 "elem pop mismatch");
27456 }
27457 res = xmlSchemaValidatorPopElem(vctxt);
27458 if (res != 0) {
27459 if (res < 0) {
27460 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27461 "calling xmlSchemaValidatorPopElem()");
27462 goto internal_error;
27463 }
27464 goto exit;
27465 }
27466exit:
27467 return;
27468internal_error:
27469 vctxt->err = -1;
27470 xmlStopParser(vctxt->parserCtxt);
27471 return;
27472}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027473
Daniel Veillard4255d502002-04-16 15:50:10 +000027474/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027475 * *
27476 * Validation interfaces *
27477 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027478 ************************************************************************/
27479
27480/**
27481 * xmlSchemaNewValidCtxt:
27482 * @schema: a precompiled XML Schemas
27483 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027484 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027485 *
27486 * Returns the validation context or NULL in case of error
27487 */
27488xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027489xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27490{
Daniel Veillard4255d502002-04-16 15:50:10 +000027491 xmlSchemaValidCtxtPtr ret;
27492
27493 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27494 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027495 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027496 return (NULL);
27497 }
27498 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027499 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027500 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027501 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027502 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027503 return (ret);
27504}
27505
27506/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027507 * xmlSchemaValidateSetFilename:
Daniel Veillardef4526a2012-08-15 09:14:31 +080027508 * @vctxt: the schema validation context
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027509 * @filename: the file name
27510 *
27511 * Workaround to provide file error reporting information when this is
27512 * not provided by current APIs
27513 */
27514void
27515xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27516 if (vctxt == NULL)
27517 return;
27518 if (vctxt->filename != NULL)
27519 xmlFree(vctxt->filename);
27520 if (filename != NULL)
27521 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27522 else
27523 vctxt->filename = NULL;
27524}
27525
27526/**
27527 * xmlSchemaClearValidCtxt:
27528 * @vctxt: the schema validation context
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027529 *
27530 * Free the resources associated to the schema validation context;
27531 * leaves some fields alive intended for reuse of the context.
27532 */
27533static void
27534xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27535{
27536 if (vctxt == NULL)
27537 return;
27538
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027539 /*
27540 * TODO: Should we clear the flags?
27541 * Might be problematic if one reuses the context
27542 * and assumes that the options remain the same.
27543 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027544 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027545 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027546 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027547#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027548 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027549#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000027550 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027551
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027552 if (vctxt->value != NULL) {
27553 xmlSchemaFreeValue(vctxt->value);
27554 vctxt->value = NULL;
27555 }
27556 /*
27557 * Augmented IDC information.
27558 */
27559 if (vctxt->aidcs != NULL) {
27560 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27561 do {
27562 next = cur->next;
27563 xmlFree(cur);
27564 cur = next;
27565 } while (cur != NULL);
27566 vctxt->aidcs = NULL;
27567 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027568 if (vctxt->idcMatcherCache != NULL) {
27569 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27570
27571 while (matcher) {
27572 tmp = matcher;
27573 matcher = matcher->nextCached;
27574 xmlSchemaIDCFreeMatcherList(tmp);
27575 }
27576 vctxt->idcMatcherCache = NULL;
27577 }
27578
27579
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027580 if (vctxt->idcNodes != NULL) {
27581 int i;
27582 xmlSchemaPSVIIDCNodePtr item;
27583
27584 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027585 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027586 xmlFree(item->keys);
27587 xmlFree(item);
27588 }
27589 xmlFree(vctxt->idcNodes);
27590 vctxt->idcNodes = NULL;
Daniel Veillard1131e112006-08-07 11:02:54 +000027591 vctxt->nbIdcNodes = 0;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027592 vctxt->sizeIdcNodes = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027593 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027594 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027595 * Note that we won't delete the XPath state pool here.
27596 */
27597 if (vctxt->xpathStates != NULL) {
27598 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27599 vctxt->xpathStates = NULL;
27600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027601 /*
27602 * Attribute info.
27603 */
27604 if (vctxt->nbAttrInfos != 0) {
27605 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027606 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027607 /*
27608 * Element info.
27609 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027610 if (vctxt->elemInfos != NULL) {
27611 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027612 xmlSchemaNodeInfoPtr ei;
27613
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027614 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027615 ei = vctxt->elemInfos[i];
27616 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027617 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027618 xmlSchemaClearElemInfo(vctxt, ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027619 }
Daniel Veillarddee23482008-04-11 12:58:43 +000027620 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027621 xmlSchemaItemListClear(vctxt->nodeQNames);
27622 /* Recreate the dict. */
27623 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027624 /*
27625 * TODO: Is is save to recreate it? Do we have a scenario
27626 * where the user provides the dict?
27627 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027628 vctxt->dict = xmlDictCreate();
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027629
27630 if (vctxt->filename != NULL) {
27631 xmlFree(vctxt->filename);
27632 vctxt->filename = NULL;
27633 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027634}
27635
27636/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027637 * xmlSchemaFreeValidCtxt:
27638 * @ctxt: the schema validation context
27639 *
27640 * Free the resources associated to the schema validation context
27641 */
27642void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027643xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27644{
Daniel Veillard4255d502002-04-16 15:50:10 +000027645 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027646 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027647 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027648 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027649 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027650 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027651 if (ctxt->idcNodes != NULL) {
27652 int i;
27653 xmlSchemaPSVIIDCNodePtr item;
27654
27655 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027656 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027657 xmlFree(item->keys);
27658 xmlFree(item);
27659 }
27660 xmlFree(ctxt->idcNodes);
27661 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027662 if (ctxt->idcKeys != NULL) {
27663 int i;
27664 for (i = 0; i < ctxt->nbIdcKeys; i++)
27665 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27666 xmlFree(ctxt->idcKeys);
27667 }
27668
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027669 if (ctxt->xpathStates != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027670 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027671 ctxt->xpathStates = NULL;
27672 }
27673 if (ctxt->xpathStatePool != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027674 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027675 ctxt->xpathStatePool = NULL;
27676 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027677
27678 /*
27679 * Augmented IDC information.
27680 */
27681 if (ctxt->aidcs != NULL) {
27682 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27683 do {
27684 next = cur->next;
27685 xmlFree(cur);
27686 cur = next;
27687 } while (cur != NULL);
27688 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027689 if (ctxt->attrInfos != NULL) {
27690 int i;
27691 xmlSchemaAttrInfoPtr attr;
27692
27693 /* Just a paranoid call to the cleanup. */
27694 if (ctxt->nbAttrInfos != 0)
27695 xmlSchemaClearAttrInfos(ctxt);
27696 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27697 attr = ctxt->attrInfos[i];
27698 xmlFree(attr);
27699 }
27700 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027701 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027702 if (ctxt->elemInfos != NULL) {
27703 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027704 xmlSchemaNodeInfoPtr ei;
27705
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027706 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027707 ei = ctxt->elemInfos[i];
27708 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027709 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027710 xmlSchemaClearElemInfo(ctxt, ei);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027711 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027712 }
27713 xmlFree(ctxt->elemInfos);
27714 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027715 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027716 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027717 if (ctxt->dict != NULL)
27718 xmlDictFree(ctxt->dict);
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027719 if (ctxt->filename != NULL)
27720 xmlFree(ctxt->filename);
Daniel Veillard4255d502002-04-16 15:50:10 +000027721 xmlFree(ctxt);
27722}
27723
27724/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027725 * xmlSchemaIsValid:
27726 * @ctxt: the schema validation context
27727 *
27728 * Check if any error was detected during validation.
Daniel Veillarddee23482008-04-11 12:58:43 +000027729 *
Daniel Veillardf10ae122005-07-10 19:03:16 +000027730 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27731 * of internal error.
27732 */
27733int
27734xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27735{
27736 if (ctxt == NULL)
27737 return(-1);
27738 return(ctxt->err == 0);
27739}
27740
27741/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027742 * xmlSchemaSetValidErrors:
27743 * @ctxt: a schema validation context
27744 * @err: the error function
27745 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027746 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027747 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027748 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027749 */
27750void
27751xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027752 xmlSchemaValidityErrorFunc err,
27753 xmlSchemaValidityWarningFunc warn, void *ctx)
27754{
Daniel Veillard4255d502002-04-16 15:50:10 +000027755 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027756 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027757 ctxt->error = err;
27758 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027759 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027760 if (ctxt->pctxt != NULL)
27761 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027762}
27763
27764/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027765 * xmlSchemaSetValidStructuredErrors:
27766 * @ctxt: a schema validation context
27767 * @serror: the structured error function
27768 * @ctx: the functions context
27769 *
27770 * Set the structured error callback
27771 */
27772void
27773xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027774 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027775{
27776 if (ctxt == NULL)
27777 return;
27778 ctxt->serror = serror;
27779 ctxt->error = NULL;
27780 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027781 ctxt->errCtxt = ctx;
27782 if (ctxt->pctxt != NULL)
27783 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027784}
27785
27786/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027787 * xmlSchemaGetValidErrors:
Daniel Veillarddee23482008-04-11 12:58:43 +000027788 * @ctxt: a XML-Schema validation context
Daniel Veillard259f0df2004-08-18 09:13:18 +000027789 * @err: the error function result
27790 * @warn: the warning function result
27791 * @ctx: the functions context result
27792 *
27793 * Get the error and warning callback informations
27794 *
27795 * Returns -1 in case of error and 0 otherwise
27796 */
27797int
27798xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027799 xmlSchemaValidityErrorFunc * err,
27800 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027801{
27802 if (ctxt == NULL)
27803 return (-1);
27804 if (err != NULL)
27805 *err = ctxt->error;
27806 if (warn != NULL)
27807 *warn = ctxt->warning;
27808 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027809 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027810 return (0);
27811}
27812
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027813
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027814/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027815 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027816 * @ctxt: a schema validation context
27817 * @options: a combination of xmlSchemaValidOption
27818 *
27819 * Sets the options to be used during the validation.
27820 *
27821 * Returns 0 in case of success, -1 in case of an
27822 * API error.
27823 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027824int
27825xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27826 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027827
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027828{
27829 int i;
27830
27831 if (ctxt == NULL)
27832 return (-1);
27833 /*
27834 * WARNING: Change the start value if adding to the
27835 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027836 * TODO: Is there an other, more easy to maintain,
27837 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027838 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027839 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027840 if (options & 1<<i)
27841 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027842 }
27843 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027844 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027845}
27846
27847/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027848 * xmlSchemaValidCtxtGetOptions:
Daniel Veillarddee23482008-04-11 12:58:43 +000027849 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027850 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027851 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027852 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027853 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027854 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027855int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027856xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027857
27858{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027859 if (ctxt == NULL)
27860 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027861 else
27862 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027863}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027865static int
27866xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27867{
27868 xmlAttrPtr attr;
27869 int ret = 0;
27870 xmlSchemaNodeInfoPtr ielem = NULL;
27871 xmlNodePtr node, valRoot;
27872 const xmlChar *nsName;
27873
27874 /* DOC VAL TODO: Move this to the start function. */
Csaba László1f6c42c2013-03-18 15:30:00 +080027875 if (vctxt->validationRoot != NULL)
27876 valRoot = vctxt->validationRoot;
27877 else
27878 valRoot = xmlDocGetRootElement(vctxt->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027879 if (valRoot == NULL) {
27880 /* VAL TODO: Error code? */
27881 VERROR(1, NULL, "The document has no document element");
27882 return (1);
27883 }
27884 vctxt->depth = -1;
27885 vctxt->validationRoot = valRoot;
27886 node = valRoot;
27887 while (node != NULL) {
27888 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27889 goto next_sibling;
27890 if (node->type == XML_ELEMENT_NODE) {
27891
27892 /*
27893 * Init the node-info.
27894 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027895 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027896 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27897 goto internal_error;
27898 ielem = vctxt->inode;
27899 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027900 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027901 ielem->localName = node->name;
27902 if (node->ns != NULL)
27903 ielem->nsName = node->ns->href;
27904 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27905 /*
27906 * Register attributes.
27907 * DOC VAL TODO: We do not register namespace declaration
27908 * attributes yet.
27909 */
27910 vctxt->nbAttrInfos = 0;
27911 if (node->properties != NULL) {
27912 attr = node->properties;
27913 do {
27914 if (attr->ns != NULL)
27915 nsName = attr->ns->href;
27916 else
27917 nsName = NULL;
27918 ret = xmlSchemaValidatorPushAttribute(vctxt,
27919 (xmlNodePtr) attr,
Daniel Veillarddee23482008-04-11 12:58:43 +000027920 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027921 * Note that we give it the line number of the
27922 * parent element.
27923 */
27924 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027925 attr->name, nsName, 0,
27926 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27927 if (ret == -1) {
27928 VERROR_INT("xmlSchemaDocWalk",
27929 "calling xmlSchemaValidatorPushAttribute()");
27930 goto internal_error;
27931 }
27932 attr = attr->next;
27933 } while (attr);
27934 }
27935 /*
27936 * Validate the element.
27937 */
27938 ret = xmlSchemaValidateElem(vctxt);
27939 if (ret != 0) {
27940 if (ret == -1) {
27941 VERROR_INT("xmlSchemaDocWalk",
27942 "calling xmlSchemaValidateElem()");
27943 goto internal_error;
27944 }
27945 /*
27946 * Don't stop validation; just skip the content
27947 * of this element.
27948 */
27949 goto leave_node;
27950 }
27951 if ((vctxt->skipDepth != -1) &&
27952 (vctxt->depth >= vctxt->skipDepth))
27953 goto leave_node;
27954 } else if ((node->type == XML_TEXT_NODE) ||
27955 (node->type == XML_CDATA_SECTION_NODE)) {
27956 /*
27957 * Process character content.
27958 */
Daniel Veillard14b56432006-03-09 18:41:40 +000027959 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027960 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27961 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27962 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27963 if (ret < 0) {
27964 VERROR_INT("xmlSchemaVDocWalk",
27965 "calling xmlSchemaVPushText()");
27966 goto internal_error;
27967 }
27968 /*
27969 * DOC VAL TODO: Should we skip further validation of the
27970 * element content here?
27971 */
27972 } else if ((node->type == XML_ENTITY_NODE) ||
27973 (node->type == XML_ENTITY_REF_NODE)) {
27974 /*
27975 * DOC VAL TODO: What to do with entities?
Daniel Veillarddee23482008-04-11 12:58:43 +000027976 */
Kasimier T. Buchcik146a9822006-05-04 17:19:07 +000027977 VERROR_INT("xmlSchemaVDocWalk",
27978 "there is at least one entity reference in the node-tree "
27979 "currently being validated. Processing of entities with "
27980 "this XML Schema processor is not supported (yet). Please "
27981 "substitute entities before validation.");
27982 goto internal_error;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027983 } else {
27984 goto leave_node;
27985 /*
27986 * DOC VAL TODO: XInclude nodes, etc.
27987 */
27988 }
27989 /*
27990 * Walk the doc.
27991 */
27992 if (node->children != NULL) {
27993 node = node->children;
27994 continue;
27995 }
27996leave_node:
27997 if (node->type == XML_ELEMENT_NODE) {
27998 /*
27999 * Leaving the scope of an element.
28000 */
28001 if (node != vctxt->inode->node) {
28002 VERROR_INT("xmlSchemaVDocWalk",
28003 "element position mismatch");
28004 goto internal_error;
28005 }
28006 ret = xmlSchemaValidatorPopElem(vctxt);
28007 if (ret != 0) {
28008 if (ret < 0) {
28009 VERROR_INT("xmlSchemaVDocWalk",
28010 "calling xmlSchemaValidatorPopElem()");
28011 goto internal_error;
28012 }
28013 }
28014 if (node == valRoot)
28015 goto exit;
28016 }
28017next_sibling:
28018 if (node->next != NULL)
28019 node = node->next;
28020 else {
28021 node = node->parent;
28022 goto leave_node;
28023 }
28024 }
28025
28026exit:
28027 return (ret);
28028internal_error:
28029 return (-1);
28030}
28031
28032static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000028033xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028034 /*
28035 * Some initialization.
Daniel Veillarddee23482008-04-11 12:58:43 +000028036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028037 vctxt->err = 0;
28038 vctxt->nberrors = 0;
28039 vctxt->depth = -1;
28040 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028041 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028042 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000028043#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028044 vctxt->createIDCNodeTables = 1;
28045#else
28046 vctxt->createIDCNodeTables = 0;
28047#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028048 /*
28049 * Create a schema + parser if necessary.
28050 */
28051 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028052 xmlSchemaParserCtxtPtr pctxt;
Daniel Veillarddee23482008-04-11 12:58:43 +000028053
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028054 vctxt->xsiAssemble = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028055 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028056 * If not schema was given then we will create a schema
28057 * dynamically using XSI schema locations.
28058 *
28059 * Create the schema parser context.
28060 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028061 if ((vctxt->pctxt == NULL) &&
28062 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28063 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028064 pctxt = vctxt->pctxt;
28065 pctxt->xsiAssemble = 1;
28066 /*
28067 * Create the schema.
28068 */
28069 vctxt->schema = xmlSchemaNewSchema(pctxt);
28070 if (vctxt->schema == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000028071 return (-1);
28072 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028073 * Create the schema construction context.
28074 */
28075 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28076 if (pctxt->constructor == NULL)
28077 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028078 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028079 /*
28080 * Take ownership of the constructor to be able to free it.
28081 */
28082 pctxt->ownsConstructor = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028083 }
28084 /*
28085 * Augment the IDC definitions for the main schema and all imported ones
Daniel Veillard3888f472007-08-23 09:29:03 +000028086 * NOTE: main schema if the first in the imported list
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028087 */
Daniel Veillard3888f472007-08-23 09:29:03 +000028088 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000028089
Daniel Veillardf10ae122005-07-10 19:03:16 +000028090 return(0);
28091}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028092
Daniel Veillardf10ae122005-07-10 19:03:16 +000028093static void
28094xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028095 if (vctxt->xsiAssemble) {
28096 if (vctxt->schema != NULL) {
28097 xmlSchemaFree(vctxt->schema);
28098 vctxt->schema = NULL;
28099 }
28100 }
28101 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028102}
28103
28104static int
28105xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28106{
28107 int ret = 0;
28108
28109 if (xmlSchemaPreRun(vctxt) < 0)
28110 return(-1);
28111
28112 if (vctxt->doc != NULL) {
28113 /*
28114 * Tree validation.
28115 */
28116 ret = xmlSchemaVDocWalk(vctxt);
28117#ifdef LIBXML_READER_ENABLED
28118 } else if (vctxt->reader != NULL) {
28119 /*
28120 * XML Reader validation.
28121 */
28122#ifdef XML_SCHEMA_READER_ENABLED
28123 ret = xmlSchemaVReaderWalk(vctxt);
28124#endif
28125#endif
28126 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28127 /*
28128 * SAX validation.
28129 */
28130 ret = xmlParseDocument(vctxt->parserCtxt);
28131 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028132 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000028133 "no instance to validate");
28134 ret = -1;
28135 }
28136
28137 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028138 if (ret == 0)
28139 ret = vctxt->err;
28140 return (ret);
28141}
28142
28143/**
28144 * xmlSchemaValidateOneElement:
28145 * @ctxt: a schema validation context
28146 * @elem: an element node
28147 *
28148 * Validate a branch of a tree, starting with the given @elem.
28149 *
28150 * Returns 0 if the element and its subtree is valid, a positive error
28151 * code number otherwise and -1 in case of an internal or API error.
28152 */
28153int
28154xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28155{
28156 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28157 return (-1);
28158
28159 if (ctxt->schema == NULL)
28160 return (-1);
28161
28162 ctxt->doc = elem->doc;
28163 ctxt->node = elem;
28164 ctxt->validationRoot = elem;
28165 return(xmlSchemaVStart(ctxt));
28166}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028167
Daniel Veillard259f0df2004-08-18 09:13:18 +000028168/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028169 * xmlSchemaValidateDoc:
28170 * @ctxt: a schema validation context
28171 * @doc: a parsed document tree
28172 *
28173 * Validate a document tree in memory.
28174 *
28175 * Returns 0 if the document is schemas valid, a positive error code
28176 * number otherwise and -1 in case of internal or API error.
28177 */
28178int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028179xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28180{
Daniel Veillard4255d502002-04-16 15:50:10 +000028181 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028182 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000028183
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028184 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028185 ctxt->node = xmlDocGetRootElement(doc);
28186 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028187 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028188 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28189 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028190 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028191 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028192 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028193 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028194 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000028195}
28196
Daniel Veillardcdc82732005-07-08 15:04:06 +000028197
28198/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080028199 * *
28200 * Function and data for SAX streaming API *
28201 * *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028202 ************************************************************************/
28203typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28204typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28205
28206struct _xmlSchemaSplitSAXData {
28207 xmlSAXHandlerPtr user_sax;
28208 void *user_data;
28209 xmlSchemaValidCtxtPtr ctxt;
28210 xmlSAXHandlerPtr schemas_sax;
28211};
28212
Daniel Veillard971771e2005-07-09 17:32:57 +000028213#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28214
28215struct _xmlSchemaSAXPlug {
28216 unsigned int magic;
28217
28218 /* the original callbacks informations */
28219 xmlSAXHandlerPtr *user_sax_ptr;
28220 xmlSAXHandlerPtr user_sax;
28221 void **user_data_ptr;
28222 void *user_data;
28223
28224 /* the block plugged back and validation informations */
28225 xmlSAXHandler schemas_sax;
28226 xmlSchemaValidCtxtPtr ctxt;
28227};
28228
Daniel Veillardcdc82732005-07-08 15:04:06 +000028229/* All those functions just bounces to the user provided SAX handlers */
28230static void
28231internalSubsetSplit(void *ctx, const xmlChar *name,
28232 const xmlChar *ExternalID, const xmlChar *SystemID)
28233{
Daniel Veillard971771e2005-07-09 17:32:57 +000028234 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028235 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28236 (ctxt->user_sax->internalSubset != NULL))
28237 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28238 SystemID);
28239}
28240
28241static int
28242isStandaloneSplit(void *ctx)
28243{
Daniel Veillard971771e2005-07-09 17:32:57 +000028244 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028245 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28246 (ctxt->user_sax->isStandalone != NULL))
28247 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28248 return(0);
28249}
28250
28251static int
28252hasInternalSubsetSplit(void *ctx)
28253{
Daniel Veillard971771e2005-07-09 17:32:57 +000028254 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028255 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28256 (ctxt->user_sax->hasInternalSubset != NULL))
28257 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28258 return(0);
28259}
28260
28261static int
28262hasExternalSubsetSplit(void *ctx)
28263{
Daniel Veillard971771e2005-07-09 17:32:57 +000028264 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028265 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266 (ctxt->user_sax->hasExternalSubset != NULL))
28267 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28268 return(0);
28269}
28270
28271static void
28272externalSubsetSplit(void *ctx, const xmlChar *name,
28273 const xmlChar *ExternalID, const xmlChar *SystemID)
28274{
Daniel Veillard971771e2005-07-09 17:32:57 +000028275 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028276 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
Daniel Veillardb3e45362008-03-26 13:39:31 +000028277 (ctxt->user_sax->externalSubset != NULL))
28278 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028279 SystemID);
28280}
28281
28282static xmlParserInputPtr
28283resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28284{
Daniel Veillard971771e2005-07-09 17:32:57 +000028285 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028286 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28287 (ctxt->user_sax->resolveEntity != NULL))
28288 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28289 systemId));
28290 return(NULL);
28291}
28292
28293static xmlEntityPtr
28294getEntitySplit(void *ctx, const xmlChar *name)
28295{
Daniel Veillard971771e2005-07-09 17:32:57 +000028296 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028297 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28298 (ctxt->user_sax->getEntity != NULL))
28299 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28300 return(NULL);
28301}
28302
28303static xmlEntityPtr
28304getParameterEntitySplit(void *ctx, const xmlChar *name)
28305{
Daniel Veillard971771e2005-07-09 17:32:57 +000028306 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028307 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28308 (ctxt->user_sax->getParameterEntity != NULL))
28309 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28310 return(NULL);
28311}
28312
28313
28314static void
28315entityDeclSplit(void *ctx, const xmlChar *name, int type,
28316 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28317{
Daniel Veillard971771e2005-07-09 17:32:57 +000028318 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028319 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28320 (ctxt->user_sax->entityDecl != NULL))
28321 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28322 systemId, content);
28323}
28324
28325static void
28326attributeDeclSplit(void *ctx, const xmlChar * elem,
28327 const xmlChar * name, int type, int def,
28328 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28329{
Daniel Veillard971771e2005-07-09 17:32:57 +000028330 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028331 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28332 (ctxt->user_sax->attributeDecl != NULL)) {
28333 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28334 def, defaultValue, tree);
28335 } else {
28336 xmlFreeEnumeration(tree);
28337 }
28338}
28339
28340static void
28341elementDeclSplit(void *ctx, const xmlChar *name, int type,
28342 xmlElementContentPtr content)
28343{
Daniel Veillard971771e2005-07-09 17:32:57 +000028344 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028345 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28346 (ctxt->user_sax->elementDecl != NULL))
28347 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28348}
28349
28350static void
28351notationDeclSplit(void *ctx, const xmlChar *name,
28352 const xmlChar *publicId, const xmlChar *systemId)
28353{
Daniel Veillard971771e2005-07-09 17:32:57 +000028354 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028355 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28356 (ctxt->user_sax->notationDecl != NULL))
28357 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28358 systemId);
28359}
28360
28361static void
28362unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28363 const xmlChar *publicId, const xmlChar *systemId,
28364 const xmlChar *notationName)
28365{
Daniel Veillard971771e2005-07-09 17:32:57 +000028366 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028367 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28368 (ctxt->user_sax->unparsedEntityDecl != NULL))
28369 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28370 systemId, notationName);
28371}
28372
28373static void
28374setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28375{
Daniel Veillard971771e2005-07-09 17:32:57 +000028376 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028377 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28378 (ctxt->user_sax->setDocumentLocator != NULL))
28379 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28380}
28381
28382static void
28383startDocumentSplit(void *ctx)
28384{
Daniel Veillard971771e2005-07-09 17:32:57 +000028385 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028386 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28387 (ctxt->user_sax->startDocument != NULL))
28388 ctxt->user_sax->startDocument(ctxt->user_data);
28389}
28390
28391static void
28392endDocumentSplit(void *ctx)
28393{
Daniel Veillard971771e2005-07-09 17:32:57 +000028394 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028395 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28396 (ctxt->user_sax->endDocument != NULL))
28397 ctxt->user_sax->endDocument(ctxt->user_data);
28398}
28399
28400static void
28401processingInstructionSplit(void *ctx, const xmlChar *target,
28402 const xmlChar *data)
28403{
Daniel Veillard971771e2005-07-09 17:32:57 +000028404 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028405 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28406 (ctxt->user_sax->processingInstruction != NULL))
28407 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28408}
28409
28410static void
28411commentSplit(void *ctx, const xmlChar *value)
28412{
Daniel Veillard971771e2005-07-09 17:32:57 +000028413 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028414 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28415 (ctxt->user_sax->comment != NULL))
28416 ctxt->user_sax->comment(ctxt->user_data, value);
28417}
28418
28419/*
28420 * Varargs error callbacks to the user application, harder ...
28421 */
28422
Daniel Veillardffa3c742005-07-21 13:24:09 +000028423static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028424warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028425 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028426 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28427 (ctxt->user_sax->warning != NULL)) {
28428 TODO
28429 }
28430}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028431static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028432errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028433 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028434 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28435 (ctxt->user_sax->error != NULL)) {
28436 TODO
28437 }
28438}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028439static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028440fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028441 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028442 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28443 (ctxt->user_sax->fatalError != NULL)) {
28444 TODO
28445 }
28446}
28447
28448/*
28449 * Those are function where both the user handler and the schemas handler
28450 * need to be called.
28451 */
28452static void
28453charactersSplit(void *ctx, const xmlChar *ch, int len)
28454{
Daniel Veillard971771e2005-07-09 17:32:57 +000028455 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028456 if (ctxt == NULL)
28457 return;
28458 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28459 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28460 if (ctxt->ctxt != NULL)
28461 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28462}
28463
28464static void
28465ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28466{
Daniel Veillard971771e2005-07-09 17:32:57 +000028467 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028468 if (ctxt == NULL)
28469 return;
28470 if ((ctxt->user_sax != NULL) &&
28471 (ctxt->user_sax->ignorableWhitespace != NULL))
28472 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28473 if (ctxt->ctxt != NULL)
28474 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28475}
28476
28477static void
28478cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28479{
Daniel Veillard971771e2005-07-09 17:32:57 +000028480 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028481 if (ctxt == NULL)
28482 return;
28483 if ((ctxt->user_sax != NULL) &&
Daniel Veillard7d0ca5e2008-02-05 08:43:52 +000028484 (ctxt->user_sax->cdataBlock != NULL))
28485 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028486 if (ctxt->ctxt != NULL)
28487 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28488}
28489
28490static void
28491referenceSplit(void *ctx, const xmlChar *name)
28492{
Daniel Veillard971771e2005-07-09 17:32:57 +000028493 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillard14b56432006-03-09 18:41:40 +000028494 if (ctxt == NULL)
28495 return;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028496 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28497 (ctxt->user_sax->reference != NULL))
28498 ctxt->user_sax->reference(ctxt->user_data, name);
28499 if (ctxt->ctxt != NULL)
28500 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28501}
28502
28503static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028504startElementNsSplit(void *ctx, const xmlChar * localname,
28505 const xmlChar * prefix, const xmlChar * URI,
28506 int nb_namespaces, const xmlChar ** namespaces,
28507 int nb_attributes, int nb_defaulted,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028508 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028509 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028510 if (ctxt == NULL)
28511 return;
28512 if ((ctxt->user_sax != NULL) &&
28513 (ctxt->user_sax->startElementNs != NULL))
28514 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28515 URI, nb_namespaces, namespaces,
28516 nb_attributes, nb_defaulted,
28517 attributes);
28518 if (ctxt->ctxt != NULL)
28519 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28520 URI, nb_namespaces, namespaces,
28521 nb_attributes, nb_defaulted,
28522 attributes);
28523}
28524
28525static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028526endElementNsSplit(void *ctx, const xmlChar * localname,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028527 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028528 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028529 if (ctxt == NULL)
28530 return;
28531 if ((ctxt->user_sax != NULL) &&
28532 (ctxt->user_sax->endElementNs != NULL))
28533 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28534 if (ctxt->ctxt != NULL)
28535 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28536}
28537
Daniel Veillard4255d502002-04-16 15:50:10 +000028538/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028539 * xmlSchemaSAXPlug:
28540 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028541 * @sax: a pointer to the original xmlSAXHandlerPtr
28542 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028543 *
28544 * Plug a SAX based validation layer in a SAX parsing event flow.
28545 * The original @saxptr and @dataptr data are replaced by new pointers
28546 * but the calls to the original will be maintained.
28547 *
28548 * Returns a pointer to a data structure needed to unplug the validation layer
28549 * or NULL in case of errors.
28550 */
28551xmlSchemaSAXPlugPtr
28552xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28553 xmlSAXHandlerPtr *sax, void **user_data)
28554{
28555 xmlSchemaSAXPlugPtr ret;
28556 xmlSAXHandlerPtr old_sax;
28557
28558 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28559 return(NULL);
28560
28561 /*
28562 * We only allow to plug into SAX2 event streams
28563 */
28564 old_sax = *sax;
28565 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28566 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000028567 if ((old_sax != NULL) &&
Daniel Veillard971771e2005-07-09 17:32:57 +000028568 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28569 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28570 return(NULL);
28571
28572 /*
28573 * everything seems right allocate the local data needed for that layer
28574 */
28575 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28576 if (ret == NULL) {
28577 return(NULL);
28578 }
28579 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28580 ret->magic = XML_SAX_PLUG_MAGIC;
28581 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28582 ret->ctxt = ctxt;
28583 ret->user_sax_ptr = sax;
28584 ret->user_sax = old_sax;
Daniel Veillarddee23482008-04-11 12:58:43 +000028585 if (old_sax == NULL) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028586 /*
28587 * go direct, no need for the split block and functions.
28588 */
28589 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28590 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28591 /*
28592 * Note that we use the same text-function for both, to prevent
28593 * the parser from testing for ignorable whitespace.
28594 */
28595 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28596 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28597
28598 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28599 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28600
28601 ret->user_data = ctxt;
28602 *user_data = ctxt;
28603 } else {
28604 /*
28605 * for each callback unused by Schemas initialize it to the Split
Daniel Veillarddee23482008-04-11 12:58:43 +000028606 * routine only if non NULL in the user block, this can speed up
Daniel Veillard971771e2005-07-09 17:32:57 +000028607 * things at the SAX level.
28608 */
28609 if (old_sax->internalSubset != NULL)
28610 ret->schemas_sax.internalSubset = internalSubsetSplit;
28611 if (old_sax->isStandalone != NULL)
28612 ret->schemas_sax.isStandalone = isStandaloneSplit;
28613 if (old_sax->hasInternalSubset != NULL)
28614 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28615 if (old_sax->hasExternalSubset != NULL)
28616 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28617 if (old_sax->resolveEntity != NULL)
28618 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28619 if (old_sax->getEntity != NULL)
28620 ret->schemas_sax.getEntity = getEntitySplit;
28621 if (old_sax->entityDecl != NULL)
28622 ret->schemas_sax.entityDecl = entityDeclSplit;
28623 if (old_sax->notationDecl != NULL)
28624 ret->schemas_sax.notationDecl = notationDeclSplit;
28625 if (old_sax->attributeDecl != NULL)
28626 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28627 if (old_sax->elementDecl != NULL)
28628 ret->schemas_sax.elementDecl = elementDeclSplit;
28629 if (old_sax->unparsedEntityDecl != NULL)
28630 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28631 if (old_sax->setDocumentLocator != NULL)
28632 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28633 if (old_sax->startDocument != NULL)
28634 ret->schemas_sax.startDocument = startDocumentSplit;
28635 if (old_sax->endDocument != NULL)
28636 ret->schemas_sax.endDocument = endDocumentSplit;
28637 if (old_sax->processingInstruction != NULL)
28638 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28639 if (old_sax->comment != NULL)
28640 ret->schemas_sax.comment = commentSplit;
28641 if (old_sax->warning != NULL)
28642 ret->schemas_sax.warning = warningSplit;
28643 if (old_sax->error != NULL)
28644 ret->schemas_sax.error = errorSplit;
28645 if (old_sax->fatalError != NULL)
28646 ret->schemas_sax.fatalError = fatalErrorSplit;
28647 if (old_sax->getParameterEntity != NULL)
28648 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28649 if (old_sax->externalSubset != NULL)
28650 ret->schemas_sax.externalSubset = externalSubsetSplit;
28651
28652 /*
28653 * the 6 schemas callback have to go to the splitter functions
28654 * Note that we use the same text-function for ignorableWhitespace
28655 * if possible, to prevent the parser from testing for ignorable
28656 * whitespace.
28657 */
28658 ret->schemas_sax.characters = charactersSplit;
28659 if ((old_sax->ignorableWhitespace != NULL) &&
28660 (old_sax->ignorableWhitespace != old_sax->characters))
28661 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28662 else
28663 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28664 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28665 ret->schemas_sax.reference = referenceSplit;
28666 ret->schemas_sax.startElementNs = startElementNsSplit;
28667 ret->schemas_sax.endElementNs = endElementNsSplit;
28668
28669 ret->user_data_ptr = user_data;
28670 ret->user_data = *user_data;
28671 *user_data = ret;
28672 }
28673
28674 /*
28675 * plug the pointers back.
28676 */
28677 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028678 ctxt->sax = *sax;
28679 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28680 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028681 return(ret);
28682}
28683
28684/**
28685 * xmlSchemaSAXUnplug:
28686 * @plug: a data structure returned by xmlSchemaSAXPlug
28687 *
28688 * Unplug a SAX based validation layer in a SAX parsing event flow.
28689 * The original pointers used in the call are restored.
28690 *
28691 * Returns 0 in case of success and -1 in case of failure.
28692 */
28693int
28694xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28695{
28696 xmlSAXHandlerPtr *sax;
28697 void **user_data;
28698
28699 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28700 return(-1);
28701 plug->magic = 0;
28702
Daniel Veillardf10ae122005-07-10 19:03:16 +000028703 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028704 /* restore the data */
28705 sax = plug->user_sax_ptr;
28706 *sax = plug->user_sax;
28707 if (plug->user_sax != NULL) {
28708 user_data = plug->user_data_ptr;
28709 *user_data = plug->user_data;
28710 }
28711
28712 /* free and return */
28713 xmlFree(plug);
28714 return(0);
28715}
28716
28717/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080028718 * xmlSchemaValidateSetLocator:
28719 * @vctxt: a schema validation context
28720 * @f: the locator function pointer
28721 * @ctxt: the locator context
28722 *
28723 * Allows to set a locator function to the validation context,
28724 * which will be used to provide file and line information since
28725 * those are not provided as part of the SAX validation flow
28726 * Setting @f to NULL disable the locator.
28727 */
28728
28729void
28730xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28731 xmlSchemaValidityLocatorFunc f,
28732 void *ctxt)
28733{
28734 if (vctxt == NULL) return;
28735 vctxt->locFunc = f;
28736 vctxt->locCtxt = ctxt;
28737}
28738
28739/**
28740 * xmlSchemaValidateStreamLocator:
28741 * @ctx: the xmlTextReaderPtr used
28742 * @file: returned file information
28743 * @line: returned line information
28744 *
28745 * Internal locator function for the readers
28746 *
28747 * Returns 0 in case the Schema validation could be (des)activated and
28748 * -1 in case of error.
28749 */
28750static int
28751xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28752 unsigned long *line) {
28753 xmlParserCtxtPtr ctxt;
28754
28755 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28756 return(-1);
28757
28758 if (file != NULL)
28759 *file = NULL;
28760 if (line != NULL)
28761 *line = 0;
28762
28763 ctxt = (xmlParserCtxtPtr) ctx;
28764 if (ctxt->input != NULL) {
28765 if (file != NULL)
28766 *file = ctxt->input->filename;
28767 if (line != NULL)
28768 *line = ctxt->input->line;
28769 return(0);
28770 }
28771 return(-1);
28772}
28773
28774/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028775 * xmlSchemaValidateStream:
28776 * @ctxt: a schema validation context
28777 * @input: the input to use for reading the data
28778 * @enc: an optional encoding information
28779 * @sax: a SAX handler for the resulting events
28780 * @user_data: the context to provide to the SAX handler.
28781 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028782 * Validate an input based on a flow of SAX event from the parser
28783 * and forward the events to the @sax handler with the provided @user_data
28784 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028785 *
28786 * Returns 0 if the document is schemas valid, a positive error code
28787 * number otherwise and -1 in case of internal or API error.
28788 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028789int
Daniel Veillard4255d502002-04-16 15:50:10 +000028790xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028791 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28792 xmlSAXHandlerPtr sax, void *user_data)
28793{
Daniel Veillard971771e2005-07-09 17:32:57 +000028794 xmlSchemaSAXPlugPtr plug = NULL;
28795 xmlSAXHandlerPtr old_sax = NULL;
28796 xmlParserCtxtPtr pctxt = NULL;
28797 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028798 int ret;
28799
Daniel Veillard4255d502002-04-16 15:50:10 +000028800 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028801 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028802
Daniel Veillardcdc82732005-07-08 15:04:06 +000028803 /*
28804 * prepare the parser
28805 */
28806 pctxt = xmlNewParserCtxt();
28807 if (pctxt == NULL)
28808 return (-1);
28809 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028810 pctxt->sax = sax;
28811 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028812#if 0
28813 if (options)
28814 xmlCtxtUseOptions(pctxt, options);
28815#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000028816 pctxt->linenumbers = 1;
Daniel Veillard97fa5b32012-08-14 11:01:07 +080028817 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028818
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028819 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028820 if (inputStream == NULL) {
28821 ret = -1;
28822 goto done;
28823 }
28824 inputPush(pctxt, inputStream);
28825 ctxt->parserCtxt = pctxt;
28826 ctxt->input = input;
28827
28828 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028829 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028830 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028831 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28832 if (plug == NULL) {
28833 ret = -1;
28834 goto done;
28835 }
28836 ctxt->input = input;
28837 ctxt->enc = enc;
28838 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028839 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28840 ret = xmlSchemaVStart(ctxt);
28841
28842 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28843 ret = ctxt->parserCtxt->errNo;
28844 if (ret == 0)
28845 ret = 1;
Daniel Veillard33fe2882008-04-10 08:09:25 +000028846 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028847
28848done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028849 ctxt->parserCtxt = NULL;
28850 ctxt->sax = NULL;
28851 ctxt->input = NULL;
28852 if (plug != NULL) {
28853 xmlSchemaSAXUnplug(plug);
28854 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028855 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028856 if (pctxt != NULL) {
28857 pctxt->sax = old_sax;
28858 xmlFreeParserCtxt(pctxt);
28859 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028860 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028861}
28862
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028863/**
28864 * xmlSchemaValidateFile:
28865 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028866 * @filename: the URI of the instance
28867 * @options: a future set of options, currently unused
28868 *
28869 * Do a schemas validation of the given resource, it will use the
28870 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028871 *
28872 * Returns 0 if the document is valid, a positive error code
28873 * number otherwise and -1 in case of an internal or API error.
28874 */
28875int
28876xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028877 const char * filename,
28878 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028879{
28880 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028881 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028882
28883 if ((ctxt == NULL) || (filename == NULL))
28884 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000028885
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028886 input = xmlParserInputBufferCreateFilename(filename,
28887 XML_CHAR_ENCODING_NONE);
28888 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028889 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028890 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
Daniel Veillarddee23482008-04-11 12:58:43 +000028891 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028892 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028893}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028894
Daniel Veillarddee23482008-04-11 12:58:43 +000028895/**
28896 * xmlSchemaValidCtxtGetParserCtxt:
28897 * @ctxt: a schema validation context
28898 *
28899 * allow access to the parser context of the schema validation context
28900 *
28901 * Returns the parser context of the schema validation context or NULL
28902 * in case of error.
28903 */
28904xmlParserCtxtPtr
28905xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28906{
28907 if (ctxt == NULL)
28908 return(NULL);
28909 return (ctxt->parserCtxt);
28910}
28911
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028912#define bottom_xmlschemas
28913#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028914#endif /* LIBXML_SCHEMAS_ENABLED */