blob: d30ad07be3cadd6ffe8aafed2985a81f070d8885 [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. Buchcik4efd90d2005-06-09 10:32:53 +000083#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000085/* #define DEBUG_IDC */
86
87/* #define DEBUG_IDC_NODE_TABLE */
88
89#ifdef DEBUG_IDC
90 #ifndef DEBUG_IDC_NODE_TABLE
91 #define DEBUG_IDC_NODE_TABLE
92 #endif
93#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. Buchcik27820272005-10-14 14:33:48 +0000101#define ENABLE_IDC_NODE_TABLES
102
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)
110#define TODO \
111 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
188#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
189/*
190* Macros for model groups definitions.
191*/
192#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
193/*
194* Macros for model groups.
195*/
196#define WXS_IS_MODEL_GROUP(i) \
197 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
198 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
199 ((i)->type == XML_SCHEMA_TYPE_ALL))
200
201#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
202/*
203* Macros for schema buckets.
204*/
205#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
206 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
207
208#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
209 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
210
211#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
212
213#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
214/*
215* Macros for complex/simple types.
216*/
217#define WXS_IS_ANYTYPE(i) \
218 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
219 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
220
221#define WXS_IS_COMPLEX(i) \
222 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
223 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
224
225#define WXS_IS_SIMPLE(item) \
226 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
227 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000228 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000229
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000230#define WXS_IS_ANY_SIMPLE_TYPE(i) \
231 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
232 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000233
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000234#define WXS_IS_RESTRICTION(t) \
235 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000236
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000237#define WXS_IS_EXTENSION(t) \
238 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
239
240#define WXS_IS_TYPE_NOT_FIXED(i) \
241 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
242 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
243
244#define WXS_IS_TYPE_NOT_FIXED_1(item) \
245 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000246 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000247/*
248* Macros for exclusively for complex types.
249*/
250#define WXS_HAS_COMPLEX_CONTENT(item) \
251 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
252 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000253 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
254
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000255#define WXS_HAS_SIMPLE_CONTENT(item) \
256 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000257 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
258
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000259#define WXS_HAS_MIXED_CONTENT(item) \
260 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000261
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000262#define WXS_EMPTIABLE(t) \
263 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000264
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000265#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000267#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000269#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
270/*
271* Macros for exclusively for simple types.
272*/
273#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000276
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000277#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000278
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000279#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
280/*
281* Misc parser context macros.
282*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000283#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
284
285#define WXS_HAS_BUCKETS(ctx) \
286( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
287(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
288
289#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
290
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000291#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000292
293#define WXS_SCHEMA(ctx) (ctx)->schema
294
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000295#define WXS_ADD_LOCAL(ctx, item) \
296 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000297
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000298#define WXS_ADD_GLOBAL(ctx, item) \
299 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000300
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000301#define WXS_ADD_PENDING(ctx, item) \
302 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
303/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000304* xmlSchemaItemList macros.
305*/
306#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
307/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000308* Misc macros.
309*/
310#define IS_SCHEMA(node, type) \
311 ((node != NULL) && (node->ns != NULL) && \
312 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
313 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000314
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000315#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000316
317/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000318* Since we put the default/fixed values into the dict, we can
319* use pointer comparison for those values.
320* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000321*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000322#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000323
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000324#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000325
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000326#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000327
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000328#define HFAILURE if (res == -1) goto exit_failure;
329
330#define HERROR if (res != 0) goto exit_error;
331
332#define HSTOP(ctx) if ((ctx)->stop) goto exit;
333/*
334* Some flags used for various schema constraints.
335*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000336#define SUBSET_RESTRICTION 1<<0
337#define SUBSET_EXTENSION 1<<1
338#define SUBSET_SUBSTITUTION 1<<2
339#define SUBSET_LIST 1<<3
340#define SUBSET_UNION 1<<4
341
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000342typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
343typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000344
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000345typedef struct _xmlSchemaItemList xmlSchemaItemList;
346typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000347struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000348 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000349 int nbItems; /* used for dynamic addition of schemata */
350 int sizeItems; /* used for dynamic addition of schemata */
351};
352
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000353#define XML_SCHEMA_CTXT_PARSER 1
354#define XML_SCHEMA_CTXT_VALIDATOR 2
355
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000356typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
357typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
358struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000359 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000360};
361
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000362typedef struct _xmlSchemaBucket xmlSchemaBucket;
363typedef xmlSchemaBucket *xmlSchemaBucketPtr;
364
365#define XML_SCHEMA_SCHEMA_MAIN 0
366#define XML_SCHEMA_SCHEMA_IMPORT 1
367#define XML_SCHEMA_SCHEMA_INCLUDE 2
368#define XML_SCHEMA_SCHEMA_REDEFINE 3
369
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000370/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000371 * xmlSchemaSchemaRelation:
372 *
373 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000374 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000375typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
376typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
377struct _xmlSchemaSchemaRelation {
378 xmlSchemaSchemaRelationPtr next;
379 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
380 const xmlChar *importNamespace;
381 xmlSchemaBucketPtr bucket;
382};
383
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000384#define XML_SCHEMA_BUCKET_MARKED 1<<0
385#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
386
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000387struct _xmlSchemaBucket {
388 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000389 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000390 const xmlChar *schemaLocation;
391 const xmlChar *origTargetNamespace;
392 const xmlChar *targetNamespace;
393 xmlDocPtr doc;
394 xmlSchemaSchemaRelationPtr relations;
395 int located;
396 int parsed;
397 int imported;
398 int preserveDoc;
399 xmlSchemaItemListPtr globals; /* Global components. */
400 xmlSchemaItemListPtr locals; /* Local components. */
401};
402
403/**
404 * xmlSchemaImport:
405 * (extends xmlSchemaBucket)
406 *
407 * Reflects a schema. Holds some information
408 * about the schema and its toplevel components. Duplicate
409 * toplevel components are not checked at this level.
410 */
411typedef struct _xmlSchemaImport xmlSchemaImport;
412typedef xmlSchemaImport *xmlSchemaImportPtr;
413struct _xmlSchemaImport {
414 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000415 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000416 const xmlChar *schemaLocation; /* The URI of the schema document. */
417 /* For chameleon includes, @origTargetNamespace will be NULL */
418 const xmlChar *origTargetNamespace;
419 /*
420 * For chameleon includes, @targetNamespace will be the
421 * targetNamespace of the including schema.
422 */
423 const xmlChar *targetNamespace;
424 xmlDocPtr doc; /* The schema node-tree. */
425 /* @relations will hold any included/imported/redefined schemas. */
426 xmlSchemaSchemaRelationPtr relations;
427 int located;
428 int parsed;
429 int imported;
430 int preserveDoc;
431 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000432 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000433 /* The imported schema. */
434 xmlSchemaPtr schema;
435};
436
437/*
438* (extends xmlSchemaBucket)
439*/
440typedef struct _xmlSchemaInclude xmlSchemaInclude;
441typedef xmlSchemaInclude *xmlSchemaIncludePtr;
442struct _xmlSchemaInclude {
443 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000444 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000445 const xmlChar *schemaLocation;
446 const xmlChar *origTargetNamespace;
447 const xmlChar *targetNamespace;
448 xmlDocPtr doc;
449 xmlSchemaSchemaRelationPtr relations;
450 int located;
451 int parsed;
452 int imported;
453 int preserveDoc;
454 xmlSchemaItemListPtr globals; /* Global components. */
455 xmlSchemaItemListPtr locals; /* Local components. */
456
457 /* The owning main or import schema bucket. */
458 xmlSchemaImportPtr ownerImport;
459};
460
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000461/**
462 * xmlSchemaBasicItem:
463 *
464 * The abstract base type for schema components.
465 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000466typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
467typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
468struct _xmlSchemaBasicItem {
469 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000470};
471
472/**
473 * xmlSchemaAnnotItem:
474 *
475 * The abstract base type for annotated schema components.
476 * (Extends xmlSchemaBasicItem)
477 */
478typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
479typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
480struct _xmlSchemaAnnotItem {
481 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000482 xmlSchemaAnnotPtr annot;
483};
484
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000485/**
486 * xmlSchemaTreeItem:
487 *
488 * The abstract base type for tree-like structured schema components.
489 * (Extends xmlSchemaAnnotItem)
490 */
491typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
492typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
493struct _xmlSchemaTreeItem {
494 xmlSchemaTypeType type;
495 xmlSchemaAnnotPtr annot;
496 xmlSchemaTreeItemPtr next;
497 xmlSchemaTreeItemPtr children;
498};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000499
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000500
501#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
502/**
503 * xmlSchemaAttributeUsePtr:
504 *
505 * The abstract base type for tree-like structured schema components.
506 * (Extends xmlSchemaTreeItem)
507 */
508typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
509typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
510struct _xmlSchemaAttributeUse {
511 xmlSchemaTypeType type;
512 xmlSchemaAnnotPtr annot;
513 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
514 /*
515 * The attr. decl. OR a QName-ref. to an attr. decl. OR
516 * a QName-ref. to an attribute group definition.
517 */
518 xmlSchemaAttributePtr attrDecl;
519
520 int flags;
521 xmlNodePtr node;
522 int occurs; /* required, optional */
523 const xmlChar * defValue;
524 xmlSchemaValPtr defVal;
525};
526
527/**
528 * xmlSchemaAttributeUseProhibPtr:
529 *
530 * A helper component to reflect attribute prohibitions.
531 * (Extends xmlSchemaBasicItem)
532 */
533typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
534typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
535struct _xmlSchemaAttributeUseProhib {
536 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
537 xmlNodePtr node;
538 const xmlChar *name;
539 const xmlChar *targetNamespace;
540 int isRef;
541};
542
543/**
544 * xmlSchemaRedef:
545 */
546typedef struct _xmlSchemaRedef xmlSchemaRedef;
547typedef xmlSchemaRedef *xmlSchemaRedefPtr;
548struct _xmlSchemaRedef {
549 xmlSchemaRedefPtr next;
550 xmlSchemaBasicItemPtr item; /* The redefining component. */
551 xmlSchemaBasicItemPtr reference; /* The referencing component. */
552 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
553 const xmlChar *refName; /* The name of the to-be-redefined component. */
554 const xmlChar *refTargetNs; /* The target namespace of the
555 to-be-redefined comp. */
556 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
557};
558
559/**
560 * xmlSchemaConstructionCtxt:
561 */
562typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
563typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
564struct _xmlSchemaConstructionCtxt {
565 xmlSchemaPtr mainSchema; /* The main schema. */
566 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
567 xmlDictPtr dict;
568 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
569 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
570 xmlSchemaBucketPtr bucket; /* The current schema bucket */
571 xmlSchemaItemListPtr pending; /* All Components of all schemas that
572 need to be fixed. */
573 xmlHashTablePtr substGroups;
574 xmlSchemaRedefPtr redefs;
575 xmlSchemaRedefPtr lastRedef;
576};
577
578#define XML_SCHEMAS_PARSE_ERROR 1
579#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
580
581struct _xmlSchemaParserCtxt {
582 int type;
583 void *userData; /* user specific data block */
584 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
585 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
586 xmlSchemaValidError err;
587 int nberrors;
588 xmlStructuredErrorFunc serror;
589
590 xmlSchemaConstructionCtxtPtr constructor;
591 int ownsConstructor; /* TODO: Move this to parser *flags*. */
592
593 /* xmlSchemaPtr topschema; */
594 /* xmlHashTablePtr namespaces; */
595
596 xmlSchemaPtr schema; /* The main schema in use */
597 int counter;
598
599 const xmlChar *URL;
600 xmlDocPtr doc;
601 int preserve; /* Whether the doc should be freed */
602
603 const char *buffer;
604 int size;
605
606 /*
607 * Used to build complex element content models
608 */
609 xmlAutomataPtr am;
610 xmlAutomataStatePtr start;
611 xmlAutomataStatePtr end;
612 xmlAutomataStatePtr state;
613
614 xmlDictPtr dict; /* dictionnary for interned string names */
615 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
616 int options;
617 xmlSchemaValidCtxtPtr vctxt;
618 int isS4S;
619 int isRedefine;
620 int xsiAssemble;
621 int stop; /* If the parser should stop; i.e. a critical error. */
622 const xmlChar *targetNamespace;
623 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
624
625 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
626 int redefCounter; /* Used for redefinitions. */
627 xmlSchemaItemListPtr attrProhibs;
628};
629
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000630/**
631 * xmlSchemaQNameRef:
632 *
633 * A component reference item (not a schema component)
634 * (Extends xmlSchemaBasicItem)
635 */
636typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
637typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
638struct _xmlSchemaQNameRef {
639 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000640 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000641 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000642 const xmlChar *name;
643 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000644 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000645};
646
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000647/**
648 * xmlSchemaParticle:
649 *
650 * A particle component.
651 * (Extends xmlSchemaTreeItem)
652 */
653typedef struct _xmlSchemaParticle xmlSchemaParticle;
654typedef xmlSchemaParticle *xmlSchemaParticlePtr;
655struct _xmlSchemaParticle {
656 xmlSchemaTypeType type;
657 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000658 xmlSchemaTreeItemPtr next; /* next particle */
659 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
660 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
661 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000662 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000663 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000664 xmlNodePtr node;
665};
666
667/**
668 * xmlSchemaModelGroup:
669 *
670 * A model group component.
671 * (Extends xmlSchemaTreeItem)
672 */
673typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
674typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
675struct _xmlSchemaModelGroup {
676 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
677 xmlSchemaAnnotPtr annot;
678 xmlSchemaTreeItemPtr next; /* not used */
679 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
680 xmlNodePtr node;
681};
682
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000683#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000684#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000685/**
686 * xmlSchemaModelGroupDef:
687 *
688 * A model group definition component.
689 * (Extends xmlSchemaTreeItem)
690 */
691typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
692typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
693struct _xmlSchemaModelGroupDef {
694 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
695 xmlSchemaAnnotPtr annot;
696 xmlSchemaTreeItemPtr next; /* not used */
697 xmlSchemaTreeItemPtr children; /* the "model group" */
698 const xmlChar *name;
699 const xmlChar *targetNamespace;
700 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000701 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000702};
703
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000704typedef struct _xmlSchemaIDC xmlSchemaIDC;
705typedef xmlSchemaIDC *xmlSchemaIDCPtr;
706
707/**
708 * xmlSchemaIDCSelect:
709 *
710 * The identity-constraint "field" and "selector" item, holding the
711 * XPath expression.
712 */
713typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
714typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000715struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000716 xmlSchemaIDCSelectPtr next;
717 xmlSchemaIDCPtr idc;
718 int index; /* an index position if significant for IDC key-sequences */
719 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000720 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000721};
722
723/**
724 * xmlSchemaIDC:
725 *
726 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000727 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000728 */
729
730struct _xmlSchemaIDC {
731 xmlSchemaTypeType type;
732 xmlSchemaAnnotPtr annot;
733 xmlSchemaIDCPtr next;
734 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000735 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000736 const xmlChar *targetNamespace;
737 xmlSchemaIDCSelectPtr selector;
738 xmlSchemaIDCSelectPtr fields;
739 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000741};
742
743/**
744 * xmlSchemaIDCAug:
745 *
746 * The augmented IDC information used for validation.
747 */
748typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
749typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
750struct _xmlSchemaIDCAug {
751 xmlSchemaIDCAugPtr next; /* next in a list */
752 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000753 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000754 tables need to be bubbled upwards */
755};
756
757/**
758 * xmlSchemaPSVIIDCKeySequence:
759 *
760 * The key sequence of a node table item.
761 */
762typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
763typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
764struct _xmlSchemaPSVIIDCKey {
765 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000766 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000767};
768
769/**
770 * xmlSchemaPSVIIDCNode:
771 *
772 * The node table item of a node table.
773 */
774typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
775typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
776struct _xmlSchemaPSVIIDCNode {
777 xmlNodePtr node;
778 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000779 int nodeLine;
780 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000781
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000782};
783
784/**
785 * xmlSchemaPSVIIDCBinding:
786 *
787 * The identity-constraint binding item of the [identity-constraint table].
788 */
789typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
790typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
791struct _xmlSchemaPSVIIDCBinding {
792 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
793 xmlSchemaIDCPtr definition; /* the IDC definition */
794 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
795 int nbNodes; /* number of entries in the node table */
796 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000797 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000798};
799
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000800
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000801#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
802#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
803
804#define XPATH_STATE_OBJ_MATCHES -2
805#define XPATH_STATE_OBJ_BLOCKED -3
806
807typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
808typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
809
810/**
811 * xmlSchemaIDCStateObj:
812 *
813 * The state object used to evaluate XPath expressions.
814 */
815typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
816typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
817struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000818 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000819 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000820 int depth; /* depth of creation */
821 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000822 int nbHistory;
823 int sizeHistory;
824 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
825 matcher */
826 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000827 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000828};
829
830#define IDC_MATCHER 0
831
832/**
833 * xmlSchemaIDCMatcher:
834 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000835 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000836 */
837struct _xmlSchemaIDCMatcher {
838 int type;
839 int depth; /* the tree depth at creation time */
840 xmlSchemaIDCMatcherPtr next; /* next in the list */
841 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000842 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000843 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
844 elements */
845 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000846 int targetDepth;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000847 xmlSchemaItemListPtr targets; /* list of target-node
848 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000849};
850
851/*
852* Element info flags.
853*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000854#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
855#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
856#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
857#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
858
859#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
860#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
861#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
862
863#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
864#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
865#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
866#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000867
868/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000869 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000870 *
871 * Holds information of an element node.
872 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000873struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000874 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000875 xmlNodePtr node;
876 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000877 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000878 const xmlChar *nsName;
879 const xmlChar *value;
880 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000881 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000882
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000883 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000884
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000885 int valNeeded;
886 int normVal;
887
888 xmlSchemaElementPtr decl; /* the element/attribute declaration */
889 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000890 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
891 for the scope element*/
892 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
893 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000894 xmlRegExecCtxtPtr regexCtxt;
895
896 const xmlChar **nsBindings; /* Namespace bindings on this element */
897 int nbNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000898 int sizeNsBindings;
899
900 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000901 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000902};
903
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000904#define XML_SCHEMAS_ATTR_UNKNOWN 1
905#define XML_SCHEMAS_ATTR_ASSESSED 2
906#define XML_SCHEMAS_ATTR_PROHIBITED 3
907#define XML_SCHEMAS_ATTR_ERR_MISSING 4
908#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
909#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
910#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
911#define XML_SCHEMAS_ATTR_DEFAULT 8
912#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
913#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
914#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
915#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
916#define XML_SCHEMAS_ATTR_WILD_SKIP 13
917#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
918#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
919#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
920#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000921/*
922* @metaType values of xmlSchemaAttrInfo.
923*/
924#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
926#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
927#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
928#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000929
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000930typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
931typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
932struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000933 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000934 xmlNodePtr node;
935 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000936 const xmlChar *localName;
937 const xmlChar *nsName;
938 const xmlChar *value;
939 xmlSchemaValPtr val; /* the pre-computed value if any */
940 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
941 int flags; /* combination of node info flags */
942
943 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000944 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000945 int state;
946 int metaType;
947 const xmlChar *vcValue; /* the value constraint value */
948 xmlSchemaNodeInfoPtr parent;
949};
950
951
952#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000953/**
954 * xmlSchemaValidCtxt:
955 *
956 * A Schemas validation context
957 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000958struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000959 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000960 void *userData; /* user specific data block */
961 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000962 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000963 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000964
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000965 xmlSchemaPtr schema; /* The schema in use */
966 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000967 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000968 xmlCharEncoding enc;
969 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000970 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000971 void *user_data; /* TODO: What is this for? */
Daniel Veillard4255d502002-04-16 15:50:10 +0000972
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000973 int err;
974 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000975
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000976 xmlNodePtr node;
977 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000978 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000979
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000980 xmlRegExecCtxtPtr regexp;
981 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000982
Daniel Veillardc0826a72004-08-10 14:17:33 +0000983 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000984 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000985 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000986 xmlSchemaParserCtxtPtr pctxt;
987 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000988
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000989 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000990 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000991 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000992 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000993
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000994 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
995
996 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
997 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000998
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000999 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1000 int nbIdcNodes;
1001 int sizeIdcNodes;
1002
1003 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1004 int nbIdcKeys;
1005 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001006
1007 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001008
1009 xmlDictPtr dict;
1010
Daniel Veillard39e5c892005-07-03 22:48:50 +00001011#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001012 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001013#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001014
1015 xmlSchemaAttrInfoPtr *attrInfos;
1016 int nbAttrInfos;
1017 int sizeAttrInfos;
1018
1019 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001020 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001021 int hasKeyrefs;
1022 int createIDCNodeTables;
1023 int psviExposeIDCNodeTables;
Daniel Veillard4255d502002-04-16 15:50:10 +00001024};
1025
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001026/**
1027 * xmlSchemaSubstGroup:
1028 *
1029 *
1030 */
1031typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1032typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1033struct _xmlSchemaSubstGroup {
1034 xmlSchemaElementPtr head;
1035 xmlSchemaItemListPtr members;
1036};
1037
Daniel Veillard4255d502002-04-16 15:50:10 +00001038/************************************************************************
1039 * *
1040 * Some predeclarations *
1041 * *
1042 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001043
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001044static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1045 xmlSchemaPtr schema,
1046 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001047static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1048 xmlSchemaPtr schema,
1049 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001050static int
1051xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001052 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001053static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001054xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1055static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001056xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1057 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001058static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001059xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1060 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001061static void
1062xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001063static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001064xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001065static xmlSchemaTreeItemPtr
1066xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1067 xmlNodePtr node, xmlSchemaTypeType type,
1068 int withParticle);
1069static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001070xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001071static xmlSchemaTypeLinkPtr
1072xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001073static void
1074xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1075 const char *funcName,
1076 const char *message);
1077static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001078xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001079 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001080 xmlSchemaTypePtr baseType,
1081 int subset);
1082static void
1083xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001084 xmlSchemaParserCtxtPtr ctxt);
1085static void
1086xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001087static xmlSchemaQNameRefPtr
1088xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1089 xmlSchemaPtr schema,
1090 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001091
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001092/************************************************************************
1093 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001094 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001095 * *
1096 ************************************************************************/
1097
1098/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001099 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001100 * @type: the type of the schema item
1101 *
1102 * Returns the component name of a schema item.
1103 */
1104static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001105xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001106{
1107 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001108 case XML_SCHEMA_TYPE_BASIC:
1109 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001110 case XML_SCHEMA_TYPE_SIMPLE:
1111 return(BAD_CAST "simple type definition");
1112 case XML_SCHEMA_TYPE_COMPLEX:
1113 return(BAD_CAST "complex type definition");
1114 case XML_SCHEMA_TYPE_ELEMENT:
1115 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001116 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1117 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001118 case XML_SCHEMA_TYPE_ATTRIBUTE:
1119 return(BAD_CAST "attribute declaration");
1120 case XML_SCHEMA_TYPE_GROUP:
1121 return(BAD_CAST "model group definition");
1122 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1123 return(BAD_CAST "attribute group definition");
1124 case XML_SCHEMA_TYPE_NOTATION:
1125 return(BAD_CAST "notation declaration");
1126 case XML_SCHEMA_TYPE_SEQUENCE:
1127 return(BAD_CAST "model group (sequence)");
1128 case XML_SCHEMA_TYPE_CHOICE:
1129 return(BAD_CAST "model group (choice)");
1130 case XML_SCHEMA_TYPE_ALL:
1131 return(BAD_CAST "model group (all)");
1132 case XML_SCHEMA_TYPE_PARTICLE:
1133 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001134 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001135 return(BAD_CAST "unique identity-constraint");
1136 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001137 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001138 return(BAD_CAST "key identity-constraint");
1139 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001140 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001141 return(BAD_CAST "keyref identity-constraint");
1142 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001143 case XML_SCHEMA_TYPE_ANY:
1144 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001145 case XML_SCHEMA_EXTRA_QNAMEREF:
1146 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001147 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1148 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001149 default:
1150 return(BAD_CAST "Not a schema component");
1151 }
1152}
1153
1154/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001155 * xmlSchemaGetComponentTypeStr:
1156 * @type: the type of the schema item
1157 *
1158 * Returns the component name of a schema item.
1159 */
1160static const xmlChar *
1161xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1162{
1163 switch (item->type) {
1164 case XML_SCHEMA_TYPE_BASIC:
1165 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1166 return(BAD_CAST "complex type definition");
1167 else
1168 return(BAD_CAST "simple type definition");
1169 default:
1170 return(xmlSchemaItemTypeToStr(item->type));
1171 }
1172}
1173
1174/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001175 * xmlSchemaGetComponentNode:
1176 * @item: a schema component
1177 *
1178 * Returns node associated with the schema component.
1179 * NOTE that such a node need not be available; plus, a component's
1180 * node need not to reflect the component directly, since there is no
1181 * one-to-one relationship between the XML Schema representation and
1182 * the component representation.
1183 */
1184static xmlNodePtr
1185xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1186{
1187 switch (item->type) {
1188 case XML_SCHEMA_TYPE_ELEMENT:
1189 return (((xmlSchemaElementPtr) item)->node);
1190 case XML_SCHEMA_TYPE_ATTRIBUTE:
1191 return (((xmlSchemaAttributePtr) item)->node);
1192 case XML_SCHEMA_TYPE_COMPLEX:
1193 case XML_SCHEMA_TYPE_SIMPLE:
1194 return (((xmlSchemaTypePtr) item)->node);
1195 case XML_SCHEMA_TYPE_ANY:
1196 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1197 return (((xmlSchemaWildcardPtr) item)->node);
1198 case XML_SCHEMA_TYPE_PARTICLE:
1199 return (((xmlSchemaParticlePtr) item)->node);
1200 case XML_SCHEMA_TYPE_SEQUENCE:
1201 case XML_SCHEMA_TYPE_CHOICE:
1202 case XML_SCHEMA_TYPE_ALL:
1203 return (((xmlSchemaModelGroupPtr) item)->node);
1204 case XML_SCHEMA_TYPE_GROUP:
1205 return (((xmlSchemaModelGroupDefPtr) item)->node);
1206 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1207 return (((xmlSchemaAttributeGroupPtr) item)->node);
1208 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1209 case XML_SCHEMA_TYPE_IDC_KEY:
1210 case XML_SCHEMA_TYPE_IDC_KEYREF:
1211 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001212 case XML_SCHEMA_EXTRA_QNAMEREF:
1213 return(((xmlSchemaQNameRefPtr) item)->node);
1214 /* TODO: What to do with NOTATIONs?
1215 case XML_SCHEMA_TYPE_NOTATION:
1216 return (((xmlSchemaNotationPtr) item)->node);
1217 */
1218 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1219 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001220 default:
1221 return (NULL);
1222 }
1223}
1224
1225#if 0
1226/**
1227 * xmlSchemaGetNextComponent:
1228 * @item: a schema component
1229 *
1230 * Returns the next sibling of the schema component.
1231 */
1232static xmlSchemaBasicItemPtr
1233xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1234{
1235 switch (item->type) {
1236 case XML_SCHEMA_TYPE_ELEMENT:
1237 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1238 case XML_SCHEMA_TYPE_ATTRIBUTE:
1239 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1240 case XML_SCHEMA_TYPE_COMPLEX:
1241 case XML_SCHEMA_TYPE_SIMPLE:
1242 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1243 case XML_SCHEMA_TYPE_ANY:
1244 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1245 return (NULL);
1246 case XML_SCHEMA_TYPE_PARTICLE:
1247 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1248 case XML_SCHEMA_TYPE_SEQUENCE:
1249 case XML_SCHEMA_TYPE_CHOICE:
1250 case XML_SCHEMA_TYPE_ALL:
1251 return (NULL);
1252 case XML_SCHEMA_TYPE_GROUP:
1253 return (NULL);
1254 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1255 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1256 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1257 case XML_SCHEMA_TYPE_IDC_KEY:
1258 case XML_SCHEMA_TYPE_IDC_KEYREF:
1259 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1260 default:
1261 return (NULL);
1262 }
1263}
1264#endif
1265
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001266
1267/**
1268 * xmlSchemaFormatQName:
1269 * @buf: the string buffer
1270 * @namespaceName: the namespace name
1271 * @localName: the local name
1272 *
1273 * Returns the given QName in the format "{namespaceName}localName" or
1274 * just "localName" if @namespaceName is NULL.
1275 *
1276 * Returns the localName if @namespaceName is NULL, a formatted
1277 * string otherwise.
1278 */
1279static const xmlChar*
1280xmlSchemaFormatQName(xmlChar **buf,
1281 const xmlChar *namespaceName,
1282 const xmlChar *localName)
1283{
1284 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001285 if (namespaceName != NULL) {
1286 *buf = xmlStrdup(BAD_CAST "{");
1287 *buf = xmlStrcat(*buf, namespaceName);
1288 *buf = xmlStrcat(*buf, BAD_CAST "}");
1289 }
1290 if (localName != NULL) {
1291 if (namespaceName == NULL)
1292 return(localName);
1293 *buf = xmlStrcat(*buf, localName);
1294 } else {
1295 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1296 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001297 return ((const xmlChar *) *buf);
1298}
1299
1300static const xmlChar*
1301xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1302{
1303 if (ns != NULL)
1304 return (xmlSchemaFormatQName(buf, ns->href, localName));
1305 else
1306 return (xmlSchemaFormatQName(buf, NULL, localName));
1307}
1308
1309static const xmlChar *
1310xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1311{
1312 switch (item->type) {
1313 case XML_SCHEMA_TYPE_ELEMENT:
1314 return (((xmlSchemaElementPtr) item)->name);
1315 case XML_SCHEMA_TYPE_ATTRIBUTE:
1316 return (((xmlSchemaAttributePtr) item)->name);
1317 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1318 return (((xmlSchemaAttributeGroupPtr) item)->name);
1319 case XML_SCHEMA_TYPE_BASIC:
1320 case XML_SCHEMA_TYPE_SIMPLE:
1321 case XML_SCHEMA_TYPE_COMPLEX:
1322 return (((xmlSchemaTypePtr) item)->name);
1323 case XML_SCHEMA_TYPE_GROUP:
1324 return (((xmlSchemaModelGroupDefPtr) item)->name);
1325 case XML_SCHEMA_TYPE_IDC_KEY:
1326 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1327 case XML_SCHEMA_TYPE_IDC_KEYREF:
1328 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001329 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1330 if (WXS_ATTRUSE_DECL(item) != NULL) {
1331 return(xmlSchemaGetComponentName(
1332 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1333 } else
1334 return(NULL);
1335 case XML_SCHEMA_EXTRA_QNAMEREF:
1336 return (((xmlSchemaQNameRefPtr) item)->name);
1337 case XML_SCHEMA_TYPE_NOTATION:
1338 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001339 default:
1340 /*
1341 * Other components cannot have names.
1342 */
1343 break;
1344 }
1345 return (NULL);
1346}
1347
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001348#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1349#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1350/*
1351static const xmlChar *
1352xmlSchemaGetQNameRefName(void *ref)
1353{
1354 return(((xmlSchemaQNameRefPtr) ref)->name);
1355}
1356
1357static const xmlChar *
1358xmlSchemaGetQNameRefTargetNs(void *ref)
1359{
1360 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1361}
1362*/
1363
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001364static const xmlChar *
1365xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1366{
1367 switch (item->type) {
1368 case XML_SCHEMA_TYPE_ELEMENT:
1369 return (((xmlSchemaElementPtr) item)->targetNamespace);
1370 case XML_SCHEMA_TYPE_ATTRIBUTE:
1371 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1372 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1373 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1374 case XML_SCHEMA_TYPE_BASIC:
1375 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1376 case XML_SCHEMA_TYPE_SIMPLE:
1377 case XML_SCHEMA_TYPE_COMPLEX:
1378 return (((xmlSchemaTypePtr) item)->targetNamespace);
1379 case XML_SCHEMA_TYPE_GROUP:
1380 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1381 case XML_SCHEMA_TYPE_IDC_KEY:
1382 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1383 case XML_SCHEMA_TYPE_IDC_KEYREF:
1384 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001385 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1386 if (WXS_ATTRUSE_DECL(item) != NULL) {
1387 return(xmlSchemaGetComponentTargetNs(
1388 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1389 }
1390 /* TODO: Will returning NULL break something? */
1391 break;
1392 case XML_SCHEMA_EXTRA_QNAMEREF:
1393 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1394 case XML_SCHEMA_TYPE_NOTATION:
1395 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001396 default:
1397 /*
1398 * Other components cannot have names.
1399 */
1400 break;
1401 }
1402 return (NULL);
1403}
1404
1405static const xmlChar*
1406xmlSchemaGetComponentQName(xmlChar **buf,
1407 void *item)
1408{
1409 return (xmlSchemaFormatQName(buf,
1410 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1411 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1412}
1413
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001414static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001415xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001416{
1417 xmlChar *str = NULL;
1418
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001419 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001420 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001421 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1422 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001423 *buf = xmlStrcat(*buf, BAD_CAST "'");
1424 FREE_AND_NULL(str);
1425 return(*buf);
1426}
1427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001428static const xmlChar*
1429xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1430{
1431 return(xmlSchemaGetComponentDesignation(buf, idc));
1432}
1433
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001434/**
1435 * xmlSchemaWildcardPCToString:
1436 * @pc: the type of processContents
1437 *
1438 * Returns a string representation of the type of
1439 * processContents.
1440 */
1441static const xmlChar *
1442xmlSchemaWildcardPCToString(int pc)
1443{
1444 switch (pc) {
1445 case XML_SCHEMAS_ANY_SKIP:
1446 return (BAD_CAST "skip");
1447 case XML_SCHEMAS_ANY_LAX:
1448 return (BAD_CAST "lax");
1449 case XML_SCHEMAS_ANY_STRICT:
1450 return (BAD_CAST "strict");
1451 default:
1452 return (BAD_CAST "invalid process contents");
1453 }
1454}
1455
1456/**
1457 * xmlSchemaGetCanonValueWhtspExt:
1458 * @val: the precomputed value
1459 * @retValue: the returned value
1460 * @ws: the whitespace type of the value
1461 *
1462 * Get a the cononical representation of the value.
1463 * The caller has to free the returned retValue.
1464 *
1465 * Returns 0 if the value could be built and -1 in case of
1466 * API errors or if the value type is not supported yet.
1467 */
1468static int
1469xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1470 xmlSchemaWhitespaceValueType ws,
1471 xmlChar **retValue)
1472{
1473 int list;
1474 xmlSchemaValType valType;
1475 const xmlChar *value, *value2 = NULL;
1476
1477
1478 if ((retValue == NULL) || (val == NULL))
1479 return (-1);
1480 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1481 *retValue = NULL;
1482 do {
1483 value = NULL;
1484 valType = xmlSchemaGetValType(val);
1485 switch (valType) {
1486 case XML_SCHEMAS_STRING:
1487 case XML_SCHEMAS_NORMSTRING:
1488 case XML_SCHEMAS_ANYSIMPLETYPE:
1489 value = xmlSchemaValueGetAsString(val);
1490 if (value != NULL) {
1491 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1492 value2 = xmlSchemaCollapseString(value);
1493 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1494 value2 = xmlSchemaWhiteSpaceReplace(value);
1495 if (value2 != NULL)
1496 value = value2;
1497 }
1498 break;
1499 default:
1500 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1501 if (value2 != NULL)
1502 xmlFree((xmlChar *) value2);
1503 goto internal_error;
1504 }
1505 value = value2;
1506 }
1507 if (*retValue == NULL)
1508 if (value == NULL) {
1509 if (! list)
1510 *retValue = xmlStrdup(BAD_CAST "");
1511 } else
1512 *retValue = xmlStrdup(value);
1513 else if (value != NULL) {
1514 /* List. */
1515 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1516 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1517 }
1518 FREE_AND_NULL(value2)
1519 val = xmlSchemaValueGetNext(val);
1520 } while (val != NULL);
1521
1522 return (0);
1523internal_error:
1524 if (*retValue != NULL)
1525 xmlFree((xmlChar *) (*retValue));
1526 if (value2 != NULL)
1527 xmlFree((xmlChar *) value2);
1528 return (-1);
1529}
1530
1531/**
1532 * xmlSchemaFormatItemForReport:
1533 * @buf: the string buffer
1534 * @itemDes: the designation of the item
1535 * @itemName: the name of the item
1536 * @item: the item as an object
1537 * @itemNode: the node of the item
1538 * @local: the local name
1539 * @parsing: if the function is used during the parse
1540 *
1541 * Returns a representation of the given item used
1542 * for error reports.
1543 *
1544 * The following order is used to build the resulting
1545 * designation if the arguments are not NULL:
1546 * 1a. If itemDes not NULL -> itemDes
1547 * 1b. If (itemDes not NULL) and (itemName not NULL)
1548 * -> itemDes + itemName
1549 * 2. If the preceding was NULL and (item not NULL) -> item
1550 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1551 *
1552 * If the itemNode is an attribute node, the name of the attribute
1553 * will be appended to the result.
1554 *
1555 * Returns the formatted string and sets @buf to the resulting value.
1556 */
1557static xmlChar*
1558xmlSchemaFormatItemForReport(xmlChar **buf,
1559 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001560 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001561 xmlNodePtr itemNode)
1562{
1563 xmlChar *str = NULL;
1564 int named = 1;
1565
1566 if (*buf != NULL) {
1567 xmlFree(*buf);
1568 *buf = NULL;
1569 }
1570
1571 if (itemDes != NULL) {
1572 *buf = xmlStrdup(itemDes);
1573 } else if (item != NULL) {
1574 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001575 case XML_SCHEMA_TYPE_BASIC: {
1576 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1577
1578 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001582 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001583 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1584 else
1585 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001586 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001587 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001589 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001590 case XML_SCHEMA_TYPE_SIMPLE: {
1591 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1592
1593 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 *buf = xmlStrdup(BAD_CAST"");
1595 } else {
1596 *buf = xmlStrdup(BAD_CAST "local ");
1597 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001602 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001603 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1604 else
1605 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001606 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001608 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001609 *buf = xmlStrcat(*buf, BAD_CAST "'");
1610 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001612 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001613 case XML_SCHEMA_TYPE_COMPLEX: {
1614 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1615
1616 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001617 *buf = xmlStrdup(BAD_CAST "");
1618 else
1619 *buf = xmlStrdup(BAD_CAST "local ");
1620 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001621 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001622 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001623 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624 *buf = xmlStrcat(*buf, BAD_CAST "'");
1625 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001626 }
1627 break;
1628 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1629 xmlSchemaAttributeUsePtr ause;
1630
1631 ause = WXS_ATTR_USE_CAST item;
1632 *buf = xmlStrdup(BAD_CAST "attribute use ");
1633 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1634 *buf = xmlStrcat(*buf, BAD_CAST "'");
1635 *buf = xmlStrcat(*buf,
1636 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1637 FREE_AND_NULL(str)
1638 *buf = xmlStrcat(*buf, BAD_CAST "'");
1639 } else {
1640 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1641 }
1642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 break;
1644 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1645 xmlSchemaAttributePtr attr;
1646
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001647 attr = (xmlSchemaAttributePtr) item;
1648 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1649 *buf = xmlStrcat(*buf, BAD_CAST " '");
1650 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1651 attr->targetNamespace, attr->name));
1652 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001653 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001654 }
1655 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001656 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1657 xmlSchemaGetComponentDesignation(buf, item);
1658 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001659 case XML_SCHEMA_TYPE_ELEMENT: {
1660 xmlSchemaElementPtr elem;
1661
1662 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001663 *buf = xmlStrdup(BAD_CAST "element decl.");
1664 *buf = xmlStrcat(*buf, BAD_CAST " '");
1665 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1666 elem->targetNamespace, elem->name));
1667 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001668 }
1669 break;
1670 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1671 case XML_SCHEMA_TYPE_IDC_KEY:
1672 case XML_SCHEMA_TYPE_IDC_KEYREF:
1673 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1674 *buf = xmlStrdup(BAD_CAST "unique '");
1675 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1676 *buf = xmlStrdup(BAD_CAST "key '");
1677 else
1678 *buf = xmlStrdup(BAD_CAST "keyRef '");
1679 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1680 *buf = xmlStrcat(*buf, BAD_CAST "'");
1681 break;
1682 case XML_SCHEMA_TYPE_ANY:
1683 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1684 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1685 ((xmlSchemaWildcardPtr) item)->processContents));
1686 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1687 break;
1688 case XML_SCHEMA_FACET_MININCLUSIVE:
1689 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1690 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1691 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1692 case XML_SCHEMA_FACET_TOTALDIGITS:
1693 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1694 case XML_SCHEMA_FACET_PATTERN:
1695 case XML_SCHEMA_FACET_ENUMERATION:
1696 case XML_SCHEMA_FACET_WHITESPACE:
1697 case XML_SCHEMA_FACET_LENGTH:
1698 case XML_SCHEMA_FACET_MAXLENGTH:
1699 case XML_SCHEMA_FACET_MINLENGTH:
1700 *buf = xmlStrdup(BAD_CAST "facet '");
1701 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1702 *buf = xmlStrcat(*buf, BAD_CAST "'");
1703 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001704 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001705 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001707 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001708 *buf = xmlStrcat(*buf, BAD_CAST "'");
1709 FREE_AND_NULL(str)
1710 }
1711 break;
1712 case XML_SCHEMA_TYPE_SEQUENCE:
1713 case XML_SCHEMA_TYPE_CHOICE:
1714 case XML_SCHEMA_TYPE_ALL:
1715 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001716 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1717 break;
1718 case XML_SCHEMA_TYPE_NOTATION: {
1719 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1720 *buf = xmlStrcat(*buf, BAD_CAST " '");
1721 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1722 *buf = xmlStrcat(*buf, BAD_CAST "'");
1723 FREE_AND_NULL(str);
1724 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725 default:
1726 named = 0;
1727 }
1728 } else
1729 named = 0;
1730
1731 if ((named == 0) && (itemNode != NULL)) {
1732 xmlNodePtr elem;
1733
1734 if (itemNode->type == XML_ATTRIBUTE_NODE)
1735 elem = itemNode->parent;
1736 else
1737 elem = itemNode;
1738 *buf = xmlStrdup(BAD_CAST "Element '");
1739 if (elem->ns != NULL) {
1740 *buf = xmlStrcat(*buf,
1741 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1742 FREE_AND_NULL(str)
1743 } else
1744 *buf = xmlStrcat(*buf, elem->name);
1745 *buf = xmlStrcat(*buf, BAD_CAST "'");
1746
1747 }
1748 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1749 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1750 if (itemNode->ns != NULL) {
1751 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1752 itemNode->ns->href, itemNode->name));
1753 FREE_AND_NULL(str)
1754 } else
1755 *buf = xmlStrcat(*buf, itemNode->name);
1756 *buf = xmlStrcat(*buf, BAD_CAST "'");
1757 }
1758 FREE_AND_NULL(str)
1759
1760 return (*buf);
1761}
1762
1763/**
1764 * xmlSchemaFormatFacetEnumSet:
1765 * @buf: the string buffer
1766 * @type: the type holding the enumeration facets
1767 *
1768 * Builds a string consisting of all enumeration elements.
1769 *
1770 * Returns a string of all enumeration elements.
1771 */
1772static const xmlChar *
1773xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1774 xmlChar **buf, xmlSchemaTypePtr type)
1775{
1776 xmlSchemaFacetPtr facet;
1777 xmlSchemaWhitespaceValueType ws;
1778 xmlChar *value = NULL;
1779 int res;
1780
1781 if (*buf != NULL)
1782 xmlFree(*buf);
1783 *buf = NULL;
1784
1785 do {
1786 /*
1787 * Use the whitespace type of the base type.
1788 */
1789 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1790 for (facet = type->facets; facet != NULL; facet = facet->next) {
1791 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1792 continue;
1793 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1794 ws, &value);
1795 if (res == -1) {
1796 xmlSchemaInternalErr(actxt,
1797 "xmlSchemaFormatFacetEnumSet",
1798 "compute the canonical lexical representation");
1799 if (*buf != NULL)
1800 xmlFree(*buf);
1801 *buf = NULL;
1802 return (NULL);
1803 }
1804 if (*buf == NULL)
1805 *buf = xmlStrdup(BAD_CAST "'");
1806 else
1807 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1808 *buf = xmlStrcat(*buf, BAD_CAST value);
1809 *buf = xmlStrcat(*buf, BAD_CAST "'");
1810 if (value != NULL) {
1811 xmlFree((xmlChar *)value);
1812 value = NULL;
1813 }
1814 }
1815 type = type->baseType;
1816 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1817
1818 return ((const xmlChar *) *buf);
1819}
1820
1821/************************************************************************
1822 * *
1823 * Error functions *
1824 * *
1825 ************************************************************************/
1826
1827#if 0
1828static void
1829xmlSchemaErrMemory(const char *msg)
1830{
1831 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1832 msg);
1833}
1834#endif
1835
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001836static void
1837xmlSchemaPSimpleErr(const char *msg)
1838{
1839 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1840 msg);
1841}
1842
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001843/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844 * xmlSchemaPErrMemory:
1845 * @node: a context node
1846 * @extra: extra informations
1847 *
1848 * Handle an out of memory condition
1849 */
1850static void
1851xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1852 const char *extra, xmlNodePtr node)
1853{
1854 if (ctxt != NULL)
1855 ctxt->nberrors++;
1856 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1857 extra);
1858}
1859
1860/**
1861 * xmlSchemaPErr:
1862 * @ctxt: the parsing context
1863 * @node: the context node
1864 * @error: the error code
1865 * @msg: the error message
1866 * @str1: extra data
1867 * @str2: extra data
1868 *
1869 * Handle a parser error
1870 */
1871static void
1872xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1873 const char *msg, const xmlChar * str1, const xmlChar * str2)
1874{
1875 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001876 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001877 void *data = NULL;
1878
1879 if (ctxt != NULL) {
1880 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001881 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001882 channel = ctxt->error;
1883 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001884 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001885 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001886 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001887 error, XML_ERR_ERROR, NULL, 0,
1888 (const char *) str1, (const char *) str2, NULL, 0, 0,
1889 msg, str1, str2);
1890}
1891
1892/**
1893 * xmlSchemaPErr2:
1894 * @ctxt: the parsing context
1895 * @node: the context node
1896 * @node: the current child
1897 * @error: the error code
1898 * @msg: the error message
1899 * @str1: extra data
1900 * @str2: extra data
1901 *
1902 * Handle a parser error
1903 */
1904static void
1905xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1906 xmlNodePtr child, int error,
1907 const char *msg, const xmlChar * str1, const xmlChar * str2)
1908{
1909 if (child != NULL)
1910 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1911 else
1912 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1913}
1914
Daniel Veillard01fa6152004-06-29 17:04:39 +00001915
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001916/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001917 * xmlSchemaPErrExt:
1918 * @ctxt: the parsing context
1919 * @node: the context node
1920 * @error: the error code
1921 * @strData1: extra data
1922 * @strData2: extra data
1923 * @strData3: extra data
1924 * @msg: the message
1925 * @str1: extra parameter for the message display
1926 * @str2: extra parameter for the message display
1927 * @str3: extra parameter for the message display
1928 * @str4: extra parameter for the message display
1929 * @str5: extra parameter for the message display
1930 *
1931 * Handle a parser error
1932 */
1933static void
1934xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1935 const xmlChar * strData1, const xmlChar * strData2,
1936 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1937 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1938 const xmlChar * str5)
1939{
1940
1941 xmlGenericErrorFunc channel = NULL;
1942 xmlStructuredErrorFunc schannel = NULL;
1943 void *data = NULL;
1944
1945 if (ctxt != NULL) {
1946 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001947 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001948 channel = ctxt->error;
1949 data = ctxt->userData;
1950 schannel = ctxt->serror;
1951 }
1952 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1953 error, XML_ERR_ERROR, NULL, 0,
1954 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001955 (const char *) strData3, 0, 0, msg, str1, str2,
1956 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001957}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001958
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001959/************************************************************************
1960 * *
1961 * Allround error functions *
1962 * *
1963 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001964
1965/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001966 * xmlSchemaVTypeErrMemory:
1967 * @node: a context node
1968 * @extra: extra informations
1969 *
1970 * Handle an out of memory condition
1971 */
1972static void
1973xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1974 const char *extra, xmlNodePtr node)
1975{
1976 if (ctxt != NULL) {
1977 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001978 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001979 }
1980 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1981 extra);
1982}
1983
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001984static void
1985xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1986 const char *msg, const xmlChar *str)
1987{
1988 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1989 msg, (const char *) str);
1990}
1991
1992#define WXS_ERROR_TYPE_ERROR 1
1993#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001994/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001995 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001996 * @ctxt: the validation context
1997 * @node: the context node
1998 * @error: the error code
1999 * @msg: the error message
2000 * @str1: extra data
2001 * @str2: extra data
2002 * @str3: extra data
2003 *
2004 * Handle a validation error
2005 */
2006static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002007xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002008 xmlErrorLevel errorLevel,
2009 int error, xmlNodePtr node, int line, const char *msg,
2010 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002011 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002012{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002013 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002014 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002015 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002016
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002017 if (ctxt != NULL) {
2018 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2019 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002020 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002021 if (errorLevel != XML_ERR_WARNING) {
2022 vctxt->nberrors++;
2023 vctxt->err = error;
2024 channel = vctxt->error;
2025 } else {
2026 channel = vctxt->warning;
2027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002028 schannel = vctxt->serror;
2029 data = vctxt->userData;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002030
2031 /*
2032 * Error node. If we specify a line number, then
2033 * do not channel any node to the error function.
2034 */
2035 if (line == 0) {
2036 if ((node == NULL) &&
2037 (vctxt->depth >= 0) &&
2038 (vctxt->inode != NULL)) {
2039 node = vctxt->inode->node;
2040 }
2041 /*
2042 * Get filename and line if no node-tree.
2043 */
2044 if ((node == NULL) &&
2045 (vctxt->parserCtxt != NULL) &&
2046 (vctxt->parserCtxt->input != NULL)) {
2047 file = vctxt->parserCtxt->input->filename;
2048 line = vctxt->parserCtxt->input->line;
2049 }
2050 } else {
2051 /*
2052 * Override the given node's (if any) position
2053 * and channel only the given line number.
2054 */
2055 node = NULL;
2056 /*
2057 * Get filename.
2058 */
2059 if (vctxt->doc != NULL)
2060 file = (const char *) vctxt->doc->URL;
2061 else if ((vctxt->parserCtxt != NULL) &&
2062 (vctxt->parserCtxt->input != NULL))
2063 file = vctxt->parserCtxt->input->filename;
2064 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002065 __xmlRaiseError(schannel, channel, data, ctxt,
2066 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002067 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002068 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002069 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002070
2071 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2072 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002073 if (errorLevel != XML_ERR_WARNING) {
2074 pctxt->nberrors++;
2075 pctxt->err = error;
2076 channel = pctxt->error;
2077 } else {
2078 channel = pctxt->warning;
2079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002080 schannel = pctxt->serror;
2081 data = pctxt->userData;
2082 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002083 node, XML_FROM_SCHEMASP, error,
2084 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002085 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002086 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002087 } else {
2088 TODO
2089 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002090 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002091}
2092
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002093/**
2094 * xmlSchemaErr3:
2095 * @ctxt: the validation context
2096 * @node: the context node
2097 * @error: the error code
2098 * @msg: the error message
2099 * @str1: extra data
2100 * @str2: extra data
2101 * @str3: extra data
2102 *
2103 * Handle a validation error
2104 */
2105static void
2106xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2107 int error, xmlNodePtr node, const char *msg,
2108 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2109{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002110 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2111 msg, str1, str2, str3, NULL);
2112}
2113
2114static void
2115xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2116 int error, xmlNodePtr node, const char *msg,
2117 const xmlChar *str1, const xmlChar *str2,
2118 const xmlChar *str3, const xmlChar *str4)
2119{
2120 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2121 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002122}
2123
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002124static void
2125xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2126 int error, xmlNodePtr node, const char *msg,
2127 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002128{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002129 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002130}
2131
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002132static xmlChar *
2133xmlSchemaFormatNodeForError(xmlChar ** msg,
2134 xmlSchemaAbstractCtxtPtr actxt,
2135 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002136{
2137 xmlChar *str = NULL;
2138
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002139 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002140 if ((node != NULL) &&
2141 (node->type != XML_ELEMENT_NODE) &&
2142 (node->type != XML_ATTRIBUTE_NODE))
2143 {
2144 /*
2145 * Don't try to format other nodes than element and
2146 * attribute nodes.
2147 * Play save and return an empty string.
2148 */
2149 *msg = xmlStrdup(BAD_CAST "");
2150 return(*msg);
2151 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002152 if (node != NULL) {
2153 /*
2154 * Work on tree nodes.
2155 */
2156 if (node->type == XML_ATTRIBUTE_NODE) {
2157 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002158
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 *msg = xmlStrdup(BAD_CAST "Element '");
2160 if (elem->ns != NULL)
2161 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2162 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002163 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002164 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2165 NULL, elem->name));
2166 FREE_AND_NULL(str);
2167 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2168 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2169 } else {
2170 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002172 if (node->ns != NULL)
2173 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2174 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002175 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2177 NULL, node->name));
2178 FREE_AND_NULL(str);
2179 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2180 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2181 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2182 /*
2183 * Work on node infos.
2184 */
2185 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2186 xmlSchemaNodeInfoPtr ielem =
2187 vctxt->elemInfos[vctxt->depth];
2188
2189 *msg = xmlStrdup(BAD_CAST "Element '");
2190 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2191 ielem->nsName, ielem->localName));
2192 FREE_AND_NULL(str);
2193 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2194 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2195 } else {
2196 *msg = xmlStrdup(BAD_CAST "Element '");
2197 }
2198 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2199 vctxt->inode->nsName, vctxt->inode->localName));
2200 FREE_AND_NULL(str);
2201 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002202 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2203 /*
2204 * Hmm, no node while parsing?
2205 * Return an empty string, in case NULL will break something.
2206 */
2207 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 } else {
2209 TODO
2210 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002212 /*
2213 * VAL TODO: The output of the given schema component is currently
2214 * disabled.
2215 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002216#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2218 *msg = xmlStrcat(*msg, BAD_CAST " [");
2219 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2220 NULL, type, NULL, 0));
2221 FREE_AND_NULL(str)
2222 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002223 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224#endif
2225 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226}
2227
Daniel Veillardc0826a72004-08-10 14:17:33 +00002228static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002229xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002230 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002231 const char *message,
2232 const xmlChar *str1,
2233 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002234{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002235 xmlChar *msg = NULL;
2236
2237 msg = xmlStrdup(BAD_CAST "Internal error: ");
2238 msg = xmlStrcat(msg, BAD_CAST funcName);
2239 msg = xmlStrcat(msg, BAD_CAST ", ");
2240 msg = xmlStrcat(msg, BAD_CAST message);
2241 msg = xmlStrcat(msg, BAD_CAST ".\n");
2242
2243 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2244 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002245 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002247 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002249 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250
2251 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252}
2253
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002255xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2256 const char *funcName,
2257 const char *message)
2258{
2259 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2260}
2261
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002262#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002263static void
2264xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2265 const char *funcName,
2266 const char *message,
2267 const xmlChar *str1,
2268 const xmlChar *str2)
2269{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002270 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002271 str1, str2);
2272}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002273#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002274
2275static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002276xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2277 xmlParserErrors error,
2278 xmlNodePtr node,
2279 xmlSchemaBasicItemPtr item,
2280 const char *message,
2281 const xmlChar *str1, const xmlChar *str2,
2282 const xmlChar *str3, const xmlChar *str4)
2283{
2284 xmlChar *msg = NULL;
2285
2286 if ((node == NULL) && (item != NULL) &&
2287 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2288 node = WXS_ITEM_NODE(item);
2289 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2290 msg = xmlStrcat(msg, BAD_CAST ": ");
2291 } else
2292 xmlSchemaFormatNodeForError(&msg, actxt, node);
2293 msg = xmlStrcat(msg, (const xmlChar *) message);
2294 msg = xmlStrcat(msg, BAD_CAST ".\n");
2295 xmlSchemaErr4(actxt, error, node,
2296 (const char *) msg, str1, str2, str3, str4);
2297 FREE_AND_NULL(msg)
2298}
2299
2300static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002301xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2302 xmlParserErrors error,
2303 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002304 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 const char *message,
2306 const xmlChar *str1,
2307 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002308{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002309 xmlSchemaCustomErr4(actxt, error, node, item,
2310 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002311}
2312
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002313
2314
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002315static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002316xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2317 xmlParserErrors error,
2318 xmlNodePtr node,
2319 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2320 const char *message,
2321 const xmlChar *str1,
2322 const xmlChar *str2,
2323 const xmlChar *str3)
2324{
2325 xmlChar *msg = NULL;
2326
2327 xmlSchemaFormatNodeForError(&msg, actxt, node);
2328 msg = xmlStrcat(msg, (const xmlChar *) message);
2329 msg = xmlStrcat(msg, BAD_CAST ".\n");
2330
2331 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002332 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2333 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002334
2335 FREE_AND_NULL(msg)
2336}
2337
2338
2339
2340static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002341xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2342 xmlParserErrors error,
2343 xmlSchemaPSVIIDCNodePtr idcNode,
2344 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2345 const char *message,
2346 const xmlChar *str1,
2347 const xmlChar *str2)
2348{
2349 xmlChar *msg = NULL, *qname = NULL;
2350
2351 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2352 msg = xmlStrcat(msg, (const xmlChar *) message);
2353 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002354 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002355 error, NULL, idcNode->nodeLine, (const char *) msg,
2356 xmlSchemaFormatQName(&qname,
2357 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2358 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002359 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002360 FREE_AND_NULL(qname);
2361 FREE_AND_NULL(msg);
2362}
2363
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002364static int
2365xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2366 xmlNodePtr node)
2367{
2368 if (node != NULL)
2369 return (node->type);
2370 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2371 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2372 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2373 return (-1);
2374}
2375
2376static int
2377xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2378{
2379 switch (item->type) {
2380 case XML_SCHEMA_TYPE_COMPLEX:
2381 case XML_SCHEMA_TYPE_SIMPLE:
2382 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2383 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002384 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002385 case XML_SCHEMA_TYPE_GROUP:
2386 return (1);
2387 case XML_SCHEMA_TYPE_ELEMENT:
2388 if ( ((xmlSchemaElementPtr) item)->flags &
2389 XML_SCHEMAS_ELEM_GLOBAL)
2390 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002391 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002392 case XML_SCHEMA_TYPE_ATTRIBUTE:
2393 if ( ((xmlSchemaAttributePtr) item)->flags &
2394 XML_SCHEMAS_ATTR_GLOBAL)
2395 return(1);
2396 break;
2397 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002398 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 return(1);
2400 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002401 return (0);
2402}
2403
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002404static void
2405xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2406 xmlParserErrors error,
2407 xmlNodePtr node,
2408 const xmlChar *value,
2409 xmlSchemaTypePtr type,
2410 int displayValue)
2411{
2412 xmlChar *msg = NULL;
2413
2414 xmlSchemaFormatNodeForError(&msg, actxt, node);
2415
2416 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2417 XML_ATTRIBUTE_NODE))
2418 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2419 else
2420 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2421 "value of ");
2422
2423 if (! xmlSchemaIsGlobalItem(type))
2424 msg = xmlStrcat(msg, BAD_CAST "the local ");
2425 else
2426 msg = xmlStrcat(msg, BAD_CAST "the ");
2427
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002428 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002430 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002432 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002433 msg = xmlStrcat(msg, BAD_CAST "union type");
2434
2435 if (xmlSchemaIsGlobalItem(type)) {
2436 xmlChar *str = NULL;
2437 msg = xmlStrcat(msg, BAD_CAST " '");
2438 if (type->builtInType != 0) {
2439 msg = xmlStrcat(msg, BAD_CAST "xs:");
2440 msg = xmlStrcat(msg, type->name);
2441 } else
2442 msg = xmlStrcat(msg,
2443 xmlSchemaFormatQName(&str,
2444 type->targetNamespace, type->name));
2445 msg = xmlStrcat(msg, BAD_CAST "'");
2446 FREE_AND_NULL(str);
2447 }
2448 msg = xmlStrcat(msg, BAD_CAST ".\n");
2449 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2450 XML_ATTRIBUTE_NODE))
2451 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2452 else
2453 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2454 FREE_AND_NULL(msg)
2455}
2456
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2459 xmlSchemaNodeInfoPtr ni,
2460 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002461{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002462 if (node != NULL) {
2463 if (node->ns != NULL)
2464 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2465 else
2466 return (xmlSchemaFormatQName(str, NULL, node->name));
2467 } else if (ni != NULL)
2468 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2469 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002470}
2471
Daniel Veillardc0826a72004-08-10 14:17:33 +00002472static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002473xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2474 xmlParserErrors error,
2475 xmlSchemaAttrInfoPtr ni,
2476 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002477{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 xmlChar *msg = NULL, *str = NULL;
2479
2480 xmlSchemaFormatNodeForError(&msg, actxt, node);
2481 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2482 xmlSchemaErr(actxt, error, node, (const char *) msg,
2483 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2484 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487}
2488
Daniel Veillardc0826a72004-08-10 14:17:33 +00002489static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2491 xmlParserErrors error,
2492 xmlNodePtr node,
2493 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002494 const char *message,
2495 int nbval,
2496 int nbneg,
2497 xmlChar **values)
2498{
2499 xmlChar *str = NULL, *msg = NULL;
2500 xmlChar *localName, *nsName;
2501 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002502 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002506 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002507 /*
2508 * Note that is does not make sense to report that we have a
2509 * wildcard here, since the wildcard might be unfolded into
2510 * multiple transitions.
2511 */
2512 if (nbval + nbneg > 0) {
2513 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002515 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002516 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002517 nsName = NULL;
2518
2519 for (i = 0; i < nbval + nbneg; i++) {
2520 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002521 if (cur == NULL)
2522 continue;
2523 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2524 (cur[3] == ' ')) {
2525 is_not = 1;
2526 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002527 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002528 } else {
2529 is_not = 0;
2530 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002531 /*
2532 * Get the local name.
2533 */
2534 localName = NULL;
2535
2536 end = cur;
2537 if (*end == '*') {
2538 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002539 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002540 } else {
2541 while ((*end != 0) && (*end != '|'))
2542 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002543 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002544 }
2545 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002546 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002547 /*
2548 * Skip "*|*" if they come with negated expressions, since
2549 * they represent the same negated wildcard.
2550 */
2551 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2552 /*
2553 * Get the namespace name.
2554 */
2555 cur = end;
2556 if (*end == '*') {
2557 nsName = xmlStrdup(BAD_CAST "{*}");
2558 } else {
2559 while (*end != 0)
2560 end++;
2561
2562 if (i >= nbval)
2563 nsName = xmlStrdup(BAD_CAST "{##other:");
2564 else
2565 nsName = xmlStrdup(BAD_CAST "{");
2566
2567 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2568 nsName = xmlStrcat(nsName, BAD_CAST "}");
2569 }
2570 str = xmlStrcat(str, BAD_CAST nsName);
2571 FREE_AND_NULL(nsName)
2572 } else {
2573 FREE_AND_NULL(localName);
2574 continue;
2575 }
2576 }
2577 str = xmlStrcat(str, BAD_CAST localName);
2578 FREE_AND_NULL(localName);
2579
2580 if (i < nbval + nbneg -1)
2581 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002584 msg = xmlStrcat(msg, BAD_CAST str);
2585 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586 } else
2587 msg = xmlStrcat(msg, BAD_CAST "\n");
2588 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002589 xmlFree(msg);
2590}
2591
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002592static void
2593xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2594 xmlParserErrors error,
2595 xmlNodePtr node,
2596 const xmlChar *value,
2597 unsigned long length,
2598 xmlSchemaTypePtr type,
2599 xmlSchemaFacetPtr facet,
2600 const char *message,
2601 const xmlChar *str1,
2602 const xmlChar *str2)
2603{
2604 xmlChar *str = NULL, *msg = NULL;
2605 xmlSchemaTypeType facetType;
2606 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2607
2608 xmlSchemaFormatNodeForError(&msg, actxt, node);
2609 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2610 facetType = XML_SCHEMA_FACET_ENUMERATION;
2611 /*
2612 * If enumerations are validated, one must not expect the
2613 * facet to be given.
2614 */
2615 } else
2616 facetType = facet->type;
2617 msg = xmlStrcat(msg, BAD_CAST "[");
2618 msg = xmlStrcat(msg, BAD_CAST "facet '");
2619 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2620 msg = xmlStrcat(msg, BAD_CAST "'] ");
2621 if (message == NULL) {
2622 /*
2623 * Use a default message.
2624 */
2625 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2626 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2627 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2628
2629 char len[25], actLen[25];
2630
2631 /* FIXME, TODO: What is the max expected string length of the
2632 * this value?
2633 */
2634 if (nodeType == XML_ATTRIBUTE_NODE)
2635 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2636 else
2637 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2638
2639 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2640 snprintf(actLen, 24, "%lu", length);
2641
2642 if (facetType == XML_SCHEMA_FACET_LENGTH)
2643 msg = xmlStrcat(msg,
2644 BAD_CAST "this differs from the allowed length of '%s'.\n");
2645 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2646 msg = xmlStrcat(msg,
2647 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2648 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2649 msg = xmlStrcat(msg,
2650 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2651
2652 if (nodeType == XML_ATTRIBUTE_NODE)
2653 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2654 value, (const xmlChar *) actLen, (const xmlChar *) len);
2655 else
2656 xmlSchemaErr(actxt, error, node, (const char *) msg,
2657 (const xmlChar *) actLen, (const xmlChar *) len);
2658
2659 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2660 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2661 "of the set {%s}.\n");
2662 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2663 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2664 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2665 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2666 "by the pattern '%s'.\n");
2667 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2668 facet->value);
2669 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2670 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2671 "minimum value allowed ('%s').\n");
2672 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2673 facet->value);
2674 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2675 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2676 "maximum value allowed ('%s').\n");
2677 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 facet->value);
2679 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2681 "'%s'.\n");
2682 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 facet->value);
2684 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2685 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2686 "'%s'.\n");
2687 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688 facet->value);
2689 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2690 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2691 "digits than are allowed ('%s').\n");
2692 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2693 facet->value);
2694 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2695 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2696 "digits than are allowed ('%s').\n");
2697 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2698 facet->value);
2699 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2700 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2701 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2702 } else {
2703 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2704 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2705 }
2706 } else {
2707 msg = xmlStrcat(msg, (const xmlChar *) message);
2708 msg = xmlStrcat(msg, BAD_CAST ".\n");
2709 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2710 }
2711 FREE_AND_NULL(str)
2712 xmlFree(msg);
2713}
2714
2715#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002716 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002718#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002719
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002720#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2721#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002722
2723#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2724
2725
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002726/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002727 * xmlSchemaPMissingAttrErr:
2728 * @ctxt: the schema validation context
2729 * @ownerDes: the designation of the owner
2730 * @ownerName: the name of the owner
2731 * @ownerItem: the owner as a schema object
2732 * @ownerElem: the owner as an element node
2733 * @node: the parent element node of the missing attribute node
2734 * @type: the corresponding type of the attribute node
2735 *
2736 * Reports an illegal attribute.
2737 */
2738static void
2739xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002740 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002741 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002742 xmlNodePtr ownerElem,
2743 const char *name,
2744 const char *message)
2745{
2746 xmlChar *des = NULL;
2747
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002748 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2749
Daniel Veillardc0826a72004-08-10 14:17:33 +00002750 if (message != NULL)
2751 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002752 else
2753 xmlSchemaPErr(ctxt, ownerElem, error,
2754 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002755 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002756 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002757}
2758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002759
Daniel Veillardc0826a72004-08-10 14:17:33 +00002760/**
2761 * xmlSchemaPResCompAttrErr:
2762 * @ctxt: the schema validation context
2763 * @error: the error code
2764 * @ownerDes: the designation of the owner
2765 * @ownerItem: the owner as a schema object
2766 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002767 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002768 * @refName: the referenced local name
2769 * @refURI: the referenced namespace URI
2770 * @message: optional message
2771 *
2772 * Used to report QName attribute values that failed to resolve
2773 * to schema components.
2774 */
2775static void
2776xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002777 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002778 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002779 xmlNodePtr ownerElem,
2780 const char *name,
2781 const xmlChar *refName,
2782 const xmlChar *refURI,
2783 xmlSchemaTypeType refType,
2784 const char *refTypeStr)
2785{
2786 xmlChar *des = NULL, *strA = NULL;
2787
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002788 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002789 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002790 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002791 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002792 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2794 "%s.\n", BAD_CAST des, BAD_CAST name,
2795 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002796 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002797 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002798 FREE_AND_NULL(strA)
2799}
2800
William M. Brack2f2a6632004-08-20 23:09:47 +00002801/**
2802 * xmlSchemaPCustomAttrErr:
2803 * @ctxt: the schema parser context
2804 * @error: the error code
2805 * @ownerDes: the designation of the owner
2806 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002807 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002808 *
2809 * Reports an illegal attribute during the parse.
2810 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002811static void
2812xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002813 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002814 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002815 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002816 xmlAttrPtr attr,
2817 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818{
2819 xmlChar *des = NULL;
2820
2821 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002822 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002823 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002824 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002826 } else
2827 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002828 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002829 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002830 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2831 if (ownerDes == NULL)
2832 FREE_AND_NULL(des);
2833}
2834
2835/**
2836 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002837 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002838 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002839 * @ownerDes: the designation of the attribute's owner
2840 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002841 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002842 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002843 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002844 */
2845static void
2846xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002847 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002848 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002849 xmlAttrPtr attr)
2850{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002851 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002852
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002853 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2854 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2855 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2856 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2857 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002858 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002859 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002860}
2861
William M. Brack2f2a6632004-08-20 23:09:47 +00002862/**
2863 * xmlSchemaPCustomErr:
2864 * @ctxt: the schema parser context
2865 * @error: the error code
2866 * @itemDes: the designation of the schema item
2867 * @item: the schema item
2868 * @itemElem: the node of the schema item
2869 * @message: the error message
2870 * @str1: an optional param for the error message
2871 * @str2: an optional param for the error message
2872 * @str3: an optional param for the error message
2873 *
2874 * Reports an error during parsing.
2875 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002876static void
2877xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002878 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002879 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002880 xmlNodePtr itemElem,
2881 const char *message,
2882 const xmlChar *str1,
2883 const xmlChar *str2,
2884 const xmlChar *str3)
2885{
2886 xmlChar *des = NULL, *msg = NULL;
2887
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002888 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002889 msg = xmlStrdup(BAD_CAST "%s: ");
2890 msg = xmlStrcat(msg, (const xmlChar *) message);
2891 msg = xmlStrcat(msg, BAD_CAST ".\n");
2892 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002893 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002894 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002895 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002896 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002897 FREE_AND_NULL(msg);
2898}
2899
William M. Brack2f2a6632004-08-20 23:09:47 +00002900/**
2901 * xmlSchemaPCustomErr:
2902 * @ctxt: the schema parser context
2903 * @error: the error code
2904 * @itemDes: the designation of the schema item
2905 * @item: the schema item
2906 * @itemElem: the node of the schema item
2907 * @message: the error message
2908 * @str1: the optional param for the error message
2909 *
2910 * Reports an error during parsing.
2911 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002912static void
2913xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002914 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002915 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002916 xmlNodePtr itemElem,
2917 const char *message,
2918 const xmlChar *str1)
2919{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002920 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002921 str1, NULL, NULL);
2922}
2923
William M. Brack2f2a6632004-08-20 23:09:47 +00002924/**
2925 * xmlSchemaPAttrUseErr:
2926 * @ctxt: the schema parser context
2927 * @error: the error code
2928 * @itemDes: the designation of the schema type
2929 * @item: the schema type
2930 * @itemElem: the node of the schema type
2931 * @attr: the invalid schema attribute
2932 * @message: the error message
2933 * @str1: the optional param for the error message
2934 *
2935 * Reports an attribute use error during parsing.
2936 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002937static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002938xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002939 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002940 xmlNodePtr node,
2941 xmlSchemaBasicItemPtr ownerItem,
2942 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002943 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002944 const xmlChar *str1, const xmlChar *str2,
2945 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002946{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002947 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948
2949 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2950 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002951 msg = xmlStrcat(msg,
2952 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002954 FREE_AND_NULL(str);
2955 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002956 msg = xmlStrcat(msg, (const xmlChar *) message);
2957 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002958 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2959 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002960 xmlFree(msg);
2961}
2962
William M. Brack2f2a6632004-08-20 23:09:47 +00002963/**
2964 * xmlSchemaPIllegalFacetAtomicErr:
2965 * @ctxt: the schema parser context
2966 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002967 * @type: the schema type
2968 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002969 * @facet: the illegal facet
2970 *
2971 * Reports an illegal facet for atomic simple types.
2972 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002973static void
2974xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002975 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002976 xmlSchemaTypePtr type,
2977 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002978 xmlSchemaFacetPtr facet)
2979{
2980 xmlChar *des = NULL, *strT = NULL;
2981
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002982 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2983 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002984 "%s: The facet '%s' is not allowed on types derived from the "
2985 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002986 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002987 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002988 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002989 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002990 FREE_AND_NULL(strT);
2991}
2992
William M. Brack2f2a6632004-08-20 23:09:47 +00002993/**
2994 * xmlSchemaPIllegalFacetListUnionErr:
2995 * @ctxt: the schema parser context
2996 * @error: the error code
2997 * @itemDes: the designation of the schema item involved
2998 * @item: the schema item involved
2999 * @facet: the illegal facet
3000 *
3001 * Reports an illegal facet for <list> and <union>.
3002 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003static void
3004xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003005 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003006 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003007 xmlSchemaFacetPtr facet)
3008{
3009 xmlChar *des = NULL, *strT = NULL;
3010
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003011 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3012 type->node);
3013 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003014 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003015 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003016 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003017 FREE_AND_NULL(strT);
3018}
3019
3020/**
3021 * xmlSchemaPMutualExclAttrErr:
3022 * @ctxt: the schema validation context
3023 * @error: the error code
3024 * @elemDes: the designation of the parent element node
3025 * @attr: the bad attribute node
3026 * @type: the corresponding type of the attribute node
3027 *
3028 * Reports an illegal attribute.
3029 */
3030static void
3031xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3032 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003033 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003034 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003035 const char *name1,
3036 const char *name2)
3037{
3038 xmlChar *des = NULL;
3039
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003040 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003041 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003042 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003043 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003044 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003045}
3046
3047/**
3048 * xmlSchemaPSimpleTypeErr:
3049 * @ctxt: the schema validation context
3050 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003051 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003052 * @ownerDes: the designation of the owner
3053 * @ownerItem: the schema object if existent
3054 * @node: the validated node
3055 * @value: the validated value
3056 *
3057 * Reports a simple type validation error.
3058 * TODO: Should this report the value of an element as well?
3059 */
3060static void
3061xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3062 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003063 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003064 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003065 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003066 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003067 const xmlChar *value,
3068 const char *message,
3069 const xmlChar *str1,
3070 const xmlChar *str2)
3071{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003073
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003074 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003075 if (message == NULL) {
3076 /*
3077 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003078 */
3079 if (type != NULL) {
3080 if (node->type == XML_ATTRIBUTE_NODE)
3081 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3082 else
3083 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3084 "valid value of ");
3085 if (! xmlSchemaIsGlobalItem(type))
3086 msg = xmlStrcat(msg, BAD_CAST "the local ");
3087 else
3088 msg = xmlStrcat(msg, BAD_CAST "the ");
3089
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003090 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003091 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003092 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003093 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003094 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003095 msg = xmlStrcat(msg, BAD_CAST "union type");
3096
3097 if (xmlSchemaIsGlobalItem(type)) {
3098 xmlChar *str = NULL;
3099 msg = xmlStrcat(msg, BAD_CAST " '");
3100 if (type->builtInType != 0) {
3101 msg = xmlStrcat(msg, BAD_CAST "xs:");
3102 msg = xmlStrcat(msg, type->name);
3103 } else
3104 msg = xmlStrcat(msg,
3105 xmlSchemaFormatQName(&str,
3106 type->targetNamespace, type->name));
3107 msg = xmlStrcat(msg, BAD_CAST "'.");
3108 FREE_AND_NULL(str);
3109 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003110 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003111 if (node->type == XML_ATTRIBUTE_NODE)
3112 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3113 else
3114 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3115 "valid.");
3116 }
3117 if (expected) {
3118 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3119 msg = xmlStrcat(msg, BAD_CAST expected);
3120 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3121 } else
3122 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003123 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003124 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3125 else
3126 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3127 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003128 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003129 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003130 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003131 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003132 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003133 /* Cleanup. */
3134 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003135}
3136
William M. Brack2f2a6632004-08-20 23:09:47 +00003137/**
3138 * xmlSchemaPContentErr:
3139 * @ctxt: the schema parser context
3140 * @error: the error code
3141 * @onwerDes: the designation of the holder of the content
3142 * @ownerItem: the owner item of the holder of the content
3143 * @ownerElem: the node of the holder of the content
3144 * @child: the invalid child node
3145 * @message: the optional error message
3146 * @content: the optional string describing the correct content
3147 *
3148 * Reports an error concerning the content of a schema element.
3149 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003150static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003151xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003152 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003153 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003154 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003155 xmlNodePtr child,
3156 const char *message,
3157 const char *content)
3158{
3159 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003160
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003161 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003162 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3164 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003165 BAD_CAST des, BAD_CAST message);
3166 else {
3167 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003168 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3169 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003170 BAD_CAST des, BAD_CAST content);
3171 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003172 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3173 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003174 BAD_CAST des, NULL);
3175 }
3176 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003177 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003178}
3179
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003180/************************************************************************
3181 * *
3182 * Streamable error functions *
3183 * *
3184 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003185
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003186
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003187
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003188
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003189/************************************************************************
3190 * *
3191 * Validation helper functions *
3192 * *
3193 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003194
Daniel Veillardc0826a72004-08-10 14:17:33 +00003195
Daniel Veillard4255d502002-04-16 15:50:10 +00003196/************************************************************************
3197 * *
3198 * Allocation functions *
3199 * *
3200 ************************************************************************/
3201
3202/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003203 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003204 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003205 *
3206 * Allocate a new Schema structure.
3207 *
3208 * Returns the newly allocated structure or NULL in case or error
3209 */
3210static xmlSchemaPtr
3211xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3212{
3213 xmlSchemaPtr ret;
3214
3215 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3216 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003217 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 return (NULL);
3219 }
3220 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003221 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003222 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003223
3224 return (ret);
3225}
3226
3227/**
3228 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003229 *
3230 * Allocate a new Facet structure.
3231 *
3232 * Returns the newly allocated structure or NULL in case or error
3233 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003234xmlSchemaFacetPtr
3235xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003236{
3237 xmlSchemaFacetPtr ret;
3238
3239 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3240 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003241 return (NULL);
3242 }
3243 memset(ret, 0, sizeof(xmlSchemaFacet));
3244
3245 return (ret);
3246}
3247
3248/**
3249 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003250 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003251 * @node: a node
3252 *
3253 * Allocate a new annotation structure.
3254 *
3255 * Returns the newly allocated structure or NULL in case or error
3256 */
3257static xmlSchemaAnnotPtr
3258xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3259{
3260 xmlSchemaAnnotPtr ret;
3261
3262 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3263 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003264 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003265 return (NULL);
3266 }
3267 memset(ret, 0, sizeof(xmlSchemaAnnot));
3268 ret->content = node;
3269 return (ret);
3270}
3271
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003272static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003273xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003274{
3275 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003276
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003277 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3278 if (ret == NULL) {
3279 xmlSchemaPErrMemory(NULL,
3280 "allocating an item list structure", NULL);
3281 return (NULL);
3282 }
3283 memset(ret, 0, sizeof(xmlSchemaItemList));
3284 return (ret);
3285}
3286
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003287static void
3288xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3289{
3290 if (list->items != NULL) {
3291 xmlFree(list->items);
3292 list->items = NULL;
3293 }
3294 list->nbItems = 0;
3295 list->sizeItems = 0;
3296}
3297
3298static int
3299xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3300{
3301 if (list->items == NULL) {
3302 list->items = (void **) xmlMalloc(
3303 20 * sizeof(void *));
3304 if (list->items == NULL) {
3305 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3306 return(-1);
3307 }
3308 list->sizeItems = 20;
3309 } else if (list->sizeItems <= list->nbItems) {
3310 list->sizeItems *= 2;
3311 list->items = (void **) xmlRealloc(list->items,
3312 list->sizeItems * sizeof(void *));
3313 if (list->items == NULL) {
3314 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3315 list->sizeItems = 0;
3316 return(-1);
3317 }
3318 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003319 list->items[list->nbItems++] = item;
3320 return(0);
3321}
3322
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003323static int
3324xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3325 int initialSize,
3326 void *item)
3327{
3328 if (list->items == NULL) {
3329 if (initialSize <= 0)
3330 initialSize = 1;
3331 list->items = (void **) xmlMalloc(
3332 initialSize * sizeof(void *));
3333 if (list->items == NULL) {
3334 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3335 return(-1);
3336 }
3337 list->sizeItems = initialSize;
3338 } else if (list->sizeItems <= list->nbItems) {
3339 list->sizeItems *= 2;
3340 list->items = (void **) xmlRealloc(list->items,
3341 list->sizeItems * sizeof(void *));
3342 if (list->items == NULL) {
3343 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3344 list->sizeItems = 0;
3345 return(-1);
3346 }
3347 }
3348 list->items[list->nbItems++] = item;
3349 return(0);
3350}
3351
3352static int
3353xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3354{
3355 if (list->items == NULL) {
3356 list->items = (void **) xmlMalloc(
3357 20 * sizeof(void *));
3358 if (list->items == NULL) {
3359 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3360 return(-1);
3361 }
3362 list->sizeItems = 20;
3363 } else if (list->sizeItems <= list->nbItems) {
3364 list->sizeItems *= 2;
3365 list->items = (void **) xmlRealloc(list->items,
3366 list->sizeItems * sizeof(void *));
3367 if (list->items == NULL) {
3368 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3369 list->sizeItems = 0;
3370 return(-1);
3371 }
3372 }
3373 /*
3374 * Just append if the index is greater/equal than the item count.
3375 */
3376 if (idx >= list->nbItems) {
3377 list->items[list->nbItems++] = item;
3378 } else {
3379 int i;
3380 for (i = list->nbItems; i > idx; i--)
3381 list->items[i] = list->items[i-1];
3382 list->items[idx] = item;
3383 list->nbItems++;
3384 }
3385 return(0);
3386}
3387
3388#if 0 /* enable if ever needed */
3389static int
3390xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3391 int initialSize,
3392 void *item,
3393 int idx)
3394{
3395 if (list->items == NULL) {
3396 if (initialSize <= 0)
3397 initialSize = 1;
3398 list->items = (void **) xmlMalloc(
3399 initialSize * sizeof(void *));
3400 if (list->items == NULL) {
3401 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3402 return(-1);
3403 }
3404 list->sizeItems = initialSize;
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#endif
3430
3431static int
3432xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3433{
3434 int i;
3435 if ((list->items == NULL) || (idx >= list->nbItems)) {
3436 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3437 "index error.\n");
3438 return(-1);
3439 }
3440
3441 if (list->nbItems == 1) {
3442 /* TODO: Really free the list? */
3443 xmlFree(list->items);
3444 list->items = NULL;
3445 list->nbItems = 0;
3446 list->sizeItems = 0;
3447 } else if (list->nbItems -1 == idx) {
3448 list->nbItems--;
3449 } else {
3450 for (i = idx; i < list->nbItems -1; i++)
3451 list->items[i] = list->items[i+1];
3452 list->nbItems--;
3453 }
3454 return(0);
3455}
3456
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003457/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003458 * xmlSchemaItemListFree:
3459 * @annot: a schema type structure
3460 *
3461 * Deallocate a annotation structure
3462 */
3463static void
3464xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3465{
3466 if (list == NULL)
3467 return;
3468 if (list->items != NULL)
3469 xmlFree(list->items);
3470 xmlFree(list);
3471}
3472
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003473static void
3474xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003475{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003476 if (bucket == NULL)
3477 return;
3478 if (bucket->globals != NULL) {
3479 xmlSchemaComponentListFree(bucket->globals);
3480 xmlSchemaItemListFree(bucket->globals);
3481 }
3482 if (bucket->locals != NULL) {
3483 xmlSchemaComponentListFree(bucket->locals);
3484 xmlSchemaItemListFree(bucket->locals);
3485 }
3486 if (bucket->relations != NULL) {
3487 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3488 do {
3489 prev = cur;
3490 cur = cur->next;
3491 xmlFree(prev);
3492 } while (cur != NULL);
3493 }
3494 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3495 xmlFreeDoc(bucket->doc);
3496 }
3497 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003498 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3499 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003500 }
3501 xmlFree(bucket);
3502}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003503
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003504static xmlSchemaBucketPtr
3505xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003506 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003507{
3508 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003509 int size;
3510 xmlSchemaPtr mainSchema;
3511
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003512 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003513 PERROR_INT("xmlSchemaBucketCreate",
3514 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003515 return(NULL);
3516 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003517 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003518 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003519 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003520 size = sizeof(xmlSchemaInclude);
3521 else
3522 size = sizeof(xmlSchemaImport);
3523 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3524 if (ret == NULL) {
3525 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3526 return(NULL);
3527 }
3528 memset(ret, 0, size);
3529 ret->targetNamespace = targetNamespace;
3530 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003531 ret->globals = xmlSchemaItemListCreate();
3532 if (ret->globals == NULL) {
3533 xmlFree(ret);
3534 return(NULL);
3535 }
3536 ret->locals = xmlSchemaItemListCreate();
3537 if (ret->locals == NULL) {
3538 xmlFree(ret);
3539 return(NULL);
3540 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003541 /*
3542 * The following will assure that only the first bucket is marked as
3543 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3544 * For each following import buckets an xmlSchema will be created.
3545 */
3546 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003547 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003548 PERROR_INT("xmlSchemaBucketCreate",
3549 "first bucket but it's an include or redefine");
3550 xmlSchemaBucketFree(ret);
3551 return(NULL);
3552 }
3553 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3554 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3555 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003556 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3557 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003558 } else {
3559 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3560 PERROR_INT("xmlSchemaBucketCreate",
3561 "main bucket but it's not the first one");
3562 xmlSchemaBucketFree(ret);
3563 return(NULL);
3564 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3565 /*
3566 * Create a schema for imports.
3567 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003568 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3569 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003570 xmlSchemaBucketFree(ret);
3571 return(NULL);
3572 }
3573 }
3574 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003575 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576 int res;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003577 /* Imports go into the "schemasImports" slot of the main *schema*. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003578 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003579 mainSchema->schemasImports = xmlHashCreateDict(5,
3580 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003581 if (mainSchema->schemasImports == NULL) {
3582 xmlSchemaBucketFree(ret);
3583 return(NULL);
3584 }
3585 }
3586 if (targetNamespace == NULL)
3587 res = xmlHashAddEntry(mainSchema->schemasImports,
3588 XML_SCHEMAS_NO_NAMESPACE, ret);
3589 else
3590 res = xmlHashAddEntry(mainSchema->schemasImports,
3591 targetNamespace, ret);
3592 if (res != 0) {
3593 PERROR_INT("xmlSchemaBucketCreate",
3594 "failed to add the schema bucket to the hash");
3595 xmlSchemaBucketFree(ret);
3596 return(NULL);
3597 }
3598 } else {
3599 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003600 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3601 WXS_INCBUCKET(ret)->ownerImport =
3602 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003603 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003604 WXS_INCBUCKET(ret)->ownerImport =
3605 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003606
3607 /* Includes got into the "includes" slot of the *main* schema. */
3608 if (mainSchema->includes == NULL) {
3609 mainSchema->includes = xmlSchemaItemListCreate();
3610 if (mainSchema->includes == NULL) {
3611 xmlSchemaBucketFree(ret);
3612 return(NULL);
3613 }
3614 }
3615 xmlSchemaItemListAdd(mainSchema->includes, ret);
3616 }
3617 /*
3618 * Add to list of all buckets; this is used for lookup
3619 * during schema construction time only.
3620 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003621 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003622 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003623 return(ret);
3624}
3625
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003626static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003627xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003628{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003629 if (*list == NULL) {
3630 *list = xmlSchemaItemListCreate();
3631 if (*list == NULL)
3632 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003633 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003634 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003635 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003636}
3637
3638/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003639 * xmlSchemaFreeAnnot:
3640 * @annot: a schema type structure
3641 *
3642 * Deallocate a annotation structure
3643 */
3644static void
3645xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3646{
3647 if (annot == NULL)
3648 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003649 if (annot->next == NULL) {
3650 xmlFree(annot);
3651 } else {
3652 xmlSchemaAnnotPtr prev;
3653
3654 do {
3655 prev = annot;
3656 annot = annot->next;
3657 xmlFree(prev);
3658 } while (annot != NULL);
3659 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003660}
3661
3662/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003663 * xmlSchemaFreeNotation:
3664 * @schema: a schema notation structure
3665 *
3666 * Deallocate a Schema Notation structure.
3667 */
3668static void
3669xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3670{
3671 if (nota == NULL)
3672 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 xmlFree(nota);
3674}
3675
3676/**
3677 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003678 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003680 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003681 */
3682static void
3683xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3684{
3685 if (attr == NULL)
3686 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003687 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003688 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003689 if (attr->defVal != NULL)
3690 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003691 xmlFree(attr);
3692}
3693
3694/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003695 * xmlSchemaFreeAttributeUse:
3696 * @use: an attribute use
3697 *
3698 * Deallocates an attribute use structure.
3699 */
3700static void
3701xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3702{
3703 if (use == NULL)
3704 return;
3705 if (use->annot != NULL)
3706 xmlSchemaFreeAnnot(use->annot);
3707 if (use->defVal != NULL)
3708 xmlSchemaFreeValue(use->defVal);
3709 xmlFree(use);
3710}
3711
3712/**
3713 * xmlSchemaFreeAttributeUseProhib:
3714 * @prohib: an attribute use prohibition
3715 *
3716 * Deallocates an attribute use structure.
3717 */
3718static void
3719xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3720{
3721 if (prohib == NULL)
3722 return;
3723 xmlFree(prohib);
3724}
3725
3726/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003727 * xmlSchemaFreeWildcardNsSet:
3728 * set: a schema wildcard namespace
3729 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003730 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003731 */
3732static void
3733xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3734{
3735 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003736
Daniel Veillard3646d642004-06-02 19:19:14 +00003737 while (set != NULL) {
3738 next = set->next;
3739 xmlFree(set);
3740 set = next;
3741 }
3742}
3743
3744/**
3745 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003746 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003747 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003748 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003749 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003750void
Daniel Veillard3646d642004-06-02 19:19:14 +00003751xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3752{
3753 if (wildcard == NULL)
3754 return;
3755 if (wildcard->annot != NULL)
3756 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003757 if (wildcard->nsSet != NULL)
3758 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3759 if (wildcard->negNsSet != NULL)
3760 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003761 xmlFree(wildcard);
3762}
3763
3764/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 * xmlSchemaFreeAttributeGroup:
3766 * @schema: a schema attribute group structure
3767 *
3768 * Deallocate a Schema Attribute Group structure.
3769 */
3770static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003771xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003772{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003773 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003775 if (attrGr->annot != NULL)
3776 xmlSchemaFreeAnnot(attrGr->annot);
3777 if (attrGr->attrUses != NULL)
3778 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3779 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003780}
3781
3782/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003783 * xmlSchemaFreeQNameRef:
3784 * @item: a QName reference structure
3785 *
3786 * Deallocatea a QName reference structure.
3787 */
3788static void
3789xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3790{
3791 xmlFree(item);
3792}
3793
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003794/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003795 * xmlSchemaFreeTypeLinkList:
3796 * @alink: a type link
3797 *
3798 * Deallocate a list of types.
3799 */
3800static void
3801xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3802{
3803 xmlSchemaTypeLinkPtr next;
3804
3805 while (link != NULL) {
3806 next = link->next;
3807 xmlFree(link);
3808 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003809 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003810}
3811
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003812static void
3813xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3814{
3815 xmlSchemaIDCStateObjPtr next;
3816 while (sto != NULL) {
3817 next = sto->next;
3818 if (sto->history != NULL)
3819 xmlFree(sto->history);
3820 if (sto->xpathCtxt != NULL)
3821 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3822 xmlFree(sto);
3823 sto = next;
3824 }
3825}
3826
3827/**
3828 * xmlSchemaFreeIDC:
3829 * @idc: a identity-constraint definition
3830 *
3831 * Deallocates an identity-constraint definition.
3832 */
3833static void
3834xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3835{
3836 xmlSchemaIDCSelectPtr cur, prev;
3837
3838 if (idcDef == NULL)
3839 return;
3840 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003841 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003842 /* Selector */
3843 if (idcDef->selector != NULL) {
3844 if (idcDef->selector->xpathComp != NULL)
3845 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3846 xmlFree(idcDef->selector);
3847 }
3848 /* Fields */
3849 if (idcDef->fields != NULL) {
3850 cur = idcDef->fields;
3851 do {
3852 prev = cur;
3853 cur = cur->next;
3854 if (prev->xpathComp != NULL)
3855 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003856 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003857 } while (cur != NULL);
3858 }
3859 xmlFree(idcDef);
3860}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003861
Daniel Veillard01fa6152004-06-29 17:04:39 +00003862/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003863 * xmlSchemaFreeElement:
3864 * @schema: a schema element structure
3865 *
3866 * Deallocate a Schema Element structure.
3867 */
3868static void
3869xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3870{
3871 if (elem == NULL)
3872 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003873 if (elem->annot != NULL)
3874 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003875 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003877 if (elem->defVal != NULL)
3878 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 xmlFree(elem);
3880}
3881
3882/**
3883 * xmlSchemaFreeFacet:
3884 * @facet: a schema facet structure
3885 *
3886 * Deallocate a Schema Facet structure.
3887 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003888void
Daniel Veillard4255d502002-04-16 15:50:10 +00003889xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3890{
3891 if (facet == NULL)
3892 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003893 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003894 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003896 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003897 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 xmlFree(facet);
3900}
3901
3902/**
3903 * xmlSchemaFreeType:
3904 * @type: a schema type structure
3905 *
3906 * Deallocate a Schema Type structure.
3907 */
3908void
3909xmlSchemaFreeType(xmlSchemaTypePtr type)
3910{
3911 if (type == NULL)
3912 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003913 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003914 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003915 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003916 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003917
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003918 facet = type->facets;
3919 while (facet != NULL) {
3920 next = facet->next;
3921 xmlSchemaFreeFacet(facet);
3922 facet = next;
3923 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003924 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003925 if (type->attrUses != NULL)
3926 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003927 if (type->memberTypes != NULL)
3928 xmlSchemaFreeTypeLinkList(type->memberTypes);
3929 if (type->facetSet != NULL) {
3930 xmlSchemaFacetLinkPtr next, link;
3931
3932 link = type->facetSet;
3933 do {
3934 next = link->next;
3935 xmlFree(link);
3936 link = next;
3937 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003938 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003939 if (type->contModel != NULL)
3940 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003941 xmlFree(type);
3942}
3943
3944/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003945 * xmlSchemaFreeModelGroupDef:
3946 * @item: a schema model group definition
3947 *
3948 * Deallocates a schema model group definition.
3949 */
3950static void
3951xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3952{
3953 if (item->annot != NULL)
3954 xmlSchemaFreeAnnot(item->annot);
3955 xmlFree(item);
3956}
3957
3958/**
3959 * xmlSchemaFreeModelGroup:
3960 * @item: a schema model group
3961 *
3962 * Deallocates a schema model group structure.
3963 */
3964static void
3965xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3966{
3967 if (item->annot != NULL)
3968 xmlSchemaFreeAnnot(item->annot);
3969 xmlFree(item);
3970}
3971
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003972static void
3973xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3974{
3975 if ((list == NULL) || (list->nbItems == 0))
3976 return;
3977 {
3978 xmlSchemaTreeItemPtr item;
3979 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3980 int i;
3981
3982 for (i = 0; i < list->nbItems; i++) {
3983 item = items[i];
3984 if (item == NULL)
3985 continue;
3986 switch (item->type) {
3987 case XML_SCHEMA_TYPE_SIMPLE:
3988 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003989 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003990 break;
3991 case XML_SCHEMA_TYPE_ATTRIBUTE:
3992 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003993 break;
3994 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
3995 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
3996 break;
3997 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
3998 xmlSchemaFreeAttributeUseProhib(
3999 (xmlSchemaAttributeUseProhibPtr) item);
4000 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004001 case XML_SCHEMA_TYPE_ELEMENT:
4002 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4003 break;
4004 case XML_SCHEMA_TYPE_PARTICLE:
4005 if (item->annot != NULL)
4006 xmlSchemaFreeAnnot(item->annot);
4007 xmlFree(item);
4008 break;
4009 case XML_SCHEMA_TYPE_SEQUENCE:
4010 case XML_SCHEMA_TYPE_CHOICE:
4011 case XML_SCHEMA_TYPE_ALL:
4012 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4013 break;
4014 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4015 xmlSchemaFreeAttributeGroup(
4016 (xmlSchemaAttributeGroupPtr) item);
4017 break;
4018 case XML_SCHEMA_TYPE_GROUP:
4019 xmlSchemaFreeModelGroupDef(
4020 (xmlSchemaModelGroupDefPtr) item);
4021 break;
4022 case XML_SCHEMA_TYPE_ANY:
4023 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4024 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4025 break;
4026 case XML_SCHEMA_TYPE_IDC_KEY:
4027 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4028 case XML_SCHEMA_TYPE_IDC_KEYREF:
4029 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4030 break;
4031 case XML_SCHEMA_TYPE_NOTATION:
4032 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4033 break;
4034 case XML_SCHEMA_EXTRA_QNAMEREF:
4035 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4036 break;
4037 default: {
4038 /* TODO: This should never be hit. */
4039 xmlSchemaPSimpleInternalErr(NULL,
4040 "Internal error: xmlSchemaComponentListFree, "
4041 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004042 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004043 }
4044 break;
4045 }
4046 }
4047 list->nbItems = 0;
4048 }
4049}
4050
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004051/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004052 * xmlSchemaFree:
4053 * @schema: a schema structure
4054 *
4055 * Deallocate a Schema structure.
4056 */
4057void
4058xmlSchemaFree(xmlSchemaPtr schema)
4059{
4060 if (schema == NULL)
4061 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004062 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004063 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004064 TODO
4065 /*
4066 * Note that those slots are not responsible for freeing
4067 * schema components anymore; this will now be done by
4068 * the schema buckets.
4069 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004070 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004071 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004073 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004074 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004075 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004076 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004077 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004078 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004079 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004080 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004081 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004082 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004083 xmlHashFree(schema->idcDef, NULL);
4084
Daniel Veillard1d913862003-11-21 00:28:39 +00004085 if (schema->schemasImports != NULL)
4086 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004087 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004088 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004089 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4090 int i;
4091 for (i = 0; i < list->nbItems; i++) {
4092 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4093 }
4094 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004095 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004097 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004098 /* Never free the doc here, since this will be done by the buckets. */
4099
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004100 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 xmlFree(schema);
4102}
4103
4104/************************************************************************
4105 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004106 * Debug functions *
4107 * *
4108 ************************************************************************/
4109
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004110#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004111
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004112static void
4113xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4114
Daniel Veillard4255d502002-04-16 15:50:10 +00004115/**
4116 * xmlSchemaElementDump:
4117 * @elem: an element
4118 * @output: the file output
4119 *
4120 * Dump the element
4121 */
4122static void
4123xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004124 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004125 const xmlChar * namespace ATTRIBUTE_UNUSED,
4126 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004127{
4128 if (elem == NULL)
4129 return;
4130
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004131
4132 fprintf(output, "Element");
4133 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4134 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004135 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004136 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004137 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004138 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004139#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004141 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004142 if (elem->maxOccurs >= UNBOUNDED)
4143 fprintf(output, "max: unbounded\n");
4144 else if (elem->maxOccurs != 1)
4145 fprintf(output, "max: %d\n", elem->maxOccurs);
4146 else
4147 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004148 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004149#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004150 /*
4151 * Misc other properties.
4152 */
4153 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4154 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4155 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004156 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004157 fprintf(output, " props: ");
4158 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4159 fprintf(output, "[fixed] ");
4160 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4161 fprintf(output, "[default] ");
4162 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4163 fprintf(output, "[abstract] ");
4164 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4165 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004166 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004167 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004168 /*
4169 * Default/fixed value.
4170 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004172 fprintf(output, " value: '%s'\n", elem->value);
4173 /*
4174 * Type.
4175 */
4176 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004177 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004178 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004179 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004180 else
4181 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004182 } else if (elem->subtypes != NULL) {
4183 /*
4184 * Dump local types.
4185 */
4186 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004187 }
4188 /*
4189 * Substitution group.
4190 */
4191 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004192 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004193 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004194 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004195 else
4196 fprintf(output, "\n");
4197 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004198}
4199
4200/**
4201 * xmlSchemaAnnotDump:
4202 * @output: the file output
4203 * @annot: a annotation
4204 *
4205 * Dump the annotation
4206 */
4207static void
4208xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4209{
4210 xmlChar *content;
4211
4212 if (annot == NULL)
4213 return;
4214
4215 content = xmlNodeGetContent(annot->content);
4216 if (content != NULL) {
4217 fprintf(output, " Annot: %s\n", content);
4218 xmlFree(content);
4219 } else
4220 fprintf(output, " Annot: empty\n");
4221}
4222
4223/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004224 * xmlSchemaContentModelDump:
4225 * @particle: the schema particle
4226 * @output: the file output
4227 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004228 *
4229 * Dump a SchemaType structure
4230 */
4231static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004232xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4233{
4234 xmlChar *str = NULL;
4235 xmlSchemaTreeItemPtr term;
4236 char shift[100];
4237 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004238
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004239 if (particle == NULL)
4240 return;
4241 for (i = 0;((i < depth) && (i < 25));i++)
4242 shift[2 * i] = shift[2 * i + 1] = ' ';
4243 shift[2 * i] = shift[2 * i + 1] = 0;
4244 fprintf(output, shift);
4245 if (particle->children == NULL) {
4246 fprintf(output, "MISSING particle term\n");
4247 return;
4248 }
4249 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004250 if (term == NULL) {
4251 fprintf(output, "(NULL)");
4252 } else {
4253 switch (term->type) {
4254 case XML_SCHEMA_TYPE_ELEMENT:
4255 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4256 ((xmlSchemaElementPtr)term)->targetNamespace,
4257 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004258 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004259 break;
4260 case XML_SCHEMA_TYPE_SEQUENCE:
4261 fprintf(output, "SEQUENCE");
4262 break;
4263 case XML_SCHEMA_TYPE_CHOICE:
4264 fprintf(output, "CHOICE");
4265 break;
4266 case XML_SCHEMA_TYPE_ALL:
4267 fprintf(output, "ALL");
4268 break;
4269 case XML_SCHEMA_TYPE_ANY:
4270 fprintf(output, "ANY");
4271 break;
4272 default:
4273 fprintf(output, "UNKNOWN\n");
4274 return;
4275 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004276 }
4277 if (particle->minOccurs != 1)
4278 fprintf(output, " min: %d", particle->minOccurs);
4279 if (particle->maxOccurs >= UNBOUNDED)
4280 fprintf(output, " max: unbounded");
4281 else if (particle->maxOccurs != 1)
4282 fprintf(output, " max: %d", particle->maxOccurs);
4283 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004284 if (term &&
4285 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4286 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4287 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4288 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004289 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4290 output, depth +1);
4291 }
4292 if (particle->next != NULL)
4293 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4294 output, depth);
4295}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004296
4297/**
4298 * xmlSchemaAttrUsesDump:
4299 * @uses: attribute uses list
4300 * @output: the file output
4301 *
4302 * Dumps a list of attribute use components.
4303 */
4304static void
4305xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4306{
4307 xmlSchemaAttributeUsePtr use;
4308 xmlSchemaAttributeUseProhibPtr prohib;
4309 xmlSchemaQNameRefPtr ref;
4310 const xmlChar *name, *tns;
4311 xmlChar *str = NULL;
4312 int i;
4313
4314 if ((uses == NULL) || (uses->nbItems == 0))
4315 return;
4316
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004317 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004318 for (i = 0; i < uses->nbItems; i++) {
4319 use = uses->items[i];
4320 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4321 fprintf(output, " [prohibition] ");
4322 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4323 name = prohib->name;
4324 tns = prohib->targetNamespace;
4325 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4326 fprintf(output, " [reference] ");
4327 ref = (xmlSchemaQNameRefPtr) use;
4328 name = ref->name;
4329 tns = ref->targetNamespace;
4330 } else {
4331 fprintf(output, " [use] ");
4332 name = WXS_ATTRUSE_DECL_NAME(use);
4333 tns = WXS_ATTRUSE_DECL_TNS(use);
4334 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004335 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004336 (const char *) xmlSchemaFormatQName(&str, tns, name));
4337 FREE_AND_NULL(str);
4338 }
4339}
4340
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004341/**
4342 * xmlSchemaTypeDump:
4343 * @output: the file output
4344 * @type: a type structure
4345 *
4346 * Dump a SchemaType structure
4347 */
4348static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004349xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4350{
4351 if (type == NULL) {
4352 fprintf(output, "Type: NULL\n");
4353 return;
4354 }
4355 fprintf(output, "Type: ");
4356 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004357 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004359 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004360 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004361 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 switch (type->type) {
4363 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004364 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004365 break;
4366 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004367 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004368 break;
4369 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004370 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 break;
4372 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004373 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 break;
4375 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004376 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 break;
4378 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004379 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004380 break;
4381 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004382 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004383 break;
4384 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004385 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004386 break;
4387 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004388 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004389 break;
4390 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004391 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004392 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004393 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004394 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004397 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 break;
4399 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004400 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004401 break;
4402 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004403 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 break;
4405 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004406 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004407 break;
4408 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004409 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410 break;
4411 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004412 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413 break;
4414 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004415 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004416 break;
4417 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004418 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004419 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004420 }
4421 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004422 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004423 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004424 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004425 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004426 else
4427 fprintf(output, "\n");
4428 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004429 if (type->attrUses != NULL)
4430 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004431 if (type->annot != NULL)
4432 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004433#ifdef DUMP_CONTENT_MODEL
4434 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4435 (type->subtypes != NULL)) {
4436 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4437 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004439#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004440}
4441
4442/**
4443 * xmlSchemaDump:
4444 * @output: the file output
4445 * @schema: a schema structure
4446 *
4447 * Dump a Schema structure.
4448 */
4449void
4450xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4451{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004452 if (output == NULL)
4453 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 if (schema == NULL) {
4455 fprintf(output, "Schemas: NULL\n");
4456 return;
4457 }
4458 fprintf(output, "Schemas: ");
4459 if (schema->name != NULL)
4460 fprintf(output, "%s, ", schema->name);
4461 else
4462 fprintf(output, "no name, ");
4463 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004464 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 else
4466 fprintf(output, "no target namespace");
4467 fprintf(output, "\n");
4468 if (schema->annot != NULL)
4469 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4471 output);
4472 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004474}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004475
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004476#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004477/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004478 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004479 * @vctxt: the WXS validation context
4480 *
4481 * Displays the current IDC table for debug purposes.
4482 */
4483static void
4484xmlSchemaDebugDumpIDCTable(FILE * output,
4485 const xmlChar *namespaceName,
4486 const xmlChar *localName,
4487 xmlSchemaPSVIIDCBindingPtr bind)
4488{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004489 xmlChar *str = NULL;
4490 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004491 xmlSchemaPSVIIDCNodePtr tab;
4492 xmlSchemaPSVIIDCKeyPtr key;
4493 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004494
4495 fprintf(output, "IDC: TABLES on %s\n",
4496 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004497 FREE_AND_NULL(str)
4498
4499 if (bind == NULL)
4500 return;
4501 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004502 fprintf(output, "IDC: BINDING %s\n",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004503 xmlSchemaGetComponentQName(&str,
4504 bind->definition));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004506 for (i = 0; i < bind->nbNodes; i++) {
4507 tab = bind->nodeTable[i];
4508 fprintf(output, " ( ");
4509 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004510 key = tab->keys[j];
4511 if ((key != NULL) && (key->val != NULL)) {
4512 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004513 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004514 fprintf(output, "\"%s\" ", value);
4515 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004516 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004518 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004519 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004520 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004521 else
4522 fprintf(output, "(key missing), ");
4523 }
4524 fprintf(output, ")\n");
4525 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004526 if (bind->dupls && bind->dupls->nbItems) {
4527 fprintf(output, "IDC: dupls:\n");
4528 for (i = 0; i < bind->dupls->nbItems; i++) {
4529 tab = bind->dupls->items[i];
4530 fprintf(output, " ( ");
4531 for (j = 0; j < bind->definition->nbFields; j++) {
4532 key = tab->keys[j];
4533 if ((key != NULL) && (key->val != NULL)) {
4534 res = xmlSchemaGetCanonValue(key->val, &value);
4535 if (res >= 0)
4536 fprintf(output, "\"%s\" ", value);
4537 else
4538 fprintf(output, "CANON-VALUE-FAILED ");
4539 if (res == 0)
4540 FREE_AND_NULL(value)
4541 } else if (key != NULL)
4542 fprintf(output, "(no val), ");
4543 else
4544 fprintf(output, "(key missing), ");
4545 }
4546 fprintf(output, ")\n");
4547 }
4548 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004549 bind = bind->next;
4550 } while (bind != NULL);
4551}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004552#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004553#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004554
4555/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004556 * *
4557 * Utilities *
4558 * *
4559 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004560
Daniel Veillardc0826a72004-08-10 14:17:33 +00004561/**
4562 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004563 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004564 * @name: the name of the attribute
4565 *
4566 * Seeks an attribute with a name of @name in
4567 * no namespace.
4568 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004569 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004570 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004571static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004572xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004573{
4574 xmlAttrPtr prop;
4575
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004576 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004577 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004578 prop = node->properties;
4579 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004581 return(prop);
4582 prop = prop->next;
4583 }
4584 return (NULL);
4585}
4586
4587/**
4588 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004589 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004590 * @uri: the uri
4591 * @name: the name of the attribute
4592 *
4593 * Seeks an attribute with a local name of @name and
4594 * a namespace URI of @uri.
4595 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004596 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 */
4598static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004599xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004600{
4601 xmlAttrPtr prop;
4602
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004603 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004604 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004605 prop = node->properties;
4606 while (prop != NULL) {
4607 if ((prop->ns != NULL) &&
4608 xmlStrEqual(prop->name, BAD_CAST name) &&
4609 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004610 return(prop);
4611 prop = prop->next;
4612 }
4613 return (NULL);
4614}
4615
4616static const xmlChar *
4617xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4618{
4619 xmlChar *val;
4620 const xmlChar *ret;
4621
4622 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004623 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004624 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004625 ret = xmlDictLookup(ctxt->dict, val, -1);
4626 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004627 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004628}
4629
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004630static const xmlChar *
4631xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4632{
4633 return((const xmlChar*) xmlNodeGetContent(node));
4634}
4635
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004636/**
4637 * xmlSchemaGetProp:
4638 * @ctxt: the parser context
4639 * @node: the node
4640 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004641 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004642 * Read a attribute value and internalize the string
4643 *
4644 * Returns the string or NULL if not present.
4645 */
4646static const xmlChar *
4647xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4648 const char *name)
4649{
4650 xmlChar *val;
4651 const xmlChar *ret;
4652
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004653 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004654 if (val == NULL)
4655 return(NULL);
4656 ret = xmlDictLookup(ctxt->dict, val, -1);
4657 xmlFree(val);
4658 return(ret);
4659}
4660
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004661/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004662 * *
4663 * Parsing functions *
4664 * *
4665 ************************************************************************/
4666
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004667#define WXS_FIND_GLOBAL_ITEM(slot) \
4668 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4669 ret = xmlHashLookup(schema->slot, name); \
4670 if (ret != NULL) goto exit; \
4671 } \
4672 if (xmlHashSize(schema->schemasImports) > 1) { \
4673 xmlSchemaImportPtr import; \
4674 if (nsName == NULL) \
4675 import = xmlHashLookup(schema->schemasImports, \
4676 XML_SCHEMAS_NO_NAMESPACE); \
4677 else \
4678 import = xmlHashLookup(schema->schemasImports, nsName); \
4679 if (import == NULL) \
4680 goto exit; \
4681 ret = xmlHashLookup(import->schema->slot, name); \
4682 }
4683
Daniel Veillard4255d502002-04-16 15:50:10 +00004684/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004685 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004686 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004687 * @name: the element name
4688 * @ns: the element namespace
4689 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004690 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004691 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004692 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004693 */
4694static xmlSchemaElementPtr
4695xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004696 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004697{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004698 xmlSchemaElementPtr ret = NULL;
4699
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004700 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004701 return(NULL);
4702 if (schema != NULL) {
4703 WXS_FIND_GLOBAL_ITEM(elemDecl)
4704 }
4705exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004706#ifdef DEBUG
4707 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004708 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004709 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004710 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004711 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004712 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004713 }
4714#endif
4715 return (ret);
4716}
4717
4718/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004720 * @schema: the main schema
4721 * @name: the type's name
4722 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004723 *
4724 * Lookup a type in the schemas or the predefined types
4725 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004726 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004727 */
4728static xmlSchemaTypePtr
4729xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004730 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004731{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004732 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004733
4734 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004735 return (NULL);
4736 /* First try the built-in types. */
4737 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4738 ret = xmlSchemaGetPredefinedType(name, nsName);
4739 if (ret != NULL)
4740 goto exit;
4741 /*
4742 * Note that we try the parsed schemas as well here
4743 * since one might have parsed the S4S, which contain more
4744 * than the built-in types.
4745 * TODO: Can we optimize this?
4746 */
4747 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004748 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004749 WXS_FIND_GLOBAL_ITEM(typeDecl)
4750 }
4751exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004752
Daniel Veillard4255d502002-04-16 15:50:10 +00004753#ifdef DEBUG
4754 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004755 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004756 fprintf(stderr, "Unable to lookup type %s", name);
4757 else
4758 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004759 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004760 }
4761#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004762 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004763}
4764
Daniel Veillard3646d642004-06-02 19:19:14 +00004765/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004766 * xmlSchemaGetAttributeDecl:
4767 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004768 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004769 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004770 *
4771 * Lookup a an attribute in the schema or imported schemas
4772 *
4773 * Returns the attribute declaration or NULL if not found.
4774 */
4775static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004776xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004777 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004778{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004779 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004780
4781 if ((name == NULL) || (schema == NULL))
4782 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004783 if (schema != NULL) {
4784 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004785 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004786exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004787#ifdef DEBUG
4788 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004789 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004790 fprintf(stderr, "Unable to lookup attribute %s", name);
4791 else
4792 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004793 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004794 }
4795#endif
4796 return (ret);
4797}
4798
4799/**
4800 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004801 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004802 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004803 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004804 *
4805 * Lookup a an attribute group in the schema or imported schemas
4806 *
4807 * Returns the attribute group definition or NULL if not found.
4808 */
4809static xmlSchemaAttributeGroupPtr
4810xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004811 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004812{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004813 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004814
4815 if ((name == NULL) || (schema == NULL))
4816 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004817 if (schema != NULL) {
4818 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4819 }
4820exit:
4821 /* TODO:
4822 if ((ret != NULL) && (ret->redef != NULL)) {
4823 * Return the last redefinition. *
4824 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004826 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004827#ifdef DEBUG
4828 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004829 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004830 fprintf(stderr, "Unable to lookup attribute group %s", name);
4831 else
4832 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004833 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004834 }
4835#endif
4836 return (ret);
4837}
4838
4839/**
4840 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004841 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004842 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004843 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004844 *
4845 * Lookup a group in the schema or imported schemas
4846 *
4847 * Returns the group definition or NULL if not found.
4848 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004849static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004850xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004851 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004852{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004853 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004854
4855 if ((name == NULL) || (schema == NULL))
4856 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004857 if (schema != NULL) {
4858 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004859 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004860exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004861
Daniel Veillard3646d642004-06-02 19:19:14 +00004862#ifdef DEBUG
4863 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004864 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 fprintf(stderr, "Unable to lookup group %s", name);
4866 else
4867 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004868 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004869 }
4870#endif
4871 return (ret);
4872}
4873
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004874static xmlSchemaNotationPtr
4875xmlSchemaGetNotation(xmlSchemaPtr schema,
4876 const xmlChar *name,
4877 const xmlChar *nsName)
4878{
4879 xmlSchemaNotationPtr ret = NULL;
4880
4881 if ((name == NULL) || (schema == NULL))
4882 return (NULL);
4883 if (schema != NULL) {
4884 WXS_FIND_GLOBAL_ITEM(notaDecl)
4885 }
4886exit:
4887 return (ret);
4888}
4889
4890static xmlSchemaIDCPtr
4891xmlSchemaGetIDC(xmlSchemaPtr schema,
4892 const xmlChar *name,
4893 const xmlChar *nsName)
4894{
4895 xmlSchemaIDCPtr ret = NULL;
4896
4897 if ((name == NULL) || (schema == NULL))
4898 return (NULL);
4899 if (schema != NULL) {
4900 WXS_FIND_GLOBAL_ITEM(idcDef)
4901 }
4902exit:
4903 return (ret);
4904}
4905
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004906/**
4907 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004908 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004909 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004910 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004911 *
4912 * Lookup a group in the schema or imported schemas
4913 *
4914 * Returns the group definition or NULL if not found.
4915 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004916static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004917xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4918 xmlSchemaTypeType itemType,
4919 const xmlChar *name,
4920 const xmlChar *targetNs)
4921{
4922 switch (itemType) {
4923 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004924 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004925 name, targetNs));
4926 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004927 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004928 name, targetNs));
4929 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004930 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004931 return (NULL);
4932 }
4933}
4934
Daniel Veillard4255d502002-04-16 15:50:10 +00004935/************************************************************************
4936 * *
4937 * Parsing functions *
4938 * *
4939 ************************************************************************/
4940
4941#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004942 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004943
4944/**
4945 * xmlSchemaIsBlank:
4946 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004947 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 *
4949 * Check if a string is ignorable
4950 *
4951 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4952 */
4953static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004955{
Daniel Veillard4255d502002-04-16 15:50:10 +00004956 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004958 if (len < 0) {
4959 while (*str != 0) {
4960 if (!(IS_BLANK_CH(*str)))
4961 return (0);
4962 str++;
4963 }
4964 } else while ((*str != 0) && (len != 0)) {
4965 if (!(IS_BLANK_CH(*str)))
4966 return (0);
4967 str++;
4968 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004969 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004970
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004972}
4973
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004974#define WXS_COMP_NAME(c, t) ((t) (c))->name
4975#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4976/*
4977* xmlSchemaFindRedefCompInGraph:
4978* ATTENTION TODO: This uses pointer comp. for strings.
4979*/
4980static xmlSchemaBasicItemPtr
4981xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4982 xmlSchemaTypeType type,
4983 const xmlChar *name,
4984 const xmlChar *nsName)
4985{
4986 xmlSchemaBasicItemPtr ret;
4987 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004988
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004989 if ((bucket == NULL) || (name == NULL))
4990 return(NULL);
4991 if ((bucket->globals == NULL) ||
4992 (bucket->globals->nbItems == 0))
4993 goto subschemas;
4994 /*
4995 * Search in global components.
4996 */
4997 for (i = 0; i < bucket->globals->nbItems; i++) {
4998 ret = bucket->globals->items[i];
4999 if (ret->type == type) {
5000 switch (type) {
5001 case XML_SCHEMA_TYPE_COMPLEX:
5002 case XML_SCHEMA_TYPE_SIMPLE:
5003 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5004 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5005 nsName))
5006 {
5007 return(ret);
5008 }
5009 break;
5010 case XML_SCHEMA_TYPE_GROUP:
5011 if ((WXS_COMP_NAME(ret,
5012 xmlSchemaModelGroupDefPtr) == name) &&
5013 (WXS_COMP_TNS(ret,
5014 xmlSchemaModelGroupDefPtr) == nsName))
5015 {
5016 return(ret);
5017 }
5018 break;
5019 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5020 if ((WXS_COMP_NAME(ret,
5021 xmlSchemaAttributeGroupPtr) == name) &&
5022 (WXS_COMP_TNS(ret,
5023 xmlSchemaAttributeGroupPtr) == nsName))
5024 {
5025 return(ret);
5026 }
5027 default:
5028 /* Should not be hit. */
5029 return(NULL);
5030 }
5031 }
5032 }
5033subschemas:
5034 /*
5035 * Process imported/included schemas.
5036 */
5037 if (bucket->relations != NULL) {
5038 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5039
5040 /*
5041 * TODO: Marking the bucket will not avoid multiple searches
5042 * in the same schema, but avoids at least circularity.
5043 */
5044 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5045 do {
5046 if ((rel->bucket != NULL) &&
5047 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5048 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5049 type, name, nsName);
5050 if (ret != NULL)
5051 return(ret);
5052 }
5053 rel = rel->next;
5054 } while (rel != NULL);
5055 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5056 }
5057 return(NULL);
5058}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005059
5060/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005061 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005062 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 * @schema: the schema being built
5064 * @name: the item name
5065 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005067 * *WARNING* this interface is highly subject to change
5068 *
5069 * Returns the new struture or NULL in case of error
5070 */
5071static xmlSchemaNotationPtr
5072xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005073 const xmlChar *name, const xmlChar *nsName,
5074 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005075{
5076 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005077
5078 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5079 return (NULL);
5080
Daniel Veillard4255d502002-04-16 15:50:10 +00005081 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5082 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005083 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005084 return (NULL);
5085 }
5086 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005087 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005088 ret->name = name;
5089 ret->targetNamespace = nsName;
5090 /* TODO: do we need the node to be set?
5091 * ret->node = node;*/
5092 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005093 return (ret);
5094}
5095
Daniel Veillard4255d502002-04-16 15:50:10 +00005096/**
5097 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005098 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005099 * @schema: the schema being built
5100 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005101 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005102 *
5103 * Add an XML schema Attrribute declaration
5104 * *WARNING* this interface is highly subject to change
5105 *
5106 * Returns the new struture or NULL in case of error
5107 */
5108static xmlSchemaAttributePtr
5109xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005110 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005111 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005112{
5113 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005114
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005115 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005116 return (NULL);
5117
5118 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5119 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005120 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005121 return (NULL);
5122 }
5123 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005124 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5125 ret->node = node;
5126 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005127 ret->targetNamespace = nsName;
5128
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005129 if (topLevel)
5130 WXS_ADD_GLOBAL(ctxt, ret);
5131 else
5132 WXS_ADD_LOCAL(ctxt, ret);
5133 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005134 return (ret);
5135}
5136
5137/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005138 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005139 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005140 * @schema: the schema being built
5141 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005142 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005143 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005144 * Add an XML schema Attrribute declaration
5145 * *WARNING* this interface is highly subject to change
5146 *
5147 * Returns the new struture or NULL in case of error
5148 */
5149static xmlSchemaAttributeUsePtr
5150xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5151 xmlNodePtr node)
5152{
5153 xmlSchemaAttributeUsePtr ret = NULL;
5154
5155 if (pctxt == NULL)
5156 return (NULL);
5157
5158 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5159 if (ret == NULL) {
5160 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5161 return (NULL);
5162 }
5163 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5164 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5165 ret->node = node;
5166
5167 WXS_ADD_LOCAL(pctxt, ret);
5168 return (ret);
5169}
5170
5171/*
5172* xmlSchemaAddRedef:
5173*
5174* Adds a redefinition information. This is used at a later stage to:
5175* resolve references to the redefined components and to check constraints.
5176*/
5177static xmlSchemaRedefPtr
5178xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5179 xmlSchemaBucketPtr targetBucket,
5180 void *item,
5181 const xmlChar *refName,
5182 const xmlChar *refTargetNs)
5183{
5184 xmlSchemaRedefPtr ret;
5185
5186 ret = (xmlSchemaRedefPtr)
5187 xmlMalloc(sizeof(xmlSchemaRedef));
5188 if (ret == NULL) {
5189 xmlSchemaPErrMemory(pctxt,
5190 "allocating redefinition info", NULL);
5191 return (NULL);
5192 }
5193 memset(ret, 0, sizeof(xmlSchemaRedef));
5194 ret->item = item;
5195 ret->targetBucket = targetBucket;
5196 ret->refName = refName;
5197 ret->refTargetNs = refTargetNs;
5198 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5199 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5200 else
5201 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5202 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5203
5204 return (ret);
5205}
5206
5207/**
5208 * xmlSchemaAddAttributeGroupDefinition:
5209 * @ctxt: a schema parser context
5210 * @schema: the schema being built
5211 * @name: the item name
5212 * @nsName: the target namespace
5213 * @node: the corresponding node
5214 *
5215 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 *
5217 * Returns the new struture or NULL in case of error
5218 */
5219static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005220xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5221 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5222 const xmlChar *name,
5223 const xmlChar *nsName,
5224 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005225{
5226 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005227
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005228 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005229 return (NULL);
5230
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005231 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005232 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005234 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005235 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 }
5237 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005238 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005239 ret->name = name;
5240 ret->targetNamespace = nsName;
5241 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005242
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005243 /* TODO: Remove the flag. */
5244 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5245 if (pctxt->isRedefine) {
5246 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5247 ret, name, nsName);
5248 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005249 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005250 return(NULL);
5251 }
5252 pctxt->redefCounter = 0;
5253 }
5254 WXS_ADD_GLOBAL(pctxt, ret);
5255 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005256 return (ret);
5257}
5258
5259/**
5260 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005261 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005262 * @schema: the schema being built
5263 * @name: the type name
5264 * @namespace: the type namespace
5265 *
5266 * Add an XML schema Element declaration
5267 * *WARNING* this interface is highly subject to change
5268 *
5269 * Returns the new struture or NULL in case of error
5270 */
5271static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005272xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005273 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005274 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005275{
5276 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005277
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005278 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005279 return (NULL);
5280
Daniel Veillard4255d502002-04-16 15:50:10 +00005281 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5282 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005283 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005284 return (NULL);
5285 }
5286 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005287 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5288 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005289 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005290 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005291
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005292 if (topLevel)
5293 WXS_ADD_GLOBAL(ctxt, ret);
5294 else
5295 WXS_ADD_LOCAL(ctxt, ret);
5296 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005297 return (ret);
5298}
5299
5300/**
5301 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005302 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005303 * @schema: the schema being built
5304 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005305 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005307 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005308 * *WARNING* this interface is highly subject to change
5309 *
5310 * Returns the new struture or NULL in case of error
5311 */
5312static xmlSchemaTypePtr
5313xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005314 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005315 const xmlChar * name, const xmlChar * nsName,
5316 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005317{
5318 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005320 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005321 return (NULL);
5322
5323 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5324 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005325 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005326 return (NULL);
5327 }
5328 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005329 ret->type = type;
5330 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005331 ret->targetNamespace = nsName;
5332 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005333 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005334 if (ctxt->isRedefine) {
5335 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5336 ret, name, nsName);
5337 if (ctxt->redef == NULL) {
5338 xmlFree(ret);
5339 return(NULL);
5340 }
5341 ctxt->redefCounter = 0;
5342 }
5343 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005344 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005345 WXS_ADD_LOCAL(ctxt, ret);
5346 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005347 return (ret);
5348}
5349
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005350static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005351xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005352 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005353 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005354 const xmlChar *refNs)
5355{
5356 xmlSchemaQNameRefPtr ret;
5357
5358 ret = (xmlSchemaQNameRefPtr)
5359 xmlMalloc(sizeof(xmlSchemaQNameRef));
5360 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005361 xmlSchemaPErrMemory(pctxt,
5362 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005363 return (NULL);
5364 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005365 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005366 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5367 ret->name = refName;
5368 ret->targetNamespace = refNs;
5369 ret->item = NULL;
5370 ret->itemType = refType;
5371 /*
5372 * Store the reference item in the schema.
5373 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005374 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005375 return (ret);
5376}
5377
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005378static xmlSchemaAttributeUseProhibPtr
5379xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5380{
5381 xmlSchemaAttributeUseProhibPtr ret;
5382
5383 ret = (xmlSchemaAttributeUseProhibPtr)
5384 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5385 if (ret == NULL) {
5386 xmlSchemaPErrMemory(pctxt,
5387 "allocating attribute use prohibition", NULL);
5388 return (NULL);
5389 }
5390 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5391 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5392 WXS_ADD_LOCAL(pctxt, ret);
5393 return (ret);
5394}
5395
5396
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005397/**
5398 * xmlSchemaAddModelGroup:
5399 * @ctxt: a schema parser context
5400 * @schema: the schema being built
5401 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005402 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005403 *
5404 * Adds a schema model group
5405 * *WARNING* this interface is highly subject to change
5406 *
5407 * Returns the new struture or NULL in case of error
5408 */
5409static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005410xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5411 xmlSchemaPtr schema,
5412 xmlSchemaTypeType type,
5413 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005414{
5415 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005416
5417 if ((ctxt == NULL) || (schema == NULL))
5418 return (NULL);
5419
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005420 ret = (xmlSchemaModelGroupPtr)
5421 xmlMalloc(sizeof(xmlSchemaModelGroup));
5422 if (ret == NULL) {
5423 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5424 NULL);
5425 return (NULL);
5426 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005427 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005428 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005429 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005430 WXS_ADD_LOCAL(ctxt, ret);
5431 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5432 (type == XML_SCHEMA_TYPE_CHOICE))
5433 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005434 return (ret);
5435}
5436
5437
5438/**
5439 * xmlSchemaAddParticle:
5440 * @ctxt: a schema parser context
5441 * @schema: the schema being built
5442 * @node: the corresponding node in the schema doc
5443 * @min: the minOccurs
5444 * @max: the maxOccurs
5445 *
5446 * Adds an XML schema particle component.
5447 * *WARNING* this interface is highly subject to change
5448 *
5449 * Returns the new struture or NULL in case of error
5450 */
5451static xmlSchemaParticlePtr
5452xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5453 xmlNodePtr node, int min, int max)
5454{
5455 xmlSchemaParticlePtr ret = NULL;
5456 if ((ctxt == NULL) || (schema == NULL))
5457 return (NULL);
5458
5459#ifdef DEBUG
5460 fprintf(stderr, "Adding particle component\n");
5461#endif
5462 ret = (xmlSchemaParticlePtr)
5463 xmlMalloc(sizeof(xmlSchemaParticle));
5464 if (ret == NULL) {
5465 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5466 NULL);
5467 return (NULL);
5468 }
5469 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5470 ret->annot = NULL;
5471 ret->node = node;
5472 ret->minOccurs = min;
5473 ret->maxOccurs = max;
5474 ret->next = NULL;
5475 ret->children = NULL;
5476
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005477 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005478 /*
5479 * Note that addition to pending components will be done locally
5480 * to the specific parsing function, since the most particles
5481 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005482 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005483 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005484 return (ret);
5485}
5486
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005487/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005488 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005489 * @ctxt: a schema validation context
5490 * @schema: the schema being built
5491 * @name: the group name
5492 *
5493 * Add an XML schema Group definition
5494 *
5495 * Returns the new struture or NULL in case of error
5496 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005497static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005498xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5499 xmlSchemaPtr schema,
5500 const xmlChar *name,
5501 const xmlChar *nsName,
5502 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005503{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005504 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005505
5506 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5507 return (NULL);
5508
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005509 ret = (xmlSchemaModelGroupDefPtr)
5510 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005511 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005512 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005513 return (NULL);
5514 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005515 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005516 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005517 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005518 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005519 ret->targetNamespace = nsName;
5520
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005521 if (ctxt->isRedefine) {
5522 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5523 ret, name, nsName);
5524 if (ctxt->redef == NULL) {
5525 xmlFree(ret);
5526 return(NULL);
5527 }
5528 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005529 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005530 WXS_ADD_GLOBAL(ctxt, ret);
5531 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005532 return (ret);
5533}
5534
Daniel Veillard3646d642004-06-02 19:19:14 +00005535/**
5536 * xmlSchemaNewWildcardNs:
5537 * @ctxt: a schema validation context
5538 *
5539 * Creates a new wildcard namespace constraint.
5540 *
5541 * Returns the new struture or NULL in case of error
5542 */
5543static xmlSchemaWildcardNsPtr
5544xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5545{
5546 xmlSchemaWildcardNsPtr ret;
5547
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005548 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005549 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5550 if (ret == NULL) {
5551 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005552 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005553 }
5554 ret->value = NULL;
5555 ret->next = NULL;
5556 return (ret);
5557}
5558
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005559static xmlSchemaIDCPtr
5560xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5561 const xmlChar *name, const xmlChar *nsName,
5562 int category, xmlNodePtr node)
5563{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005564 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005565
5566 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5567 return (NULL);
5568
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005569 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5570 if (ret == NULL) {
5571 xmlSchemaPErrMemory(ctxt,
5572 "allocating an identity-constraint definition", NULL);
5573 return (NULL);
5574 }
5575 memset(ret, 0, sizeof(xmlSchemaIDC));
5576 /* The target namespace of the parent element declaration. */
5577 ret->targetNamespace = nsName;
5578 ret->name = name;
5579 ret->type = category;
5580 ret->node = node;
5581
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005582 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005583 /*
5584 * Only keyrefs need to be fixup up.
5585 */
5586 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005587 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005588 return (ret);
5589}
5590
Daniel Veillard3646d642004-06-02 19:19:14 +00005591/**
5592 * xmlSchemaAddWildcard:
5593 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005594 * @schema: a schema
5595 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005596 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005597 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005598 *
5599 * Returns the new struture or NULL in case of error
5600 */
5601static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005602xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5603 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005604{
5605 xmlSchemaWildcardPtr ret = NULL;
5606
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005607 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005608 return (NULL);
5609
5610 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5611 if (ret == NULL) {
5612 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5613 return (NULL);
5614 }
5615 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005616 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005617 ret->node = node;
5618 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005619 return (ret);
5620}
5621
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005622static void
5623xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5624{
5625 if (group == NULL)
5626 return;
5627 if (group->members != NULL)
5628 xmlSchemaItemListFree(group->members);
5629 xmlFree(group);
5630}
5631
5632static xmlSchemaSubstGroupPtr
5633xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5634 xmlSchemaElementPtr head)
5635{
5636 xmlSchemaSubstGroupPtr ret;
5637
5638 /* Init subst group hash. */
5639 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5640 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5641 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5642 return(NULL);
5643 }
5644 /* Create a new substitution group. */
5645 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5646 if (ret == NULL) {
5647 xmlSchemaPErrMemory(NULL,
5648 "allocating a substitution group container", NULL);
5649 return(NULL);
5650 }
5651 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5652 ret->head = head;
5653 /* Create list of members. */
5654 ret->members = xmlSchemaItemListCreate();
5655 if (ret->members == NULL) {
5656 xmlSchemaSubstGroupFree(ret);
5657 return(NULL);
5658 }
5659 /* Add subst group to hash. */
5660 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5661 head->name, head->targetNamespace, ret) != 0) {
5662 PERROR_INT("xmlSchemaSubstGroupAdd",
5663 "failed to add a new substitution container");
5664 xmlSchemaSubstGroupFree(ret);
5665 return(NULL);
5666 }
5667 return(ret);
5668}
5669
5670static xmlSchemaSubstGroupPtr
5671xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5672 xmlSchemaElementPtr head)
5673{
5674 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5675 return(NULL);
5676 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5677 head->name, head->targetNamespace));
5678
5679}
5680
5681/**
5682 * xmlSchemaAddElementSubstitutionMember:
5683 * @pctxt: a schema parser context
5684 * @head: the head of the substitution group
5685 * @member: the new member of the substitution group
5686 *
5687 * Allocate a new annotation structure.
5688 *
5689 * Returns the newly allocated structure or NULL in case or error
5690 */
5691static int
5692xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5693 xmlSchemaElementPtr head,
5694 xmlSchemaElementPtr member)
5695{
5696 xmlSchemaSubstGroupPtr substGroup = NULL;
5697
5698 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5699 return (-1);
5700
5701 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5702 if (substGroup == NULL)
5703 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5704 if (substGroup == NULL)
5705 return(-1);
5706 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5707 return(-1);
5708 return(0);
5709}
5710
Daniel Veillard4255d502002-04-16 15:50:10 +00005711/************************************************************************
5712 * *
5713 * Utilities for parsing *
5714 * *
5715 ************************************************************************/
5716
Daniel Veillard4255d502002-04-16 15:50:10 +00005717/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005718 * xmlSchemaPValAttrNodeQNameValue:
5719 * @ctxt: a schema parser context
5720 * @schema: the schema context
5721 * @ownerDes: the designation of the parent element
5722 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005723 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 * @local: the resulting local part if found, the attribute value otherwise
5725 * @uri: the resulting namespace URI if found
5726 *
5727 * Extracts the local name and the URI of a QName value and validates it.
5728 * This one is intended to be used on attribute values that
5729 * should resolve to schema components.
5730 *
5731 * Returns 0, in case the QName is valid, a positive error code
5732 * if not valid and -1 if an internal error occurs.
5733 */
5734static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005735xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005736 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005737 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 xmlAttrPtr attr,
5739 const xmlChar *value,
5740 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005741 const xmlChar **local)
5742{
5743 const xmlChar *pref;
5744 xmlNsPtr ns;
5745 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 *uri = NULL;
5748 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005749 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005750 if (ret > 0) {
5751 xmlSchemaPSimpleTypeErr(ctxt,
5752 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5753 ownerItem, (xmlNodePtr) attr,
5754 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5755 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005756 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005757 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005758 } else if (ret < 0)
5759 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005760
5761 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005762 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005763 if (ns)
5764 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5765 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005766 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5767 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005768 /*
5769 * This one takes care of included schemas with no
5770 * target namespace.
5771 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005772 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005774 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005775 return (0);
5776 }
5777 /*
5778 * At this point xmlSplitQName3 has to return a local name.
5779 */
5780 *local = xmlSplitQName3(value, &len);
5781 *local = xmlDictLookup(ctxt->dict, *local, -1);
5782 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005783 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5784 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005785 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005786 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005787 ownerItem, (xmlNodePtr) attr,
5788 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5789 "The value '%s' of simple type 'xs:QName' has no "
5790 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005791 return (ctxt->err);
5792 } else {
5793 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005794 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005795 return (0);
5796}
5797
5798/**
5799 * xmlSchemaPValAttrNodeQName:
5800 * @ctxt: a schema parser context
5801 * @schema: the schema context
5802 * @ownerDes: the designation of the owner element
5803 * @ownerItem: the owner as a schema object
5804 * @attr: the attribute node
5805 * @local: the resulting local part if found, the attribute value otherwise
5806 * @uri: the resulting namespace URI if found
5807 *
5808 * Extracts and validates the QName of an attribute value.
5809 * This one is intended to be used on attribute values that
5810 * should resolve to schema components.
5811 *
5812 * Returns 0, in case the QName is valid, a positive error code
5813 * if not valid and -1 if an internal error occurs.
5814 */
5815static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005816xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005818 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005819 xmlAttrPtr attr,
5820 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005821 const xmlChar **local)
5822{
5823 const xmlChar *value;
5824
5825 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005826 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005827 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005828}
5829
5830/**
5831 * xmlSchemaPValAttrQName:
5832 * @ctxt: a schema parser context
5833 * @schema: the schema context
5834 * @ownerDes: the designation of the parent element
5835 * @ownerItem: the owner as a schema object
5836 * @ownerElem: the parent node of the attribute
5837 * @name: the name of the attribute
5838 * @local: the resulting local part if found, the attribute value otherwise
5839 * @uri: the resulting namespace URI if found
5840 *
5841 * Extracts and validates the QName of an attribute value.
5842 *
5843 * Returns 0, in case the QName is valid, a positive error code
5844 * if not valid and -1 if an internal error occurs.
5845 */
5846static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005847xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5848 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005849 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850 xmlNodePtr ownerElem,
5851 const char *name,
5852 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005853 const xmlChar **local)
5854{
5855 xmlAttrPtr attr;
5856
5857 attr = xmlSchemaGetPropNode(ownerElem, name);
5858 if (attr == NULL) {
5859 *local = NULL;
5860 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005861 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005862 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005863 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005864 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005865}
5866
5867/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005868 * xmlSchemaPValAttrID:
5869 * @ctxt: a schema parser context
5870 * @schema: the schema context
5871 * @ownerDes: the designation of the parent element
5872 * @ownerItem: the owner as a schema object
5873 * @ownerElem: the parent node of the attribute
5874 * @name: the name of the attribute
5875 *
5876 * Extracts and validates the ID of an attribute value.
5877 *
5878 * Returns 0, in case the ID is valid, a positive error code
5879 * if not valid and -1 if an internal error occurs.
5880 */
5881static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005882xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005883{
5884 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005885 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005886
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005887 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005888 return(0);
5889 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5890 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005891 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005892 /*
5893 * NOTE: the IDness might have already be declared in the DTD
5894 */
5895 if (attr->atype != XML_ATTRIBUTE_ID) {
5896 xmlIDPtr res;
5897 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005898
5899 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005900 * TODO: Use xmlSchemaStrip here; it's not exported at this
5901 * moment.
5902 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005903 strip = xmlSchemaCollapseString(value);
5904 if (strip != NULL) {
5905 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005906 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005907 }
5908 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005909 if (res == NULL) {
5910 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 xmlSchemaPSimpleTypeErr(ctxt,
5912 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005913 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005914 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5915 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005916 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005917 } else
5918 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005919 }
5920 } else if (ret > 0) {
5921 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005922 xmlSchemaPSimpleTypeErr(ctxt,
5923 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005924 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005925 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5926 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5927 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005928 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005929 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005930 if (value != NULL)
5931 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005932
5933 return (ret);
5934}
5935
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005936static int
5937xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5938 xmlNodePtr ownerElem,
5939 const xmlChar *name)
5940{
5941 xmlAttrPtr attr;
5942
5943 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5944 if (attr == NULL)
5945 return(0);
5946 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5947
5948}
5949
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005950/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005951 * xmlGetMaxOccurs:
5952 * @ctxt: a schema validation context
5953 * @node: a subtree containing XML Schema informations
5954 *
5955 * Get the maxOccurs property
5956 *
5957 * Returns the default if not found, or the value
5958 */
5959static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005960xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5961 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005962{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005963 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005964 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005965 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005966
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005967 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5968 if (attr == NULL)
5969 return (def);
5970 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005971
5972 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005973 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005974 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005975 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5976 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005977 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005978 val, NULL, NULL, NULL);
5979 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005981 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005982 }
5983
5984 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005985 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005988 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5990 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005992 val, NULL, NULL, NULL);
5993 return (def);
5994 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005995 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 ret = ret * 10 + (*cur - '0');
5997 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 }
William M. Brack76e95df2003-10-18 16:20:14 +00005999 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006000 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 /*
6002 * TODO: Restrict the maximal value to Integer.
6003 */
6004 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006005 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006006 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6007 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006008 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 val, NULL, NULL, NULL);
6010 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006011 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006012 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006013}
6014
6015/**
6016 * xmlGetMinOccurs:
6017 * @ctxt: a schema validation context
6018 * @node: a subtree containing XML Schema informations
6019 *
6020 * Get the minOccurs property
6021 *
6022 * Returns the default if not found, or the value
6023 */
6024static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006025xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006026 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006027{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006028 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006029 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006030 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006031
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006032 attr = xmlSchemaGetPropNode(node, "minOccurs");
6033 if (attr == NULL)
6034 return (def);
6035 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006037 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006039 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006040 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006041 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6042 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006043 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006044 val, NULL, NULL, NULL);
6045 return (def);
6046 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006047 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 ret = ret * 10 + (*cur - '0');
6049 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 }
William M. Brack76e95df2003-10-18 16:20:14 +00006051 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006053 /*
6054 * TODO: Restrict the maximal value to Integer.
6055 */
6056 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006057 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6059 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006060 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006061 val, NULL, NULL, NULL);
6062 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006063 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006064 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006065}
6066
6067/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006068 * xmlSchemaPGetBoolNodeValue:
6069 * @ctxt: a schema validation context
6070 * @ownerDes: owner designation
6071 * @ownerItem: the owner as a schema item
6072 * @node: the node holding the value
6073 *
6074 * Converts a boolean string value into 1 or 0.
6075 *
6076 * Returns 0 or 1.
6077 */
6078static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006079xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006080 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006081 xmlNodePtr node)
6082{
6083 xmlChar *value = NULL;
6084 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006085
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006086 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006087 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006088 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006089 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006090 * can have the following legal literals {true, false, 1, 0}.
6091 */
6092 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6093 res = 1;
6094 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6095 res = 0;
6096 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6097 res = 1;
6098 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006100 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006101 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006102 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006103 ownerItem, node,
6104 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6105 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006106 NULL, NULL, NULL);
6107 }
6108 if (value != NULL)
6109 xmlFree(value);
6110 return (res);
6111}
6112
6113/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006114 * xmlGetBooleanProp:
6115 * @ctxt: a schema validation context
6116 * @node: a subtree containing XML Schema informations
6117 * @name: the attribute name
6118 * @def: the default value
6119 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006120 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006121 *
6122 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006123 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006124 */
6125static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006126xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006127 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006128 const char *name, int def)
6129{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006130 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006131
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006132 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006133 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006134 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006135 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006136 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006137 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006138 * can have the following legal literals {true, false, 1, 0}.
6139 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 if (xmlStrEqual(val, BAD_CAST "true"))
6141 def = 1;
6142 else if (xmlStrEqual(val, BAD_CAST "false"))
6143 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006144 else if (xmlStrEqual(val, BAD_CAST "1"))
6145 def = 1;
6146 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006147 def = 0;
6148 else {
6149 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006150 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006151 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006152 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006153 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6154 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006156 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006157}
6158
6159/************************************************************************
6160 * *
6161 * Shema extraction from an Infoset *
6162 * *
6163 ************************************************************************/
6164static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6165 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006166 xmlNodePtr node,
6167 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006168static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6169 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006170 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006171 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006172 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6174 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006175 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006176 xmlNodePtr node,
6177 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006178static xmlSchemaBasicItemPtr
6179xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6180 xmlSchemaPtr schema,
6181 xmlNodePtr node,
6182 xmlSchemaItemListPtr uses,
6183 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006184static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6185 xmlSchemaPtr schema,
6186 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006187static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006188xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6189 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006190
6191/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006192 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006193 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006194 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006195 * @ownerDes: the designation of the parent element
6196 * @ownerItem: the schema object owner if existent
6197 * @attr: the schema attribute node being validated
6198 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006199 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006200 *
6201 * Validates a value against the given built-in type.
6202 * This one is intended to be used internally for validation
6203 * of schema attribute values during parsing of the schema.
6204 *
6205 * Returns 0 if the value is valid, a positive error code
6206 * number otherwise and -1 in case of an internal or API error.
6207 */
6208static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006209xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006210 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006211 xmlAttrPtr attr,
6212 const xmlChar *value,
6213 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006214{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006215
6216 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006217
6218 /*
6219 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6220 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006221 */
6222 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006223 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006224 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6225 PERROR_INT("xmlSchemaPValAttrNodeValue",
6226 "the given type is not a built-in type");
6227 return (-1);
6228 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006229 switch (type->builtInType) {
6230 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006231 case XML_SCHEMAS_QNAME:
6232 case XML_SCHEMAS_ANYURI:
6233 case XML_SCHEMAS_TOKEN:
6234 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006235 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6236 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006237 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006238 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006239 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006240 "validation using the given type is not supported while "
6241 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006242 return (-1);
6243 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006244 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006245 /*
6246 * TODO: Should we use the S4S error codes instead?
6247 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006248 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006249 PERROR_INT("xmlSchemaPValAttrNodeValue",
6250 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006251 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006252 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006253 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006254 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6255 else
6256 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6257 xmlSchemaPSimpleTypeErr(pctxt,
6258 ret, ownerItem, (xmlNodePtr) attr,
6259 type, NULL, value, NULL, NULL, NULL);
6260 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006261 return (ret);
6262}
6263
6264/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006265 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006266 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006267 * @ctxt: a schema parser context
6268 * @ownerDes: the designation of the parent element
6269 * @ownerItem: the schema object owner if existent
6270 * @attr: the schema attribute node being validated
6271 * @type: the built-in type to be validated against
6272 * @value: the resulting value if any
6273 *
6274 * Extracts and validates a value against the given built-in type.
6275 * This one is intended to be used internally for validation
6276 * of schema attribute values during parsing of the schema.
6277 *
6278 * Returns 0 if the value is valid, a positive error code
6279 * number otherwise and -1 in case of an internal or API error.
6280 */
6281static int
6282xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006283 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006284 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006285 xmlSchemaTypePtr type,
6286 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006288 const xmlChar *val;
6289
6290 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006291 return (-1);
6292
Daniel Veillardc0826a72004-08-10 14:17:33 +00006293 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6294 if (value != NULL)
6295 *value = val;
6296
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006297 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006299}
6300
6301/**
6302 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006303 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006304 * @ctxt: a schema parser context
6305 * @node: the element node of the attribute
6306 * @ownerDes: the designation of the parent element
6307 * @ownerItem: the schema object owner if existent
6308 * @ownerElem: the owner element node
6309 * @name: the name of the schema attribute node
6310 * @type: the built-in type to be validated against
6311 * @value: the resulting value if any
6312 *
6313 * Extracts and validates a value against the given built-in type.
6314 * This one is intended to be used internally for validation
6315 * of schema attribute values during parsing of the schema.
6316 *
6317 * Returns 0 if the value is valid, a positive error code
6318 * number otherwise and -1 in case of an internal or API error.
6319 */
6320static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006321xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6322 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006323 xmlNodePtr ownerElem,
6324 const char *name,
6325 xmlSchemaTypePtr type,
6326 const xmlChar **value)
6327{
6328 xmlAttrPtr attr;
6329
6330 if ((ctxt == NULL) || (type == NULL)) {
6331 if (value != NULL)
6332 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006334 }
6335 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6336 if (value != NULL)
6337 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006338 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006339 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006340 "Internal error: xmlSchemaPValAttr, the given "
6341 "type '%s' is not a built-in type.\n",
6342 type->name, NULL);
6343 return (-1);
6344 }
6345 attr = xmlSchemaGetPropNode(ownerElem, name);
6346 if (attr == NULL) {
6347 if (value != NULL)
6348 *value = NULL;
6349 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006351 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006352 type, value));
6353}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006354
6355static int
6356xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006357 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006358 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006359 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006360 const xmlChar *namespaceName)
6361{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006362 /* TODO: Pointer comparison instead? */
6363 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006364 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006365 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006366 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006367 /*
6368 * Check if the referenced namespace was <import>ed.
6369 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006370 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006371 xmlSchemaSchemaRelationPtr rel;
6372
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006373 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006374 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006375 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006376 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006377 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006378 rel = rel->next;
6379 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006380 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006381 /*
6382 * No matching <import>ed namespace found.
6383 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006384 {
6385 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6386
6387 if (namespaceName == NULL)
6388 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6389 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6390 "References from this schema to components in no "
6391 "namespace are not allowed, since not indicated by an "
6392 "import statement", NULL, NULL);
6393 else
6394 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6395 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6396 "References from this schema to components in the "
6397 "namespace '%s' are not allowed, since not indicated by an "
6398 "import statement", namespaceName, NULL);
6399 }
6400 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006401}
6402
Daniel Veillardc0826a72004-08-10 14:17:33 +00006403/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006404 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006405 * @ctxt: a schema validation context
6406 * @schema: the schema being built
6407 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006408 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006409 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006410 * Parses attribute uses and attribute declarations and
6411 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006412 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006413static int
6414xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6415 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6416 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006417{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006418 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006419
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006420 while ((IS_SCHEMA((*child), "attribute")) ||
6421 (IS_SCHEMA((*child), "attributeGroup"))) {
6422 if (IS_SCHEMA((*child), "attribute")) {
6423 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6424 *list, parentType);
6425 } else {
6426 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6427 if ((item != NULL) && (hasRefs != NULL))
6428 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006429 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006430 if (item != NULL) {
6431 if (*list == NULL) {
6432 /* TODO: Customize grow factor. */
6433 *list = xmlSchemaItemListCreate();
6434 if (*list == NULL)
6435 return(-1);
6436 }
6437 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6438 return(-1);
6439 }
6440 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006441 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006442 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006443}
6444
6445/**
6446 * xmlSchemaParseAnnotation:
6447 * @ctxt: a schema validation context
6448 * @schema: the schema being built
6449 * @node: a subtree containing XML Schema informations
6450 *
6451 * parse a XML schema Attrribute declaration
6452 * *WARNING* this interface is highly subject to change
6453 *
William M. Bracke7091952004-05-11 15:09:58 +00006454 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006455 * 1 in case of success.
6456 */
6457static xmlSchemaAnnotPtr
6458xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006459 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006460{
6461 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 xmlNodePtr child = NULL;
6463 xmlAttrPtr attr;
6464 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006465
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 /*
6467 * INFO: S4S completed.
6468 */
6469 /*
6470 * id = ID
6471 * {any attributes with non-schema namespace . . .}>
6472 * Content: (appinfo | documentation)*
6473 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006474 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6475 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006476 if (needed)
6477 ret = xmlSchemaNewAnnot(ctxt, node);
6478 else
6479 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 attr = node->properties;
6481 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006484 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006486
6487 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006488 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 }
6490 attr = attr->next;
6491 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006492 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 /*
6494 * And now for the children...
6495 */
6496 child = node->children;
6497 while (child != NULL) {
6498 if (IS_SCHEMA(child, "appinfo")) {
6499 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006500 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006501 * source = anyURI
6502 * {any attributes with non-schema namespace . . .}>
6503 * Content: ({any})*
6504 */
6505 attr = child->properties;
6506 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006507 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006509 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006511
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006512 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006513 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 }
6515 attr = attr->next;
6516 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006517 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006518 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 child = child->next;
6520 } else if (IS_SCHEMA(child, "documentation")) {
6521 /* TODO: make available the content of "documentation". */
6522 /*
6523 * source = anyURI
6524 * {any attributes with non-schema namespace . . .}>
6525 * Content: ({any})*
6526 */
6527 attr = child->properties;
6528 while (attr != NULL) {
6529 if (attr->ns == NULL) {
6530 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006532 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 }
6534 } else {
6535 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6536 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6537 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538
6539 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006540 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 }
6542 }
6543 attr = attr->next;
6544 }
6545 /*
6546 * Attribute "xml:lang".
6547 */
6548 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6549 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006550 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 child = child->next;
6553 } else {
6554 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 xmlSchemaPContentErr(ctxt,
6556 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006557 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006558 barked = 1;
6559 child = child->next;
6560 }
6561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006562
Daniel Veillard4255d502002-04-16 15:50:10 +00006563 return (ret);
6564}
6565
6566/**
6567 * xmlSchemaParseFacet:
6568 * @ctxt: a schema validation context
6569 * @schema: the schema being built
6570 * @node: a subtree containing XML Schema informations
6571 *
6572 * parse a XML schema Facet declaration
6573 * *WARNING* this interface is highly subject to change
6574 *
6575 * Returns the new type structure or NULL in case of error
6576 */
6577static xmlSchemaFacetPtr
6578xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006579 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006580{
6581 xmlSchemaFacetPtr facet;
6582 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006583 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006584
6585 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6586 return (NULL);
6587
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006588 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006589 if (facet == NULL) {
6590 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6591 return (NULL);
6592 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006593 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006594 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006596 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6597 "Facet %s has no value\n", node->name, NULL);
6598 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006599 return (NULL);
6600 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006602 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006604 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006607 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006609 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006610 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006612 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006615 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006617 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006619 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006620 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006621 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006622 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6623 } else if (IS_SCHEMA(node, "minLength")) {
6624 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6625 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006626 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6627 "Unknown facet type %s\n", node->name, NULL);
6628 xmlSchemaFreeFacet(facet);
6629 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006630 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006631 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006632 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006633 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6634 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6635 const xmlChar *fixed;
6636
6637 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6638 if (fixed != NULL) {
6639 if (xmlStrEqual(fixed, BAD_CAST "true"))
6640 facet->fixed = 1;
6641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006642 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006643 child = node->children;
6644
6645 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006646 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006648 }
6649 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006650 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6651 "Facet %s has unexpected child content\n",
6652 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006653 }
6654 return (facet);
6655}
6656
6657/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006658 * xmlSchemaParseWildcardNs:
6659 * @ctxt: a schema parser context
6660 * @wildc: the wildcard, already created
6661 * @node: a subtree containing XML Schema informations
6662 *
6663 * Parses the attribute "processContents" and "namespace"
6664 * of a xsd:anyAttribute and xsd:any.
6665 * *WARNING* this interface is highly subject to change
6666 *
6667 * Returns 0 if everything goes fine, a positive error code
6668 * if something is not valid and -1 if an internal error occurs.
6669 */
6670static int
6671xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006672 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006673 xmlSchemaWildcardPtr wildc,
6674 xmlNodePtr node)
6675{
6676 const xmlChar *pc, *ns, *dictnsItem;
6677 int ret = 0;
6678 xmlChar *nsItem;
6679 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6680 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006681
Daniel Veillardc0826a72004-08-10 14:17:33 +00006682 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6683 if ((pc == NULL)
6684 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6685 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6686 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6687 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6688 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6689 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6690 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006691 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006692 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006693 NULL, node,
6694 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006695 NULL, NULL, NULL);
6696 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006697 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006698 }
6699 /*
6700 * Build the namespace constraints.
6701 */
6702 attr = xmlSchemaGetPropNode(node, "namespace");
6703 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006704 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006705 wildc->any = 1;
6706 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6707 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006708 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006709 return (-1);
6710 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006711 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006712 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 const xmlChar *end, *cur;
6714
6715 cur = ns;
6716 do {
6717 while (IS_BLANK_CH(*cur))
6718 cur++;
6719 end = cur;
6720 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6721 end++;
6722 if (end == cur)
6723 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006724 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006725 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6726 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006727 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006728 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006729 NULL, (xmlNodePtr) attr,
6730 NULL,
6731 "((##any | ##other) | List of (xs:anyURI | "
6732 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 nsItem, NULL, NULL, NULL);
6734 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6735 } else {
6736 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006737 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6739 dictnsItem = NULL;
6740 } else {
6741 /*
6742 * Validate the item (anyURI).
6743 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006744 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006745 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6746 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6747 }
6748 /*
6749 * Avoid dublicate namespaces.
6750 */
6751 tmp = wildc->nsSet;
6752 while (tmp != NULL) {
6753 if (dictnsItem == tmp->value)
6754 break;
6755 tmp = tmp->next;
6756 }
6757 if (tmp == NULL) {
6758 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6759 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006760 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 return (-1);
6762 }
6763 tmp->value = dictnsItem;
6764 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006765 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006766 wildc->nsSet = tmp;
6767 else
6768 lastNs->next = tmp;
6769 lastNs = tmp;
6770 }
6771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006772 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 xmlFree(nsItem);
6774 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006775 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 }
6777 return (ret);
6778}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006779
6780static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006781xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6782 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006783 xmlNodePtr node,
6784 int minOccurs,
6785 int maxOccurs) {
6786
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006787 if ((maxOccurs == 0) && ( minOccurs == 0))
6788 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006789 if (maxOccurs != UNBOUNDED) {
6790 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006791 * TODO: Maybe we should better not create the particle,
6792 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006793 * content model.
6794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006795 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006796 * 3.9.6 Schema Component Constraint: Particle Correct
6797 *
6798 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 if (maxOccurs < 1) {
6800 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006801 * 2.2 {max occurs} must be greater than or equal to 1.
6802 */
6803 xmlSchemaPCustomAttrErr(ctxt,
6804 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006805 NULL, NULL,
6806 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006807 "The value must be greater than or equal to 1");
6808 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6809 } else if (minOccurs > maxOccurs) {
6810 /*
6811 * 2.1 {min occurs} must not be greater than {max occurs}.
6812 */
6813 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006815 NULL, NULL,
6816 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006817 "The value must not be greater than the value of 'maxOccurs'");
6818 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6819 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006820 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006821 return (0);
6822}
6823
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006825 * xmlSchemaParseAny:
6826 * @ctxt: a schema validation context
6827 * @schema: the schema being built
6828 * @node: a subtree containing XML Schema informations
6829 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006830 * Parsea a XML schema <any> element. A particle and wildcard
6831 * will be created (except if minOccurs==maxOccurs==0, in this case
6832 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006833 * *WARNING* this interface is highly subject to change
6834 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006835 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006836 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006837static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006838xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6839 xmlNodePtr node)
6840{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006841 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006842 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006843 xmlSchemaWildcardPtr wild;
6844 int min, max;
6845 xmlAttrPtr attr;
6846 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006847
6848 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6849 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006850 /*
6851 * Check for illegal attributes.
6852 */
6853 attr = node->properties;
6854 while (attr != NULL) {
6855 if (attr->ns == NULL) {
6856 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6857 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6858 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6859 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6860 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006861 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006862 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006863 }
6864 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006865 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006866 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006867 }
6868 attr = attr->next;
6869 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006870 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006871 /*
6872 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006873 */
6874 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6875 "(xs:nonNegativeInteger | unbounded)");
6876 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6877 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006878 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6879 /*
6880 * Create & parse the wildcard.
6881 */
6882 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6883 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006884 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006885 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006886 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006887 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006888 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006889 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006890 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006891 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006892 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006893 }
6894 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006895 xmlSchemaPContentErr(ctxt,
6896 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006897 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006898 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006899 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006900 /*
6901 * No component if minOccurs==maxOccurs==0.
6902 */
6903 if ((min == 0) && (max == 0)) {
6904 /* Don't free the wildcard, since it's already on the list. */
6905 return (NULL);
6906 }
6907 /*
6908 * Create the particle.
6909 */
6910 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6911 if (particle == NULL)
6912 return (NULL);
6913 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006914 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006915
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006917}
6918
6919/**
6920 * xmlSchemaParseNotation:
6921 * @ctxt: a schema validation context
6922 * @schema: the schema being built
6923 * @node: a subtree containing XML Schema informations
6924 *
6925 * parse a XML schema Notation declaration
6926 *
6927 * Returns the new structure or NULL in case of error
6928 */
6929static xmlSchemaNotationPtr
6930xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006931 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006932{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006933 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006934 xmlSchemaNotationPtr ret;
6935 xmlNodePtr child = NULL;
6936
6937 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6938 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006939 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006940 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006941 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6942 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006943 return (NULL);
6944 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006945 ret = xmlSchemaAddNotation(ctxt, schema, name,
6946 ctxt->targetNamespace, node);
6947 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006948 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006949 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006950
6951 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006952 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006953 child = child->next;
6954 }
6955
Daniel Veillard4255d502002-04-16 15:50:10 +00006956 child = node->children;
6957 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006958 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006959 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006960 }
6961 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006962 xmlSchemaPContentErr(ctxt,
6963 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006964 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006965 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006966 }
6967
6968 return (ret);
6969}
6970
6971/**
6972 * xmlSchemaParseAnyAttribute:
6973 * @ctxt: a schema validation context
6974 * @schema: the schema being built
6975 * @node: a subtree containing XML Schema informations
6976 *
6977 * parse a XML schema AnyAttrribute declaration
6978 * *WARNING* this interface is highly subject to change
6979 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006980 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006981 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006982static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006983xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6984 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006985{
Daniel Veillard3646d642004-06-02 19:19:14 +00006986 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006987 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006988 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006989
6990 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6991 return (NULL);
6992
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006993 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6994 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006995 if (ret == NULL) {
6996 return (NULL);
6997 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006998 /*
6999 * Check for illegal attributes.
7000 */
7001 attr = node->properties;
7002 while (attr != NULL) {
7003 if (attr->ns == NULL) {
7004 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7005 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7006 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007007 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007008 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007009 }
7010 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007011 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007012 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007013 }
7014 attr = attr->next;
7015 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007016 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007017 /*
7018 * Parse the namespace list.
7019 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007020 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007021 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007022 /*
7023 * And now for the children...
7024 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 child = node->children;
7026 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007027 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007028 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007029 }
7030 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007031 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007032 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007033 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007034 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007035 }
7036
7037 return (ret);
7038}
7039
7040
7041/**
7042 * xmlSchemaParseAttribute:
7043 * @ctxt: a schema validation context
7044 * @schema: the schema being built
7045 * @node: a subtree containing XML Schema informations
7046 *
7047 * parse a XML schema Attrribute declaration
7048 * *WARNING* this interface is highly subject to change
7049 *
William M. Bracke7091952004-05-11 15:09:58 +00007050 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007051 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007052static xmlSchemaBasicItemPtr
7053xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7054 xmlSchemaPtr schema,
7055 xmlNodePtr node,
7056 xmlSchemaItemListPtr uses,
7057 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007058{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007059 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7060 xmlSchemaAttributeUsePtr use = NULL;
7061 xmlNodePtr child = NULL;
7062 xmlAttrPtr attr;
7063 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7064 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7065 int nberrors, hasForm = 0, defValueType = 0;
7066
7067#define WXS_ATTR_DEF_VAL_DEFAULT 1
7068#define WXS_ATTR_DEF_VAL_FIXED 2
7069
7070 /*
7071 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7072 */
7073
7074 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7075 return (NULL);
7076 attr = xmlSchemaGetPropNode(node, "ref");
7077 if (attr != NULL) {
7078 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7079 NULL, attr, &tmpNs, &tmpName) != 0) {
7080 return (NULL);
7081 }
7082 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7083 return(NULL);
7084 isRef = 1;
7085 }
7086 nberrors = pctxt->nberrors;
7087 /*
7088 * Check for illegal attributes.
7089 */
7090 attr = node->properties;
7091 while (attr != NULL) {
7092 if (attr->ns == NULL) {
7093 if (isRef) {
7094 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7095 xmlSchemaPValAttrNodeID(pctxt, attr);
7096 goto attr_next;
7097 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7098 goto attr_next;
7099 }
7100 } else {
7101 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7102 goto attr_next;
7103 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7104 xmlSchemaPValAttrNodeID(pctxt, attr);
7105 goto attr_next;
7106 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7107 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7108 attr, &tmpNs, &tmpName);
7109 goto attr_next;
7110 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7111 /*
7112 * Evaluate the target namespace
7113 */
7114 hasForm = 1;
7115 attrValue = xmlSchemaGetNodeContent(pctxt,
7116 (xmlNodePtr) attr);
7117 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7118 ns = pctxt->targetNamespace;
7119 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7120 {
7121 xmlSchemaPSimpleTypeErr(pctxt,
7122 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7123 NULL, (xmlNodePtr) attr,
7124 NULL, "(qualified | unqualified)",
7125 attrValue, NULL, NULL, NULL);
7126 }
7127 goto attr_next;
7128 }
7129 }
7130 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7131
7132 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7133 /* TODO: Maybe we need to normalize the value beforehand. */
7134 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7135 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7136 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7137 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7138 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7139 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7140 else {
7141 xmlSchemaPSimpleTypeErr(pctxt,
7142 XML_SCHEMAP_INVALID_ATTR_USE,
7143 NULL, (xmlNodePtr) attr,
7144 NULL, "(optional | prohibited | required)",
7145 attrValue, NULL, NULL, NULL);
7146 }
7147 goto attr_next;
7148 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7149 /*
7150 * 3.2.3 : 1
7151 * default and fixed must not both be present.
7152 */
7153 if (defValue) {
7154 xmlSchemaPMutualExclAttrErr(pctxt,
7155 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7156 NULL, attr, "default", "fixed");
7157 } else {
7158 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7159 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7160 }
7161 goto attr_next;
7162 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7163 /*
7164 * 3.2.3 : 1
7165 * default and fixed must not both be present.
7166 */
7167 if (defValue) {
7168 xmlSchemaPMutualExclAttrErr(pctxt,
7169 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7170 NULL, attr, "default", "fixed");
7171 } else {
7172 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7173 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7174 }
7175 goto attr_next;
7176 }
7177 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7178 goto attr_next;
7179
7180 xmlSchemaPIllegalAttrErr(pctxt,
7181 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7182
7183attr_next:
7184 attr = attr->next;
7185 }
7186 /*
7187 * 3.2.3 : 2
7188 * If default and use are both present, use must have
7189 * the actual value optional.
7190 */
7191 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7192 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7193 xmlSchemaPSimpleTypeErr(pctxt,
7194 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7195 NULL, node, NULL,
7196 "(optional | prohibited | required)", NULL,
7197 "The value of the attribute 'use' must be 'optional' "
7198 "if the attribute 'default' is present",
7199 NULL, NULL);
7200 }
7201 /*
7202 * We want correct attributes.
7203 */
7204 if (nberrors != pctxt->nberrors)
7205 return(NULL);
7206 if (! isRef) {
7207 xmlSchemaAttributePtr attrDecl;
7208
7209 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7210 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7211 ns = pctxt->targetNamespace;
7212 /*
7213 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7214 * TODO: Move this to the component layer.
7215 */
7216 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7217 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7218 XML_SCHEMAP_NO_XSI,
7219 node, NULL,
7220 "The target namespace must not match '%s'",
7221 xmlSchemaInstanceNs, NULL);
7222 }
7223 attr = xmlSchemaGetPropNode(node, "name");
7224 if (attr == NULL) {
7225 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7226 NULL, node, "name", NULL);
7227 return (NULL);
7228 }
7229 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7230 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7231 return (NULL);
7232 }
7233 /*
7234 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7235 * TODO: Move this to the component layer.
7236 */
7237 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7238 xmlSchemaPSimpleTypeErr(pctxt,
7239 XML_SCHEMAP_NO_XMLNS,
7240 NULL, (xmlNodePtr) attr,
7241 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7242 "The value of the attribute must not match 'xmlns'",
7243 NULL, NULL);
7244 return (NULL);
7245 }
7246 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7247 goto check_children;
7248 /*
7249 * Create the attribute use component.
7250 */
7251 use = xmlSchemaAddAttributeUse(pctxt, node);
7252 if (use == NULL)
7253 return(NULL);
7254 use->occurs = occurs;
7255 /*
7256 * Create the attribute declaration.
7257 */
7258 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7259 if (attrDecl == NULL)
7260 return (NULL);
7261 if (tmpName != NULL) {
7262 attrDecl->typeName = tmpName;
7263 attrDecl->typeNs = tmpNs;
7264 }
7265 use->attrDecl = attrDecl;
7266 /*
7267 * Value constraint.
7268 */
7269 if (defValue != NULL) {
7270 attrDecl->defValue = defValue;
7271 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7272 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7273 }
7274 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7275 xmlSchemaQNameRefPtr ref;
7276
7277 /*
7278 * Create the attribute use component.
7279 */
7280 use = xmlSchemaAddAttributeUse(pctxt, node);
7281 if (use == NULL)
7282 return(NULL);
7283 /*
7284 * We need to resolve the reference at later stage.
7285 */
7286 WXS_ADD_PENDING(pctxt, use);
7287 use->occurs = occurs;
7288 /*
7289 * Create a QName reference to the attribute declaration.
7290 */
7291 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7292 tmpName, tmpNs);
7293 if (ref == NULL)
7294 return(NULL);
7295 /*
7296 * Assign the reference. This will be substituted for the
7297 * referenced attribute declaration when the QName is resolved.
7298 */
7299 use->attrDecl = WXS_ATTR_CAST ref;
7300 /*
7301 * Value constraint.
7302 */
7303 if (defValue != NULL)
7304 use->defValue = defValue;
7305 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7306 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7307 }
7308
7309check_children:
7310 /*
7311 * And now for the children...
7312 */
7313 child = node->children;
7314 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7315 xmlSchemaAttributeUseProhibPtr prohib;
7316
7317 if (IS_SCHEMA(child, "annotation")) {
7318 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7319 child = child->next;
7320 }
7321 if (child != NULL) {
7322 xmlSchemaPContentErr(pctxt,
7323 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7324 NULL, node, child, NULL,
7325 "(annotation?)");
7326 }
7327 /*
7328 * Check for pointlessness of attribute prohibitions.
7329 */
7330 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7331 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7332 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7333 node, NULL,
7334 "Skipping attribute use prohibition, since it is "
7335 "pointless inside an <attributeGroup>",
7336 NULL, NULL, NULL);
7337 return(NULL);
7338 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7339 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7340 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7341 node, NULL,
7342 "Skipping attribute use prohibition, since it is "
7343 "pointless when extending a type",
7344 NULL, NULL, NULL);
7345 return(NULL);
7346 }
7347 if (! isRef) {
7348 tmpName = name;
7349 tmpNs = ns;
7350 }
7351 /*
7352 * Check for duplicate attribute prohibitions.
7353 */
7354 if (uses) {
7355 int i;
7356
7357 for (i = 0; i < uses->nbItems; i++) {
7358 use = uses->items[i];
7359 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7360 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7361 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7362 {
7363 xmlChar *str = NULL;
7364
7365 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7366 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7367 node, NULL,
7368 "Skipping duplicate attribute use prohibition '%s'",
7369 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7370 NULL, NULL);
7371 FREE_AND_NULL(str)
7372 return(NULL);
7373 }
7374 }
7375 }
7376 /*
7377 * Create the attribute prohibition helper component.
7378 */
7379 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7380 if (prohib == NULL)
7381 return(NULL);
7382 prohib->node = node;
7383 prohib->name = tmpName;
7384 prohib->targetNamespace = tmpNs;
7385 if (isRef) {
7386 /*
7387 * We need at least to resolve to the attribute declaration.
7388 */
7389 WXS_ADD_PENDING(pctxt, prohib);
7390 }
7391 return(WXS_BASIC_CAST prohib);
7392 } else {
7393 if (IS_SCHEMA(child, "annotation")) {
7394 /*
7395 * TODO: Should this go into the attr decl?
7396 */
7397 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7398 child = child->next;
7399 }
7400 if (isRef) {
7401 if (child != NULL) {
7402 if (IS_SCHEMA(child, "simpleType"))
7403 /*
7404 * 3.2.3 : 3.2
7405 * If ref is present, then all of <simpleType>,
7406 * form and type must be absent.
7407 */
7408 xmlSchemaPContentErr(pctxt,
7409 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7410 NULL, node, child, NULL,
7411 "(annotation?)");
7412 else
7413 xmlSchemaPContentErr(pctxt,
7414 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7415 NULL, node, child, NULL,
7416 "(annotation?)");
7417 }
7418 } else {
7419 if (IS_SCHEMA(child, "simpleType")) {
7420 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7421 /*
7422 * 3.2.3 : 4
7423 * type and <simpleType> must not both be present.
7424 */
7425 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7426 NULL, node, child,
7427 "The attribute 'type' and the <simpleType> child "
7428 "are mutually exclusive", NULL);
7429 } else
7430 WXS_ATTRUSE_TYPEDEF(use) =
7431 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7432 child = child->next;
7433 }
7434 if (child != NULL)
7435 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7436 NULL, node, child, NULL,
7437 "(annotation?, simpleType?)");
7438 }
7439 }
7440 return (WXS_BASIC_CAST use);
7441}
7442
7443
7444static xmlSchemaAttributePtr
7445xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7446 xmlSchemaPtr schema,
7447 xmlNodePtr node)
7448{
7449 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007450 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007451 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007452 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007453
7454 /*
7455 * Note that the w3c spec assumes the schema to be validated with schema
7456 * for schemas beforehand.
7457 *
7458 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007459 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007460 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7461 return (NULL);
7462 /*
7463 * 3.2.3 : 3.1
7464 * One of ref or name must be present, but not both
7465 */
7466 attr = xmlSchemaGetPropNode(node, "name");
7467 if (attr == NULL) {
7468 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7469 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007470 return (NULL);
7471 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007472 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7473 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7474 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007475 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007476 /*
7477 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7478 * TODO: Move this to the component layer.
7479 */
7480 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7481 xmlSchemaPSimpleTypeErr(pctxt,
7482 XML_SCHEMAP_NO_XMLNS,
7483 NULL, (xmlNodePtr) attr,
7484 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7485 "The value of the attribute must not match 'xmlns'",
7486 NULL, NULL);
7487 return (NULL);
7488 }
7489 /*
7490 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7491 * TODO: Move this to the component layer.
7492 * Or better leave it here and add it to the component layer
7493 * if we have a schema construction API.
7494 */
7495 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7496 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7497 XML_SCHEMAP_NO_XSI, node, NULL,
7498 "The target namespace must not match '%s'",
7499 xmlSchemaInstanceNs, NULL);
7500 }
7501
7502 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7503 pctxt->targetNamespace, node, 1);
7504 if (ret == NULL)
7505 return (NULL);
7506 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7507
7508 /*
7509 * Check for illegal attributes.
7510 */
7511 attr = node->properties;
7512 while (attr != NULL) {
7513 if (attr->ns == NULL) {
7514 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7515 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7516 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7517 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7518 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7519 {
7520 xmlSchemaPIllegalAttrErr(pctxt,
7521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7522 }
7523 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7524 xmlSchemaPIllegalAttrErr(pctxt,
7525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7526 }
7527 attr = attr->next;
7528 }
7529 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7530 node, "type", &ret->typeNs, &ret->typeName);
7531
7532 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007533 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007534 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007535 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007536 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007537 if (ret->defValue != NULL)
7538 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007539 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 * Attribute "default".
7541 */
7542 attr = xmlSchemaGetPropNode(node, "default");
7543 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007544 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007545 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 */
7548 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007549 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7550 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007551 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007552 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 /*
7555 * And now for the children...
7556 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007557 child = node->children;
7558 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007559 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007560 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007561 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007562 if (IS_SCHEMA(child, "simpleType")) {
7563 if (ret->typeName != NULL) {
7564 /*
7565 * 3.2.3 : 4
7566 * type and <simpleType> must not both be present.
7567 */
7568 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7569 NULL, node, child,
7570 "The attribute 'type' and the <simpleType> child "
7571 "are mutually exclusive", NULL);
7572 } else
7573 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7574 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007575 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007576 if (child != NULL)
7577 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7578 NULL, node, child, NULL,
7579 "(annotation?, simpleType?)");
7580
Daniel Veillard4255d502002-04-16 15:50:10 +00007581 return (ret);
7582}
7583
7584/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007585 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007586 * @ctxt: a schema validation context
7587 * @schema: the schema being built
7588 * @node: a subtree containing XML Schema informations
7589 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007590 * Parse an attribute group definition reference.
7591 * Note that a reference to an attribute group does not
7592 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007593 * *WARNING* this interface is highly subject to change
7594 *
7595 * Returns the attribute group or NULL in case of error.
7596 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007597static xmlSchemaQNameRefPtr
7598xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7599 xmlSchemaPtr schema,
7600 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007601{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007602 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007603 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007604 xmlAttrPtr attr;
7605 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007606
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007607 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007608 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007609
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007610 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007611 if (attr == NULL) {
7612 xmlSchemaPMissingAttrErr(pctxt,
7613 XML_SCHEMAP_S4S_ATTR_MISSING,
7614 NULL, node, "ref", NULL);
7615 return (NULL);
7616 }
7617 xmlSchemaPValAttrNodeQName(pctxt, schema,
7618 NULL, attr, &refNs, &ref);
7619 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7620 return(NULL);
7621
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007622 /*
7623 * Check for illegal attributes.
7624 */
7625 attr = node->properties;
7626 while (attr != NULL) {
7627 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007628 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007629 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007630 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007631 xmlSchemaPIllegalAttrErr(pctxt,
7632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007633 }
7634 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007635 xmlSchemaPIllegalAttrErr(pctxt,
7636 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007637 }
7638 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007639 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007640 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007641 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7642
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007643 /*
7644 * And now for the children...
7645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007646 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007647 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007648 /*
7649 * TODO: We do not have a place to store the annotation, do we?
7650 */
7651 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007652 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007653 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007654 if (child != NULL) {
7655 xmlSchemaPContentErr(pctxt,
7656 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7657 NULL, node, child, NULL,
7658 "(annotation?)");
7659 }
7660
7661 /*
7662 * Handle attribute group redefinitions.
7663 */
7664 if (pctxt->isRedefine && pctxt->redef &&
7665 (pctxt->redef->item->type ==
7666 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7667 (ref == pctxt->redef->refName) &&
7668 (refNs == pctxt->redef->refTargetNs))
7669 {
7670 /*
7671 * SPEC src-redefine:
7672 * (7.1) "If it has an <attributeGroup> among its contents
7673 * the ·actual value· of whose ref [attribute] is the same
7674 * as the ·actual value· of its own name attribute plus
7675 * target namespace, then it must have exactly one such group."
7676 */
7677 if (pctxt->redefCounter != 0) {
7678 xmlChar *str = NULL;
7679
7680 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7681 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7682 "The redefining attribute group definition "
7683 "'%s' must not contain more than one "
7684 "reference to the redefined definition",
7685 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7686 FREE_AND_NULL(str);
7687 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007688 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007689 pctxt->redefCounter++;
7690 /*
7691 * URGENT TODO: How to ensure that the reference will not be
7692 * handled by the normal component resolution mechanism?
7693 */
7694 ret = xmlSchemaNewQNameRef(pctxt,
7695 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7696 if (ret == NULL)
7697 return(NULL);
7698 ret->node = node;
7699 pctxt->redef->reference = WXS_BASIC_CAST ret;
7700 } else {
7701 /*
7702 * Create a QName-reference helper component. We will substitute this
7703 * component for the attribute uses of the referenced attribute group
7704 * definition.
7705 */
7706 ret = xmlSchemaNewQNameRef(pctxt,
7707 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7708 if (ret == NULL)
7709 return(NULL);
7710 ret->node = node;
7711 /* Add to pending items, to be able to resolve the reference. */
7712 WXS_ADD_PENDING(pctxt, ret);
7713 }
7714 return (ret);
7715}
7716
7717/**
7718 * xmlSchemaParseAttributeGroupDefinition:
7719 * @pctxt: a schema validation context
7720 * @schema: the schema being built
7721 * @node: a subtree containing XML Schema informations
7722 *
7723 * parse a XML schema Attribute Group declaration
7724 * *WARNING* this interface is highly subject to change
7725 *
7726 * Returns the attribute group definition or NULL in case of error.
7727 */
7728static xmlSchemaAttributeGroupPtr
7729xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7730 xmlSchemaPtr schema,
7731 xmlNodePtr node)
7732{
7733 const xmlChar *name;
7734 xmlSchemaAttributeGroupPtr ret;
7735 xmlNodePtr child = NULL;
7736 xmlAttrPtr attr;
7737 int hasRefs = 0;
7738
7739 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7740 return (NULL);
7741
7742 attr = xmlSchemaGetPropNode(node, "name");
7743 if (attr == NULL) {
7744 xmlSchemaPMissingAttrErr(pctxt,
7745 XML_SCHEMAP_S4S_ATTR_MISSING,
7746 NULL, node, "name", NULL);
7747 return (NULL);
7748 }
7749 /*
7750 * The name is crucial, exit if invalid.
7751 */
7752 if (xmlSchemaPValAttrNode(pctxt,
7753 NULL, attr,
7754 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7755 return (NULL);
7756 }
7757 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7758 name, pctxt->targetNamespace, node);
7759 if (ret == NULL)
7760 return (NULL);
7761 /*
7762 * Check for illegal attributes.
7763 */
7764 attr = node->properties;
7765 while (attr != NULL) {
7766 if (attr->ns == NULL) {
7767 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7768 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7769 {
7770 xmlSchemaPIllegalAttrErr(pctxt,
7771 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7772 }
7773 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7774 xmlSchemaPIllegalAttrErr(pctxt,
7775 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7776 }
7777 attr = attr->next;
7778 }
7779 /* Attribute ID */
7780 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7781 /*
7782 * And now for the children...
7783 */
7784 child = node->children;
7785 if (IS_SCHEMA(child, "annotation")) {
7786 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7787 child = child->next;
7788 }
7789 /*
7790 * Parse contained attribute decls/refs.
7791 */
7792 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7793 (xmlSchemaItemListPtr *) &(ret->attrUses),
7794 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7795 return(NULL);
7796 if (hasRefs)
7797 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7798 /*
7799 * Parse the attribute wildcard.
7800 */
7801 if (IS_SCHEMA(child, "anyAttribute")) {
7802 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7803 schema, child);
7804 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007805 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007806 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007807 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007808 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007809 NULL, node, child, NULL,
7810 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007811 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007812 return (ret);
7813}
7814
7815/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007816 * xmlSchemaPValAttrFormDefault:
7817 * @value: the value
7818 * @flags: the flags to be modified
7819 * @flagQualified: the specific flag for "qualified"
7820 *
7821 * Returns 0 if the value is valid, 1 otherwise.
7822 */
7823static int
7824xmlSchemaPValAttrFormDefault(const xmlChar *value,
7825 int *flags,
7826 int flagQualified)
7827{
7828 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7829 if ((*flags & flagQualified) == 0)
7830 *flags |= flagQualified;
7831 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007832 return (1);
7833
William M. Brack2f2a6632004-08-20 23:09:47 +00007834 return (0);
7835}
7836
7837/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007838 * xmlSchemaPValAttrBlockFinal:
7839 * @value: the value
7840 * @flags: the flags to be modified
7841 * @flagAll: the specific flag for "#all"
7842 * @flagExtension: the specific flag for "extension"
7843 * @flagRestriction: the specific flag for "restriction"
7844 * @flagSubstitution: the specific flag for "substitution"
7845 * @flagList: the specific flag for "list"
7846 * @flagUnion: the specific flag for "union"
7847 *
7848 * Validates the value of the attribute "final" and "block". The value
7849 * is converted into the specified flag values and returned in @flags.
7850 *
7851 * Returns 0 if the value is valid, 1 otherwise.
7852 */
7853
7854static int
7855xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007856 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007857 int flagAll,
7858 int flagExtension,
7859 int flagRestriction,
7860 int flagSubstitution,
7861 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007862 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007863{
7864 int ret = 0;
7865
7866 /*
7867 * TODO: This does not check for dublicate entries.
7868 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007869 if ((flags == NULL) || (value == NULL))
7870 return (-1);
7871 if (value[0] == 0)
7872 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007873 if (xmlStrEqual(value, BAD_CAST "#all")) {
7874 if (flagAll != -1)
7875 *flags |= flagAll;
7876 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 if (flagExtension != -1)
7878 *flags |= flagExtension;
7879 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007881 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007882 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007883 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007884 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007886 *flags |= flagUnion;
7887 }
7888 } else {
7889 const xmlChar *end, *cur = value;
7890 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007891
Daniel Veillardc0826a72004-08-10 14:17:33 +00007892 do {
7893 while (IS_BLANK_CH(*cur))
7894 cur++;
7895 end = cur;
7896 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7897 end++;
7898 if (end == cur)
7899 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007900 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007901 if (xmlStrEqual(item, BAD_CAST "extension")) {
7902 if (flagExtension != -1) {
7903 if ((*flags & flagExtension) == 0)
7904 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007906 ret = 1;
7907 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7908 if (flagRestriction != -1) {
7909 if ((*flags & flagRestriction) == 0)
7910 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007911 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007912 ret = 1;
7913 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7914 if (flagSubstitution != -1) {
7915 if ((*flags & flagSubstitution) == 0)
7916 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007918 ret = 1;
7919 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7920 if (flagList != -1) {
7921 if ((*flags & flagList) == 0)
7922 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007923 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007924 ret = 1;
7925 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7926 if (flagUnion != -1) {
7927 if ((*flags & flagUnion) == 0)
7928 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007929 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007930 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007931 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007932 ret = 1;
7933 if (item != NULL)
7934 xmlFree(item);
7935 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007936 } while ((ret == 0) && (*cur != 0));
7937 }
7938
Daniel Veillardc0826a72004-08-10 14:17:33 +00007939 return (ret);
7940}
7941
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007942static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007943xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007944 xmlSchemaIDCPtr idc,
7945 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007946 xmlAttrPtr attr,
7947 int isField)
7948{
7949 xmlNodePtr node;
7950
7951 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007952 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007953 * Schema Component Constraint: Selector Value OK
7954 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007955 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007956 * in [XPath].
7957 */
7958 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007960 XML_SCHEMAP_INTERNAL,
7961 "Internal error: xmlSchemaCheckCSelectorXPath, "
7962 "the selector is not specified.\n", NULL, NULL);
7963 return (-1);
7964 }
7965 if (attr == NULL)
7966 node = idc->node;
7967 else
7968 node = (xmlNodePtr) attr;
7969 if (selector->xpath == NULL) {
7970 xmlSchemaPCustomErr(ctxt,
7971 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007973 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007974 "The XPath expression of the selector is not valid", NULL);
7975 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7976 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007977 const xmlChar **nsArray = NULL;
7978 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007979 /*
7980 * Compile the XPath expression.
7981 */
7982 /*
7983 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007984 * TODO: Call xmlPatterncompile with different options for selector/
7985 * field.
7986 */
7987 nsList = xmlGetNsList(attr->doc, attr->parent);
7988 /*
7989 * Build an array of prefixes and namespaces.
7990 */
7991 if (nsList != NULL) {
7992 int i, count = 0;
7993 xmlNsPtr ns;
7994
7995 for (i = 0; nsList[i] != NULL; i++)
7996 count++;
7997
7998 nsArray = (const xmlChar **) xmlMalloc(
7999 (count * 2 + 1) * sizeof(const xmlChar *));
8000 if (nsArray == NULL) {
8001 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8002 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008003 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008004 return (-1);
8005 }
8006 for (i = 0; i < count; i++) {
8007 ns = nsList[i];
8008 nsArray[2 * i] = nsList[i]->href;
8009 nsArray[2 * i + 1] = nsList[i]->prefix;
8010 }
8011 nsArray[count * 2] = NULL;
8012 xmlFree(nsList);
8013 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 /*
8015 * TODO: Differentiate between "selector" and "field".
8016 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008017 if (isField)
8018 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008019 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008020 else
8021 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008022 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008023 if (nsArray != NULL)
8024 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008025
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008026 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008027 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008028 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008029 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008030 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008031 "The XPath expression '%s' could not be "
8032 "compiled", selector->xpath);
8033 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008034 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008035 }
8036 return (0);
8037}
8038
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008039#define ADD_ANNOTATION(annot) \
8040 xmlSchemaAnnotPtr cur = item->annot; \
8041 if (item->annot == NULL) { \
8042 item->annot = annot; \
8043 return (annot); \
8044 } \
8045 cur = item->annot; \
8046 if (cur->next != NULL) { \
8047 cur = cur->next; \
8048 } \
8049 cur->next = annot;
8050
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008051/**
8052 * xmlSchemaAssignAnnotation:
8053 * @item: the schema component
8054 * @annot: the annotation
8055 *
8056 * Adds the annotation to the given schema component.
8057 *
8058 * Returns the given annotaion.
8059 */
8060static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008061xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8062 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008063{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008064 if ((annItem == NULL) || (annot == NULL))
8065 return (NULL);
8066 switch (annItem->type) {
8067 case XML_SCHEMA_TYPE_ELEMENT: {
8068 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8069 ADD_ANNOTATION(annot)
8070 }
8071 break;
8072 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8073 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8074 ADD_ANNOTATION(annot)
8075 }
8076 break;
8077 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8078 case XML_SCHEMA_TYPE_ANY: {
8079 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8080 ADD_ANNOTATION(annot)
8081 }
8082 break;
8083 case XML_SCHEMA_TYPE_PARTICLE:
8084 case XML_SCHEMA_TYPE_IDC_KEY:
8085 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008086 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008087 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8088 ADD_ANNOTATION(annot)
8089 }
8090 break;
8091 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8092 xmlSchemaAttributeGroupPtr item =
8093 (xmlSchemaAttributeGroupPtr) annItem;
8094 ADD_ANNOTATION(annot)
8095 }
8096 break;
8097 case XML_SCHEMA_TYPE_NOTATION: {
8098 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8099 ADD_ANNOTATION(annot)
8100 }
8101 break;
8102 case XML_SCHEMA_FACET_MININCLUSIVE:
8103 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8104 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8105 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8106 case XML_SCHEMA_FACET_TOTALDIGITS:
8107 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8108 case XML_SCHEMA_FACET_PATTERN:
8109 case XML_SCHEMA_FACET_ENUMERATION:
8110 case XML_SCHEMA_FACET_WHITESPACE:
8111 case XML_SCHEMA_FACET_LENGTH:
8112 case XML_SCHEMA_FACET_MAXLENGTH:
8113 case XML_SCHEMA_FACET_MINLENGTH: {
8114 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8115 ADD_ANNOTATION(annot)
8116 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008117 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008118 case XML_SCHEMA_TYPE_SIMPLE:
8119 case XML_SCHEMA_TYPE_COMPLEX: {
8120 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8121 ADD_ANNOTATION(annot)
8122 }
8123 break;
8124 case XML_SCHEMA_TYPE_GROUP: {
8125 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8126 ADD_ANNOTATION(annot)
8127 }
8128 break;
8129 case XML_SCHEMA_TYPE_SEQUENCE:
8130 case XML_SCHEMA_TYPE_CHOICE:
8131 case XML_SCHEMA_TYPE_ALL: {
8132 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8133 ADD_ANNOTATION(annot)
8134 }
8135 break;
8136 default:
8137 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008138 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008139 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008140 "Internal error: xmlSchemaAddAnnotation, "
8141 "The item is not a annotated schema component", NULL);
8142 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008143 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008144 return (annot);
8145}
8146
8147/**
8148 * xmlSchemaParseIDCSelectorAndField:
8149 * @ctxt: a schema validation context
8150 * @schema: the schema being built
8151 * @node: a subtree containing XML Schema informations
8152 *
8153 * Parses a XML Schema identity-contraint definition's
8154 * <selector> and <field> elements.
8155 *
8156 * Returns the parsed identity-constraint definition.
8157 */
8158static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008159xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008160 xmlSchemaPtr schema,
8161 xmlSchemaIDCPtr idc,
8162 xmlNodePtr node,
8163 int isField)
8164{
8165 xmlSchemaIDCSelectPtr item;
8166 xmlNodePtr child = NULL;
8167 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008169 /*
8170 * Check for illegal attributes.
8171 */
8172 attr = node->properties;
8173 while (attr != NULL) {
8174 if (attr->ns == NULL) {
8175 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8176 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008177 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008179 }
8180 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008181 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008183 }
8184 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008186 /*
8187 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008189 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8190 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191 xmlSchemaPErrMemory(ctxt,
8192 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008193 NULL);
8194 return (NULL);
8195 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008197 /*
8198 * Attribute "xpath" (mandatory).
8199 */
8200 attr = xmlSchemaGetPropNode(node, "xpath");
8201 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008202 xmlSchemaPMissingAttrErr(ctxt,
8203 XML_SCHEMAP_S4S_ATTR_MISSING,
8204 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008205 "name", NULL);
8206 } else {
8207 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8208 /*
8209 * URGENT TODO: "field"s have an other syntax than "selector"s.
8210 */
8211
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008212 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8213 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008214 xmlSchemaPErr(ctxt,
8215 (xmlNodePtr) attr,
8216 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008217 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008218 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008219 NULL, NULL);
8220 }
8221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008222 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008223 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008224 /*
8225 * And now for the children...
8226 */
8227 child = node->children;
8228 if (IS_SCHEMA(child, "annotation")) {
8229 /*
8230 * Add the annotation to the parent IDC.
8231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008232 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008233 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008234 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008236 if (child != NULL) {
8237 xmlSchemaPContentErr(ctxt,
8238 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008239 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008240 NULL, "(annotation?)");
8241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008243 return (item);
8244}
8245
8246/**
8247 * xmlSchemaParseIDC:
8248 * @ctxt: a schema validation context
8249 * @schema: the schema being built
8250 * @node: a subtree containing XML Schema informations
8251 *
8252 * Parses a XML Schema identity-contraint definition.
8253 *
8254 * Returns the parsed identity-constraint definition.
8255 */
8256static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008258 xmlSchemaPtr schema,
8259 xmlNodePtr node,
8260 xmlSchemaTypeType idcCategory,
8261 const xmlChar *targetNamespace)
8262{
8263 xmlSchemaIDCPtr item = NULL;
8264 xmlNodePtr child = NULL;
8265 xmlAttrPtr attr;
8266 const xmlChar *name = NULL;
8267 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008268
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008269 /*
8270 * Check for illegal attributes.
8271 */
8272 attr = node->properties;
8273 while (attr != NULL) {
8274 if (attr->ns == NULL) {
8275 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8276 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8277 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8278 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008279 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008280 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008281 }
8282 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008283 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008285 }
8286 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008288 /*
8289 * Attribute "name" (mandatory).
8290 */
8291 attr = xmlSchemaGetPropNode(node, "name");
8292 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008293 xmlSchemaPMissingAttrErr(ctxt,
8294 XML_SCHEMAP_S4S_ATTR_MISSING,
8295 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008296 "name", NULL);
8297 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008299 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008300 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8301 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008302 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008303 /* Create the component. */
8304 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8305 idcCategory, node);
8306 if (item == NULL)
8307 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008308
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008309 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008310 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8311 /*
8312 * Attribute "refer" (mandatory).
8313 */
8314 attr = xmlSchemaGetPropNode(node, "refer");
8315 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008316 xmlSchemaPMissingAttrErr(ctxt,
8317 XML_SCHEMAP_S4S_ATTR_MISSING,
8318 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008319 "refer", NULL);
8320 } else {
8321 /*
8322 * Create a reference item.
8323 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008324 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008325 NULL, NULL);
8326 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008327 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008328 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008329 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008331 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008332 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008333 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008334 }
8335 }
8336 /*
8337 * And now for the children...
8338 */
8339 child = node->children;
8340 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008341 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008342 child = child->next;
8343 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008344 if (child == NULL) {
8345 xmlSchemaPContentErr(ctxt,
8346 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008347 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008348 "A child element is missing",
8349 "(annotation?, (selector, field+))");
8350 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008351 /*
8352 * Child element <selector>.
8353 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 if (IS_SCHEMA(child, "selector")) {
8355 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008356 item, child, 0);
8357 child = child->next;
8358 /*
8359 * Child elements <field>.
8360 */
8361 if (IS_SCHEMA(child, "field")) {
8362 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008364 item, child, 1);
8365 if (field != NULL) {
8366 field->index = item->nbFields;
8367 item->nbFields++;
8368 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008369 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008370 else
8371 item->fields = field;
8372 lastField = field;
8373 }
8374 child = child->next;
8375 } while (IS_SCHEMA(child, "field"));
8376 } else {
8377 xmlSchemaPContentErr(ctxt,
8378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008379 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008380 NULL, "(annotation?, (selector, field+))");
8381 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008382 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008383 if (child != NULL) {
8384 xmlSchemaPContentErr(ctxt,
8385 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008386 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008387 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008388 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008389
8390 return (item);
8391}
8392
Daniel Veillardc0826a72004-08-10 14:17:33 +00008393/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008394 * xmlSchemaParseElement:
8395 * @ctxt: a schema validation context
8396 * @schema: the schema being built
8397 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008398 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008399 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008400 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008401 * *WARNING* this interface is highly subject to change
8402 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008403 * Returns the element declaration or a particle; NULL in case
8404 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008405 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008406static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008407xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008408 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008409{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008410 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008411 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008412 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008413 xmlNodePtr child = NULL;
8414 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008415 int min, max, isRef = 0;
8416 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008417
8418 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8419 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008420
Daniel Veillard4255d502002-04-16 15:50:10 +00008421 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008422 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008423
8424 if (isElemRef != NULL)
8425 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008426 /*
8427 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008428 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008429 * robust.
8430 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008431 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008432 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008433 if ((topLevel) || (attr == NULL)) {
8434 if (nameAttr == NULL) {
8435 xmlSchemaPMissingAttrErr(ctxt,
8436 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008437 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008438 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008440 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008441 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008442
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008443 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008444 child = node->children;
8445 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008446 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008447 child = child->next;
8448 }
8449 /*
8450 * Skip particle part if a global declaration.
8451 */
8452 if (topLevel)
8453 goto declaration_part;
8454 /*
8455 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008456 */
8457 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8458 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8459 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008460 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8461 if (particle == NULL)
8462 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008463
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8465
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008466 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008467 const xmlChar *refNs = NULL, *ref = NULL;
8468 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008469 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008470 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008471 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008472 if (isElemRef != NULL)
8473 *isElemRef = 1;
8474
Daniel Veillardc0826a72004-08-10 14:17:33 +00008475 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008476 NULL, attr, &refNs, &ref);
8477 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008478 /*
8479 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008480 */
8481 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008482 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008483 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008485 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008486 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008487 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008488 attr = node->properties;
8489 while (attr != NULL) {
8490 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008491 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8492 xmlStrEqual(attr->name, BAD_CAST "name") ||
8493 xmlStrEqual(attr->name, BAD_CAST "id") ||
8494 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8495 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8496 {
8497 attr = attr->next;
8498 continue;
8499 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008500 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008501 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008502 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008503 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008504 "Only the attributes 'minOccurs', 'maxOccurs' and "
8505 "'id' are allowed in addition to 'ref'");
8506 break;
8507 }
8508 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8509 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008510 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008511 }
8512 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008513 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008514 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008515 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008516 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008517 if (child != NULL) {
8518 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008519 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008520 }
8521 if ((min == 0) && (max == 0))
8522 goto return_null;
8523 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008524 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008525 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008526 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008527 ref, refNs);
8528 if (refer == NULL)
8529 goto return_null;
8530 particle->children = (xmlSchemaTreeItemPtr) refer;
8531 particle->annot = annot;
8532 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008533 * Add the particle to pending components, since the reference
8534 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008535 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008536 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008537 return ((xmlSchemaBasicItemPtr) particle);
8538 }
8539 /*
8540 * The declaration part ===============================================
8541 */
8542declaration_part:
8543 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008544 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008545 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8546
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008547 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008548 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008549 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008550 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008551 * Evaluate the target namespace.
8552 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008553 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008554 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008555 } else {
8556 attr = xmlSchemaGetPropNode(node, "form");
8557 if (attr != NULL) {
8558 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8559 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008560 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008561 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008562 xmlSchemaPSimpleTypeErr(ctxt,
8563 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8564 NULL, (xmlNodePtr) attr,
8565 NULL, "(qualified | unqualified)",
8566 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008567 }
8568 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008569 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008570 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008571 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008572 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008573 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008574 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008575 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008576 * Check for illegal attributes.
8577 */
William M. Bracke7091952004-05-11 15:09:58 +00008578 attr = node->properties;
8579 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008580 if (attr->ns == NULL) {
8581 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8582 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008583 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008584 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008586 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008587 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8588 {
8589 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008590 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008591 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008592 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008593 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008594 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008595 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8598 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008599 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8600
8601 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008603 }
8604 }
8605 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008606
Daniel Veillardc0826a72004-08-10 14:17:33 +00008607 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008609 }
8610 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611 }
William M. Bracke7091952004-05-11 15:09:58 +00008612 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008613 * Extract/validate attributes.
8614 */
8615 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008616 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008617 * Process top attributes of global element declarations here.
8618 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008619 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8620 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008621 xmlSchemaPValAttrQName(ctxt, schema,
8622 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008624 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008625 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008626 /*
8627 * Attribute "final".
8628 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008630 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008631 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8632 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8633 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8634 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008635 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8637 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008638 -1,
8639 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8640 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008642 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008643 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008644 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008645 attrValue, NULL, NULL, NULL);
8646 }
8647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008649 /*
8650 * Attribute "block".
8651 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008652 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008653 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008654 /*
8655 * Apply default "block" values.
8656 */
8657 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8658 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8659 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8660 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8661 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8662 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008663 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008664 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008666 -1,
8667 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008668 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008669 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8670 xmlSchemaPSimpleTypeErr(ctxt,
8671 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008672 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008673 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008674 "restriction | substitution))", attrValue,
8675 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008676 }
8677 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008678 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008680
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008681 attr = xmlSchemaGetPropNode(node, "type");
8682 if (attr != NULL) {
8683 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008684 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008685 &(decl->namedTypeNs), &(decl->namedType));
8686 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008687 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008688 }
8689 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8690 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 if (attr != NULL) {
8692 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008693 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008694 /*
8695 * 3.3.3 : 1
8696 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008697 */
8698 xmlSchemaPMutualExclAttrErr(ctxt,
8699 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008700 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008702 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8703 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008704 }
William M. Bracke7091952004-05-11 15:09:58 +00008705 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008706 /*
8707 * And now for the children...
8708 */
William M. Bracke7091952004-05-11 15:09:58 +00008709 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008710 /*
8711 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008712 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008713 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008714 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008715 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008716 xmlSchemaPContentErr(ctxt,
8717 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008718 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008719 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008720 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008721 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008722 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008723 child = child->next;
8724 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008725 /*
8726 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008727 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008728 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008730 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008731 xmlSchemaPContentErr(ctxt,
8732 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008733 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008734 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008735 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008736 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008737 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008738 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008739 }
William M. Bracke7091952004-05-11 15:09:58 +00008740 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008741 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008742 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008743 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008744 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008745 } else if (IS_SCHEMA(child, "key")) {
8746 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008747 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008748 } else if (IS_SCHEMA(child, "keyref")) {
8749 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008750 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008751 }
8752 if (lastIDC != NULL)
8753 lastIDC->next = curIDC;
8754 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008755 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008756 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008757 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008758 }
8759 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008760 xmlSchemaPContentErr(ctxt,
8761 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008762 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008763 NULL, "(annotation?, ((simpleType | complexType)?, "
8764 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008765 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008766 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008767 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008768 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008769 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008770 * different layer.
8771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008772 FREE_AND_NULL(des)
8773 if (topLevel)
8774 return ((xmlSchemaBasicItemPtr) decl);
8775 else {
8776 particle->children = (xmlSchemaTreeItemPtr) decl;
8777 return ((xmlSchemaBasicItemPtr) particle);
8778 }
8779
8780return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008781 FREE_AND_NULL(des);
8782 if (annot != NULL) {
8783 if (particle != NULL)
8784 particle->annot = NULL;
8785 if (decl != NULL)
8786 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008787 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008788 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008789 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008790}
8791
8792/**
8793 * xmlSchemaParseUnion:
8794 * @ctxt: a schema validation context
8795 * @schema: the schema being built
8796 * @node: a subtree containing XML Schema informations
8797 *
8798 * parse a XML schema Union definition
8799 * *WARNING* this interface is highly subject to change
8800 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008801 * Returns -1 in case of internal error, 0 in case of success and a positive
8802 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008803 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008804static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008805xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008806 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008807{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008808 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008809 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008810 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008811 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008812
8813 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008814 return (-1);
8815 /* Not a component, don't create it. */
8816 type = ctxt->ctxtType;
8817 /*
8818 * Mark the simple type as being of variety "union".
8819 */
8820 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008821 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008822 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8823 * then the ·simple ur-type definition·."
8824 */
8825 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008826 /*
8827 * Check for illegal attributes.
8828 */
8829 attr = node->properties;
8830 while (attr != NULL) {
8831 if (attr->ns == NULL) {
8832 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8833 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008835 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008836 }
8837 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008838 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008839 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008840 }
8841 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008843 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008844 /*
8845 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008846 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008847 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008849 if (attr != NULL) {
8850 const xmlChar *end;
8851 xmlChar *tmp;
8852 const xmlChar *localName, *nsName;
8853 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8854 xmlSchemaQNameRefPtr ref;
8855
8856 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008857 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008858 do {
8859 while (IS_BLANK_CH(*cur))
8860 cur++;
8861 end = cur;
8862 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8863 end++;
8864 if (end == cur)
8865 break;
8866 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008867 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008868 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008869 /*
8870 * Create the member type link.
8871 */
8872 link = (xmlSchemaTypeLinkPtr)
8873 xmlMalloc(sizeof(xmlSchemaTypeLink));
8874 if (link == NULL) {
8875 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8876 "allocating a type link", NULL);
8877 return (-1);
8878 }
8879 link->type = NULL;
8880 link->next = NULL;
8881 if (lastLink == NULL)
8882 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008884 lastLink->next = link;
8885 lastLink = link;
8886 /*
8887 * Create a reference item.
8888 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008889 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008890 localName, nsName);
8891 if (ref == NULL) {
8892 FREE_AND_NULL(tmp)
8893 return (-1);
8894 }
8895 /*
8896 * Assign the reference to the link, it will be resolved
8897 * later during fixup of the union simple type.
8898 */
8899 link->type = (xmlSchemaTypePtr) ref;
8900 }
8901 FREE_AND_NULL(tmp)
8902 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008904
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008905 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008906 /*
8907 * And now for the children...
8908 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008909 child = node->children;
8910 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008911 /*
8912 * Add the annotation to the simple type ancestor.
8913 */
8914 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008915 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008916 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008918 if (IS_SCHEMA(child, "simpleType")) {
8919 xmlSchemaTypePtr subtype, last = NULL;
8920
8921 /*
8922 * Anchor the member types in the "subtypes" field of the
8923 * simple type.
8924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008925 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008926 subtype = (xmlSchemaTypePtr)
8927 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8928 if (subtype != NULL) {
8929 if (last == NULL) {
8930 type->subtypes = subtype;
8931 last = subtype;
8932 } else {
8933 last->next = subtype;
8934 last = subtype;
8935 }
8936 last->next = NULL;
8937 }
8938 child = child->next;
8939 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008940 }
8941 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008942 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008944 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008945 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008946 if ((attr == NULL) && (type->subtypes == NULL)) {
8947 /*
8948 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008949 * Either the memberTypes [attribute] of the <union> element must
8950 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008952 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008953 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008954 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008955 "Either the attribute 'memberTypes' or "
8956 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008958 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008959}
8960
8961/**
8962 * xmlSchemaParseList:
8963 * @ctxt: a schema validation context
8964 * @schema: the schema being built
8965 * @node: a subtree containing XML Schema informations
8966 *
8967 * parse a XML schema List definition
8968 * *WARNING* this interface is highly subject to change
8969 *
William M. Bracke7091952004-05-11 15:09:58 +00008970 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008971 * 1 in case of success.
8972 */
8973static xmlSchemaTypePtr
8974xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008975 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008976{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008977 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008978 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008979 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008980
8981 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8982 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008983 /* Not a component, don't create it. */
8984 type = ctxt->ctxtType;
8985 /*
8986 * Mark the type as being of variety "list".
8987 */
8988 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008989 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008990 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8991 * then the ·simple ur-type definition·."
8992 */
8993 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008994 /*
8995 * Check for illegal attributes.
8996 */
8997 attr = node->properties;
8998 while (attr != NULL) {
8999 if (attr->ns == NULL) {
9000 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9001 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009002 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009003 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009004 }
9005 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009006 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009007 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009008 }
9009 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009011
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009012 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009013
William M. Brack2f2a6632004-08-20 23:09:47 +00009014 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009015 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9016 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009017 *
9018 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9019 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009020 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009021 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9022 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009023 /*
9024 * And now for the children...
9025 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009026 child = node->children;
9027 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009028 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009029 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009030 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009031 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009032 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009033 /*
9034 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009035 * Either the itemType [attribute] or the <simpleType> [child] of
9036 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009037 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009038 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009039 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009040 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009041 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009042 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009043 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009044 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009045 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009047 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009048 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009050 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009051 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009052 "Either the attribute 'itemType' or the <simpleType> child "
9053 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009054 }
9055 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009056 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009058 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009059 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009060 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009061 (type->subtypes == NULL) &&
9062 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009063 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009064 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009065 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009066 "Either the attribute 'itemType' or the <simpleType> child "
9067 "must be present", NULL);
9068 }
9069 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009070}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009071
Daniel Veillard4255d502002-04-16 15:50:10 +00009072/**
9073 * xmlSchemaParseSimpleType:
9074 * @ctxt: a schema validation context
9075 * @schema: the schema being built
9076 * @node: a subtree containing XML Schema informations
9077 *
9078 * parse a XML schema Simple Type definition
9079 * *WARNING* this interface is highly subject to change
9080 *
William M. Bracke7091952004-05-11 15:09:58 +00009081 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009082 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009083 */
9084static xmlSchemaTypePtr
9085xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009086 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009087{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009088 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009089 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009090 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009091 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009092 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009093
9094 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9095 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009096
Daniel Veillardc0826a72004-08-10 14:17:33 +00009097 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009098 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009099 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009100 xmlSchemaPMissingAttrErr(ctxt,
9101 XML_SCHEMAP_S4S_ATTR_MISSING,
9102 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009103 "name", NULL);
9104 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009105 } else {
9106 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009107 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009108 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9109 return (NULL);
9110 /*
9111 * Skip built-in types.
9112 */
9113 if (ctxt->isS4S) {
9114 xmlSchemaTypePtr biType;
9115
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009116 if (ctxt->isRedefine) {
9117 /*
9118 * REDEFINE: Disallow redefinition of built-in-types.
9119 * TODO: It seems that the spec does not say anything
9120 * about this case.
9121 */
9122 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009123 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009124 "Redefinition of built-in simple types is not "
9125 "supported", NULL);
9126 return(NULL);
9127 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009128 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9129 if (biType != NULL)
9130 return (biType);
9131 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009132 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009133 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009134 /*
9135 * TargetNamespace:
9136 * SPEC "The ·actual value· of the targetNamespace [attribute]
9137 * of the <schema> ancestor element information item if present,
9138 * otherwise ·absent·.
9139 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009140 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009141#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009142 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009143#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009144 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009145 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009146 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009147#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009148 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009149 type = xmlSchemaAddType(ctxt, schema,
9150 XML_SCHEMA_TYPE_SIMPLE,
9151 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009152 ctxt->targetNamespace, node, 0);
9153#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009154 type = xmlSchemaAddType(ctxt, schema,
9155 XML_SCHEMA_TYPE_SIMPLE,
9156 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009157#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009158 if (type == NULL)
9159 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009161 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009162 /*
9163 * Check for illegal attributes.
9164 */
9165 attr = node->properties;
9166 while (attr != NULL) {
9167 if (attr->ns == NULL) {
9168 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009169 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009170 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009171 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009172 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009175 }
9176 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009177 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009178 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009179 /*
9180 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009181 *
9182 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009183 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009184 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9185 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009186 if (type == NULL)
9187 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009188 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009189 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009190 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9191 /*
9192 * Check for illegal attributes.
9193 */
9194 attr = node->properties;
9195 while (attr != NULL) {
9196 if (attr->ns == NULL) {
9197 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9198 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009199 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009200 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009202 }
9203 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009204 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009206 }
9207 attr = attr->next;
9208 }
9209 /*
9210 * Attribute "final".
9211 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009212 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009213 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009214 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9215 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9216 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9217 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9218 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9219 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009220 } else {
9221 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009222 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9223 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009224 XML_SCHEMAS_TYPE_FINAL_LIST,
9225 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9226
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009227 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009228 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009229 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009231 attrValue, NULL, NULL, NULL);
9232 }
9233 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009234 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009235 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009236 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009237 /*
9238 * And now for the children...
9239 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009240 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009241
Daniel Veillardc0826a72004-08-10 14:17:33 +00009242 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009243
Daniel Veillard4255d502002-04-16 15:50:10 +00009244 child = node->children;
9245 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009246 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009247 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009248 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009249 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009250 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009251 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009252 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009253 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009254 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009255 XML_SCHEMA_TYPE_SIMPLE);
9256 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009257 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009258 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009259 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009260 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009261 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009262 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009263 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009264 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009265 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009266 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009267 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009268 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009269 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009270 /*
9271 * REDEFINE: SPEC src-redefine (5)
9272 * "Within the [children], each <simpleType> must have a
9273 * <restriction> among its [children] ... the ·actual value· of whose
9274 * base [attribute] must be the same as the ·actual value· of its own
9275 * name attribute plus target namespace;"
9276 */
9277 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9278 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009279 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009280 "<simpleType> must have a <restriction> child", NULL);
9281 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009283 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009284 return (type);
9285}
9286
Daniel Veillard4255d502002-04-16 15:50:10 +00009287/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009288 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009289 * @ctxt: the parser context
9290 * @schema: the schema being built
9291 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009292 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009293 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009294 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009295 * We will return a particle component with a qname-component or
9296 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009297 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009298static xmlSchemaTreeItemPtr
9299xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9300 xmlSchemaPtr schema,
9301 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009302{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009303 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009304 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009305 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009306 const xmlChar *ref = NULL, *refNs = NULL;
9307 int min, max;
9308
9309 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009310 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009311
9312 attr = xmlSchemaGetPropNode(node, "ref");
9313 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009314 xmlSchemaPMissingAttrErr(ctxt,
9315 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009316 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009317 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009318 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009319 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009320 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009321 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009322 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009323 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009324 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009325 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009326 /*
9327 * Check for illegal attributes.
9328 */
9329 attr = node->properties;
9330 while (attr != NULL) {
9331 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009332 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009333 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9334 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9335 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009336 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009337 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009338 }
9339 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009340 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009341 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009342 }
9343 attr = attr->next;
9344 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009345 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009346 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9347 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009348 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009350 * Create a qname-reference and set as the term; it will be substituted
9351 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009352 */
9353 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009354 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009355 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9356 /*
9357 * And now for the children...
9358 */
9359 child = node->children;
9360 /* TODO: Is annotation even allowed for a model group reference? */
9361 if (IS_SCHEMA(child, "annotation")) {
9362 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009363 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009364 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009365 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009366 child = child->next;
9367 }
9368 if (child != NULL) {
9369 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009370 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009371 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009372 "(annotation?)");
9373 }
9374 /*
9375 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9376 */
9377 if ((min == 0) && (max == 0))
9378 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009379
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009380 return ((xmlSchemaTreeItemPtr) item);
9381}
9382
9383/**
9384 * xmlSchemaParseModelGroupDefinition:
9385 * @ctxt: a schema validation context
9386 * @schema: the schema being built
9387 * @node: a subtree containing XML Schema informations
9388 *
9389 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009390 *
9391 * Note that the contraint src-redefine (6.2) can't be applied until
9392 * references have been resolved. So we will do this at the
9393 * component fixup level.
9394 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009395 * *WARNING* this interface is highly subject to change
9396 *
9397 * Returns -1 in case of error, 0 if the declaration is improper and
9398 * 1 in case of success.
9399 */
9400static xmlSchemaModelGroupDefPtr
9401xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9402 xmlSchemaPtr schema,
9403 xmlNodePtr node)
9404{
9405 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009406 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009407 xmlAttrPtr attr;
9408 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009409
9410 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009411 return (NULL);
9412
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009413 attr = xmlSchemaGetPropNode(node, "name");
9414 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009415 xmlSchemaPMissingAttrErr(ctxt,
9416 XML_SCHEMAP_S4S_ATTR_MISSING,
9417 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009418 "name", NULL);
9419 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009420 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009421 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9422 return (NULL);
9423 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009424 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9425 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009426 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009427 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009428 /*
9429 * Check for illegal attributes.
9430 */
9431 attr = node->properties;
9432 while (attr != NULL) {
9433 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009434 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009435 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009436 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009437 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009438 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009439 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009441 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009442 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009443 attr = attr->next;
9444 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009445 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009446 /*
9447 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009449 child = node->children;
9450 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009451 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009452 child = child->next;
9453 }
9454 if (IS_SCHEMA(child, "all")) {
9455 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9456 XML_SCHEMA_TYPE_ALL, 0);
9457 child = child->next;
9458 } else if (IS_SCHEMA(child, "choice")) {
9459 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9460 XML_SCHEMA_TYPE_CHOICE, 0);
9461 child = child->next;
9462 } else if (IS_SCHEMA(child, "sequence")) {
9463 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9464 XML_SCHEMA_TYPE_SEQUENCE, 0);
9465 child = child->next;
9466 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009467
9468
9469
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009470 if (child != NULL) {
9471 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009472 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009473 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009474 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009475 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009477}
9478
9479/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009480 * xmlSchemaCleanupDoc:
9481 * @ctxt: a schema validation context
9482 * @node: the root of the document.
9483 *
9484 * removes unwanted nodes in a schemas document tree
9485 */
9486static void
9487xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9488{
9489 xmlNodePtr delete, cur;
9490
9491 if ((ctxt == NULL) || (root == NULL)) return;
9492
9493 /*
9494 * Remove all the blank text nodes
9495 */
9496 delete = NULL;
9497 cur = root;
9498 while (cur != NULL) {
9499 if (delete != NULL) {
9500 xmlUnlinkNode(delete);
9501 xmlFreeNode(delete);
9502 delete = NULL;
9503 }
9504 if (cur->type == XML_TEXT_NODE) {
9505 if (IS_BLANK_NODE(cur)) {
9506 if (xmlNodeGetSpacePreserve(cur) != 1) {
9507 delete = cur;
9508 }
9509 }
9510 } else if ((cur->type != XML_ELEMENT_NODE) &&
9511 (cur->type != XML_CDATA_SECTION_NODE)) {
9512 delete = cur;
9513 goto skip_children;
9514 }
9515
9516 /*
9517 * Skip to next node
9518 */
9519 if (cur->children != NULL) {
9520 if ((cur->children->type != XML_ENTITY_DECL) &&
9521 (cur->children->type != XML_ENTITY_REF_NODE) &&
9522 (cur->children->type != XML_ENTITY_NODE)) {
9523 cur = cur->children;
9524 continue;
9525 }
9526 }
9527 skip_children:
9528 if (cur->next != NULL) {
9529 cur = cur->next;
9530 continue;
9531 }
9532
9533 do {
9534 cur = cur->parent;
9535 if (cur == NULL)
9536 break;
9537 if (cur == root) {
9538 cur = NULL;
9539 break;
9540 }
9541 if (cur->next != NULL) {
9542 cur = cur->next;
9543 break;
9544 }
9545 } while (cur != NULL);
9546 }
9547 if (delete != NULL) {
9548 xmlUnlinkNode(delete);
9549 xmlFreeNode(delete);
9550 delete = NULL;
9551 }
9552}
9553
William M. Brack2f2a6632004-08-20 23:09:47 +00009554
William M. Brack2f2a6632004-08-20 23:09:47 +00009555static void
9556xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9557{
9558 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9559 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9560
9561 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9562 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9563
9564 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9565 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9566 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9567 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9568 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9569 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9570 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9571 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9572
9573 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9574 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9575 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9576 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9577 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9578 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9579}
9580
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009581static int
9582xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009583 xmlSchemaPtr schema,
9584 xmlNodePtr node)
9585{
9586 xmlAttrPtr attr;
9587 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009588 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009589
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009590 /*
9591 * Those flags should be moved to the parser context flags,
9592 * since they are not visible at the component level. I.e.
9593 * they are used if processing schema *documents* only.
9594 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009595 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009596 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009597
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009598 /*
9599 * Since the version is of type xs:token, we won't bother to
9600 * check it.
9601 */
9602 /* REMOVED:
9603 attr = xmlSchemaGetPropNode(node, "version");
9604 if (attr != NULL) {
9605 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9606 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9607 HFAILURE;
9608 }
9609 */
9610 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9611 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009612 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009613 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9614 HFAILURE;
9615 if (res != 0) {
9616 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9617 goto exit;
9618 }
9619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009620 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009621 if (attr != NULL) {
9622 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009623 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9624 XML_SCHEMAS_QUALIF_ELEM);
9625 HFAILURE;
9626 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009629 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009630 "(qualified | unqualified)", val, NULL, NULL, NULL);
9631 }
9632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009633 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009634 if (attr != NULL) {
9635 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009636 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9637 XML_SCHEMAS_QUALIF_ATTR);
9638 HFAILURE;
9639 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009640 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009641 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009642 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009643 "(qualified | unqualified)", val, NULL, NULL, NULL);
9644 }
9645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009647 if (attr != NULL) {
9648 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009649 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009650 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9651 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9652 -1,
9653 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009654 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9655 HFAILURE;
9656 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009657 xmlSchemaPSimpleTypeErr(ctxt,
9658 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009659 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009660 "(#all | List of (extension | restriction | list | union))",
9661 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009662 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009663 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009664 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009665 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009666 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9667 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009668 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9669 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009670 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9671 HFAILURE;
9672 if (res != 0) {
9673 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009674 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009675 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009676 "(#all | List of (extension | restriction | substitution))",
9677 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009679 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009680
9681exit:
9682 if (oldErrs != ctxt->nberrors)
9683 res = ctxt->err;
9684 return(res);
9685exit_failure:
9686 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009687}
9688
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009689/**
9690 * xmlSchemaParseSchemaTopLevel:
9691 * @ctxt: a schema validation context
9692 * @schema: the schemas
9693 * @nodes: the list of top level nodes
9694 *
9695 * Returns the internal XML Schema structure built from the resource or
9696 * NULL in case of error
9697 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009698static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009699xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9700 xmlSchemaPtr schema, xmlNodePtr nodes)
9701{
9702 xmlNodePtr child;
9703 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009704 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009705
9706 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009707 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009708
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009709 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009710 child = nodes;
9711 while ((IS_SCHEMA(child, "include")) ||
9712 (IS_SCHEMA(child, "import")) ||
9713 (IS_SCHEMA(child, "redefine")) ||
9714 (IS_SCHEMA(child, "annotation"))) {
9715 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009716 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009717 if (schema->annot == NULL)
9718 schema->annot = annot;
9719 else
9720 xmlSchemaFreeAnnot(annot);
9721 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009722 tmpOldErrs = ctxt->nberrors;
9723 res = xmlSchemaParseImport(ctxt, schema, child);
9724 HFAILURE;
9725 HSTOP(ctxt);
9726 if (tmpOldErrs != ctxt->nberrors)
9727 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009728 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009729 tmpOldErrs = ctxt->nberrors;
9730 res = xmlSchemaParseInclude(ctxt, schema, child);
9731 HFAILURE;
9732 HSTOP(ctxt);
9733 if (tmpOldErrs != ctxt->nberrors)
9734 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009735 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009736 tmpOldErrs = ctxt->nberrors;
9737 res = xmlSchemaParseRedefine(ctxt, schema, child);
9738 HFAILURE;
9739 HSTOP(ctxt);
9740 if (tmpOldErrs != ctxt->nberrors)
9741 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009742 }
9743 child = child->next;
9744 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009745 /*
9746 * URGENT TODO: Change the functions to return int results.
9747 * We need especially to catch internal errors.
9748 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009749 while (child != NULL) {
9750 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009751 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009752 child = child->next;
9753 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009754 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009755 child = child->next;
9756 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009757 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009758 child = child->next;
9759 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009760 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009761 child = child->next;
9762 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009763 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009764 child = child->next;
9765 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009767 child = child->next;
9768 } else if (IS_SCHEMA(child, "notation")) {
9769 xmlSchemaParseNotation(ctxt, schema, child);
9770 child = child->next;
9771 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009772 xmlSchemaPContentErr(ctxt,
9773 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009774 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009775 NULL, "((include | import | redefine | annotation)*, "
9776 "(((simpleType | complexType | group | attributeGroup) "
9777 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009778 child = child->next;
9779 }
9780 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009781 /*
9782 * TODO: We should add all annotations.
9783 */
9784 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009785 if (schema->annot == NULL)
9786 schema->annot = annot;
9787 else
9788 xmlSchemaFreeAnnot(annot);
9789 child = child->next;
9790 }
9791 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009792exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009793 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009794 if (oldErrs != ctxt->nberrors)
9795 res = ctxt->err;
9796 return(res);
9797exit_failure:
9798 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009799}
9800
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009801static xmlSchemaSchemaRelationPtr
9802xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009803{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009804 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009805
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009806 ret = (xmlSchemaSchemaRelationPtr)
9807 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009808 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009809 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009810 return(NULL);
9811 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009812 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009813 return(ret);
9814}
9815
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009816#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009817static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009818xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009819{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009820 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009821}
9822#endif
9823
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009824static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009825xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9826{
9827 xmlSchemaRedefPtr prev;
9828
9829 while (redef != NULL) {
9830 prev = redef;
9831 redef = redef->next;
9832 xmlFree(prev);
9833 }
9834}
9835
9836static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009837xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9838{
9839 /*
9840 * After the construction context has been freed, there will be
9841 * no schema graph available any more. Only the schema buckets
9842 * will stay alive, which are put into the "schemasImports" and
9843 * "includes" slots of the xmlSchema.
9844 */
9845 if (con->buckets != NULL)
9846 xmlSchemaItemListFree(con->buckets);
9847 if (con->pending != NULL)
9848 xmlSchemaItemListFree(con->pending);
9849 if (con->substGroups != NULL)
9850 xmlHashFree(con->substGroups,
9851 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009852 if (con->redefs != NULL)
9853 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009854 if (con->dict != NULL)
9855 xmlDictFree(con->dict);
9856 xmlFree(con);
9857}
9858
9859static xmlSchemaConstructionCtxtPtr
9860xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9861{
9862 xmlSchemaConstructionCtxtPtr ret;
9863
9864 ret = (xmlSchemaConstructionCtxtPtr)
9865 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9866 if (ret == NULL) {
9867 xmlSchemaPErrMemory(NULL,
9868 "allocating schema construction context", NULL);
9869 return (NULL);
9870 }
9871 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9872
9873 ret->buckets = xmlSchemaItemListCreate();
9874 if (ret->buckets == NULL) {
9875 xmlSchemaPErrMemory(NULL,
9876 "allocating list of schema buckets", NULL);
9877 xmlFree(ret);
9878 return (NULL);
9879 }
9880 ret->pending = xmlSchemaItemListCreate();
9881 if (ret->pending == NULL) {
9882 xmlSchemaPErrMemory(NULL,
9883 "allocating list of pending global components", NULL);
9884 xmlSchemaConstructionCtxtFree(ret);
9885 return (NULL);
9886 }
9887 ret->dict = dict;
9888 xmlDictReference(dict);
9889 return(ret);
9890}
9891
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009892static xmlSchemaParserCtxtPtr
9893xmlSchemaParserCtxtCreate(void)
9894{
9895 xmlSchemaParserCtxtPtr ret;
9896
9897 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9898 if (ret == NULL) {
9899 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9900 NULL);
9901 return (NULL);
9902 }
9903 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9904 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009905 ret->attrProhibs = xmlSchemaItemListCreate();
9906 if (ret->attrProhibs == NULL) {
9907 xmlFree(ret);
9908 return(NULL);
9909 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009910 return(ret);
9911}
9912
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009913/**
9914 * xmlSchemaNewParserCtxtUseDict:
9915 * @URL: the location of the schema
9916 * @dict: the dictionary to be used
9917 *
9918 * Create an XML Schemas parse context for that file/resource expected
9919 * to contain an XML Schemas file.
9920 *
9921 * Returns the parser context or NULL in case of error
9922 */
9923static xmlSchemaParserCtxtPtr
9924xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9925{
9926 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009927
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009928 ret = xmlSchemaParserCtxtCreate();
9929 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009930 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009931 ret->dict = dict;
9932 xmlDictReference(dict);
9933 if (URL != NULL)
9934 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009935 return (ret);
9936}
9937
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009938static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9940{
9941 if (vctxt->pctxt == NULL) {
9942 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009943 vctxt->pctxt =
9944 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009945 else
9946 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9947 if (vctxt->pctxt == NULL) {
9948 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9949 "failed to create a temp. parser context");
9950 return (-1);
9951 }
9952 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009953 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9954 vctxt->warning, vctxt->userData);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009955 }
9956 return (0);
9957}
9958
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009959/**
9960 * xmlSchemaGetSchemaBucket:
9961 * @pctxt: the schema parser context
9962 * @schemaLocation: the URI of the schema document
9963 *
9964 * Returns a schema bucket if it was already parsed.
9965 *
9966 * Returns a schema bucket if it was already parsed from
9967 * @schemaLocation, NULL otherwise.
9968 */
9969static xmlSchemaBucketPtr
9970xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9971 const xmlChar *schemaLocation)
9972{
9973 xmlSchemaBucketPtr cur;
9974 xmlSchemaItemListPtr list;
9975
9976 list = pctxt->constructor->buckets;
9977 if (list->nbItems == 0)
9978 return(NULL);
9979 else {
9980 int i;
9981 for (i = 0; i < list->nbItems; i++) {
9982 cur = (xmlSchemaBucketPtr) list->items[i];
9983 /* Pointer comparison! */
9984 if (cur->schemaLocation == schemaLocation)
9985 return(cur);
9986 }
9987 }
9988 return(NULL);
9989}
9990
9991static xmlSchemaBucketPtr
9992xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9993 const xmlChar *schemaLocation,
9994 const xmlChar *targetNamespace)
9995{
9996 xmlSchemaBucketPtr cur;
9997 xmlSchemaItemListPtr list;
9998
9999 list = pctxt->constructor->buckets;
10000 if (list->nbItems == 0)
10001 return(NULL);
10002 else {
10003 int i;
10004 for (i = 0; i < list->nbItems; i++) {
10005 cur = (xmlSchemaBucketPtr) list->items[i];
10006 /* Pointer comparison! */
10007 if ((cur->origTargetNamespace == NULL) &&
10008 (cur->schemaLocation == schemaLocation) &&
10009 (cur->targetNamespace == targetNamespace))
10010 return(cur);
10011 }
10012 }
10013 return(NULL);
10014}
10015
10016
10017#define IS_BAD_SCHEMA_DOC(b) \
10018 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10019
10020static xmlSchemaBucketPtr
10021xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10022 const xmlChar *targetNamespace,
10023 int imported)
10024{
10025 xmlSchemaBucketPtr cur;
10026 xmlSchemaItemListPtr list;
10027
10028 list = pctxt->constructor->buckets;
10029 if (list->nbItems == 0)
10030 return(NULL);
10031 else {
10032 int i;
10033 for (i = 0; i < list->nbItems; i++) {
10034 cur = (xmlSchemaBucketPtr) list->items[i];
10035 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10036 (cur->origTargetNamespace == targetNamespace) &&
10037 ((imported && cur->imported) ||
10038 ((!imported) && (!cur->imported))))
10039 return(cur);
10040 }
10041 }
10042 return(NULL);
10043}
10044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010045static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010046xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10047 xmlSchemaPtr schema,
10048 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010049{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010050 int oldFlags;
10051 xmlDocPtr oldDoc;
10052 xmlNodePtr node;
10053 int ret, oldErrs;
10054 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10055
10056 /*
10057 * Save old values; reset the *main* schema.
10058 * URGENT TODO: This is not good; move the per-document information
10059 * to the parser.
10060 */
10061 oldFlags = schema->flags;
10062 oldDoc = schema->doc;
10063 if (schema->flags != 0)
10064 xmlSchemaClearSchemaDefaults(schema);
10065 schema->doc = bucket->doc;
10066 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
10067 pctxt->schema = schema;
10068 /*
10069 * Keep the current target namespace on the parser *not* on the
10070 * main schema.
10071 */
10072 pctxt->targetNamespace = bucket->targetNamespace;
10073 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010074
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010075 if ((bucket->targetNamespace != NULL) &&
10076 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010077 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010078 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010079 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010080 pctxt->isS4S = 1;
10081 }
10082 /* Mark it as parsed, even if parsing fails. */
10083 bucket->parsed++;
10084 /* Compile the schema doc. */
10085 node = xmlDocGetRootElement(bucket->doc);
10086 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10087 if (ret != 0)
10088 goto exit;
10089 /* An empty schema; just get out. */
10090 if (node->children == NULL)
10091 goto exit;
10092 oldErrs = pctxt->nberrors;
10093 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10094 if (ret != 0)
10095 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010096 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010097 * TODO: Not nice, but I'm not 100% sure we will get always an error
10098 * as a result of the obove functions; so better rely on pctxt->err
10099 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010100 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010101 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10102 ret = pctxt->err;
10103 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010104 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010105
10106exit:
10107 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10108 /* Restore schema values. */
10109 schema->doc = oldDoc;
10110 schema->flags = oldFlags;
10111 return(ret);
10112}
10113
10114static int
10115xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10116 xmlSchemaPtr schema,
10117 xmlSchemaBucketPtr bucket)
10118{
10119 xmlSchemaParserCtxtPtr newpctxt;
10120 int res = 0;
10121
10122 if (bucket == NULL)
10123 return(0);
10124 if (bucket->parsed) {
10125 PERROR_INT("xmlSchemaParseNewDoc",
10126 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010127 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010128 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010129 if (bucket->doc == NULL) {
10130 PERROR_INT("xmlSchemaParseNewDoc",
10131 "parsing a schema doc, but there's no doc");
10132 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010133 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010134 if (pctxt->constructor == NULL) {
10135 PERROR_INT("xmlSchemaParseNewDoc",
10136 "no constructor");
10137 return(-1);
10138 }
10139 /* Create and init the temporary parser context. */
10140 newpctxt = xmlSchemaNewParserCtxtUseDict(
10141 (const char *) bucket->schemaLocation, pctxt->dict);
10142 if (newpctxt == NULL)
10143 return(-1);
10144 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010145 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010146 * TODO: Can we avoid that the parser knows about the main schema?
10147 * It would be better if he knows about the current schema bucket
10148 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010149 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010150 newpctxt->schema = schema;
10151 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10152 pctxt->userData);
10153 newpctxt->counter = pctxt->counter;
10154
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010155
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010156 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10157
10158 /* Channel back errors and cleanup the temporary parser context. */
10159 if (res != 0)
10160 pctxt->err = res;
10161 pctxt->nberrors += newpctxt->nberrors;
10162 pctxt->counter = newpctxt->counter;
10163 newpctxt->constructor = NULL;
10164 /* Free the parser context. */
10165 xmlSchemaFreeParserCtxt(newpctxt);
10166 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010167}
William M. Brack2f2a6632004-08-20 23:09:47 +000010168
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010169static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010170xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10171 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010172{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010173 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010174
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010175 if (cur == NULL) {
10176 bucket->relations = rel;
10177 return;
10178 }
10179 while (cur->next != NULL)
10180 cur = cur->next;
10181 cur->next = rel;
10182}
10183
10184
10185static const xmlChar *
10186xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10187 xmlNodePtr ctxtNode)
10188{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010189 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010190 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010191 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010192 if (location != NULL) {
10193 if (ctxtNode == NULL)
10194 return(location);
10195 else {
10196 xmlChar *base, *URI;
10197 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010198
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010199 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10200 if (base == NULL) {
10201 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10202 } else {
10203 URI = xmlBuildURI(location, base);
10204 xmlFree(base);
10205 }
10206 if (URI != NULL) {
10207 ret = xmlDictLookup(dict, URI, -1);
10208 xmlFree(URI);
10209 return(ret);
10210 }
10211 }
10212 }
10213 return(NULL);
10214}
10215
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010216
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010217
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010218/**
10219 * xmlSchemaAddSchemaDoc:
10220 * @pctxt: a schema validation context
10221 * @schema: the schema being built
10222 * @node: a subtree containing XML Schema informations
10223 *
10224 * Parse an included (and to-be-redefined) XML schema document.
10225 *
10226 * Returns 0 on success, a positive error code on errors and
10227 * -1 in case of an internal or API error.
10228 */
10229
10230static int
10231xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10232 int type, /* import or include or redefine */
10233 const xmlChar *schemaLocation,
10234 xmlDocPtr schemaDoc,
10235 const char *schemaBuffer,
10236 int schemaBufferLen,
10237 xmlNodePtr invokingNode,
10238 const xmlChar *sourceTargetNamespace,
10239 const xmlChar *importNamespace,
10240 xmlSchemaBucketPtr *bucket)
10241{
10242 const xmlChar *targetNamespace = NULL;
10243 xmlSchemaSchemaRelationPtr relation = NULL;
10244 xmlDocPtr doc = NULL;
10245 int res = 0, err = 0, located = 0, preserveDoc = 0;
10246 xmlSchemaBucketPtr bkt = NULL;
10247
10248 if (bucket != NULL)
10249 *bucket = NULL;
10250
10251 switch (type) {
10252 case XML_SCHEMA_SCHEMA_IMPORT:
10253 case XML_SCHEMA_SCHEMA_MAIN:
10254 err = XML_SCHEMAP_SRC_IMPORT;
10255 break;
10256 case XML_SCHEMA_SCHEMA_INCLUDE:
10257 err = XML_SCHEMAP_SRC_INCLUDE;
10258 break;
10259 case XML_SCHEMA_SCHEMA_REDEFINE:
10260 err = XML_SCHEMAP_SRC_REDEFINE;
10261 break;
10262 }
10263
10264
10265 /* Special handling for the main schema:
10266 * skip the location and relation logic and just parse the doc.
10267 * We need just a bucket to be returned in this case.
10268 */
10269 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10270 goto doc_load;
10271
10272 /* Note that we expect the location to be an absulute URI. */
10273 if (schemaLocation != NULL) {
10274 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10275 if ((bkt != NULL) &&
10276 (pctxt->constructor->bucket == bkt)) {
10277 /* Report self-imports/inclusions/redefinitions. */
10278
10279 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10280 invokingNode, NULL,
10281 "The schema must not import/include/redefine itself",
10282 NULL, NULL);
10283 goto exit;
10284 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010285 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010286 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010287 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010288 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010289 relation = xmlSchemaSchemaRelationCreate();
10290 if (relation == NULL)
10291 return(-1);
10292 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10293 relation);
10294 relation->type = type;
10295
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010296 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010297 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010298 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010299 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010300 relation->importNamespace = importNamespace;
10301 if (schemaLocation == NULL) {
10302 /*
10303 * No location; this is just an import of the namespace.
10304 * Note that we don't assign a bucket to the relation
10305 * in this case.
10306 */
10307 goto exit;
10308 }
10309 targetNamespace = importNamespace;
10310 }
10311
10312 /* Did we already fetch the doc? */
10313 if (bkt != NULL) {
10314 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010315 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010316 /* We included/redefined and then try to import a schema. */
10317 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10318 invokingNode, NULL,
10319 "The schema document '%s' cannot be imported, since "
10320 "it was already included or redefined",
10321 schemaLocation, NULL);
10322 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010323 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010324 /* We imported and then try to include/redefine a schema. */
10325 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10326 invokingNode, NULL,
10327 "The schema document '%s' cannot be included or "
10328 "redefined, since it was already imported",
10329 schemaLocation, NULL);
10330 goto exit;
10331 }
10332 }
10333
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010334 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010335 /*
10336 * Given that the schemaLocation [attribute] is only a hint, it is open
10337 * to applications to ignore all but the first <import> for a given
10338 * namespace, regardless of the ·actual value· of schemaLocation, but
10339 * such a strategy risks missing useful information when new
10340 * schemaLocations are offered.
10341 *
10342 * We will use the first <import> that comes with a location.
10343 * Further <import>s *with* a location, will result in an error.
10344 * TODO: Better would be to just report a warning here, but
10345 * we'll try it this way until someone complains.
10346 *
10347 * Schema Document Location Strategy:
10348 * 3 Based on the namespace name, identify an existing schema document,
10349 * either as a resource which is an XML document or a <schema> element
10350 * information item, in some local schema repository;
10351 * 5 Attempt to resolve the namespace name to locate such a resource.
10352 *
10353 * NOTE: (3) and (5) are not supported.
10354 */
10355 if (bkt != NULL) {
10356 relation->bucket = bkt;
10357 goto exit;
10358 }
10359 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10360 importNamespace, 1);
10361
10362 if (bkt != NULL) {
10363 relation->bucket = bkt;
10364 if (bkt->schemaLocation == NULL) {
10365 /* First given location of the schema; load the doc. */
10366 bkt->schemaLocation = schemaLocation;
10367 } else {
10368 if (!xmlStrEqual(schemaLocation,
10369 bkt->schemaLocation)) {
10370 /*
10371 * Additional location given; just skip it.
10372 * URGENT TODO: We should report a warning here.
10373 * res = XML_SCHEMAP_SRC_IMPORT;
10374 */
10375 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10376 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10377 invokingNode, NULL,
10378 "Skipping import of schema located at '%s' for the "
10379 "namespace '%s', since this namespace was already "
10380 "imported with the schema located at '%s'",
10381 schemaLocation, importNamespace, bkt->schemaLocation);
10382 }
10383 goto exit;
10384 }
10385 }
10386 /*
10387 * No bucket + first location: load the doc and create a
10388 * bucket.
10389 */
10390 } else {
10391 /* <include> and <redefine> */
10392 if (bkt != NULL) {
10393
10394 if ((bkt->origTargetNamespace == NULL) &&
10395 (bkt->targetNamespace != sourceTargetNamespace)) {
10396 xmlSchemaBucketPtr chamel;
10397
10398 /*
10399 * Chameleon include/redefine: skip loading only if it was
10400 * aleady build for the targetNamespace of the including
10401 * schema.
10402 */
10403 /*
10404 * URGENT TODO: If the schema is a chameleon-include then copy
10405 * the components into the including schema and modify the
10406 * targetNamespace of those components, do nothing otherwise.
10407 * NOTE: This is currently worked-around by compiling the
10408 * chameleon for every destinct including targetNamespace; thus
10409 * not performant at the moment.
10410 * TODO: Check when the namespace in wildcards for chameleons
10411 * needs to be converted: before we built wildcard intersections
10412 * or after.
10413 * Answer: after!
10414 */
10415 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10416 schemaLocation, sourceTargetNamespace);
10417 if (chamel != NULL) {
10418 /* A fitting chameleon was already parsed; NOP. */
10419 relation->bucket = chamel;
10420 goto exit;
10421 }
10422 /*
10423 * We need to parse the chameleon again for a different
10424 * targetNamespace.
10425 * CHAMELEON TODO: Optimize this by only parsing the
10426 * chameleon once, and then copying the components to
10427 * the new targetNamespace.
10428 */
10429 bkt = NULL;
10430 } else {
10431 relation->bucket = bkt;
10432 goto exit;
10433 }
10434 }
10435 }
10436 if ((bkt != NULL) && (bkt->doc != NULL)) {
10437 PERROR_INT("xmlSchemaAddSchemaDoc",
10438 "trying to load a schema doc, but a doc is already "
10439 "assigned to the schema bucket");
10440 goto exit_failure;
10441 }
10442
10443doc_load:
10444 /*
10445 * Load the document.
10446 */
10447 if (schemaDoc != NULL) {
10448 doc = schemaDoc;
10449 /* Don' free this one, since it was provided by the caller. */
10450 preserveDoc = 1;
10451 /* TODO: Does the context or the doc hold the location? */
10452 if (schemaDoc->URL != NULL)
10453 schemaLocation = xmlDictLookup(pctxt->dict,
10454 schemaDoc->URL, -1);
10455
10456 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10457 xmlParserCtxtPtr parserCtxt;
10458
10459 parserCtxt = xmlNewParserCtxt();
10460 if (parserCtxt == NULL) {
10461 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10462 "allocating a parser context", NULL);
10463 goto exit_failure;
10464 }
10465 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10466 /*
10467 * TODO: Do we have to burden the schema parser dict with all
10468 * the content of the schema doc?
10469 */
10470 xmlDictFree(parserCtxt->dict);
10471 parserCtxt->dict = pctxt->dict;
10472 xmlDictReference(parserCtxt->dict);
10473 }
10474 if (schemaLocation != NULL) {
10475 /* Parse from file. */
10476 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10477 NULL, SCHEMAS_PARSE_OPTIONS);
10478 } else if (schemaBuffer != NULL) {
10479 /* Parse from memory buffer. */
10480 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10481 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10482 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10483 if (doc != NULL)
10484 doc->URL = schemaLocation;
10485 }
10486 /*
10487 * For <import>:
10488 * 2.1 The referent is (a fragment of) a resource which is an
10489 * XML document (see clause 1.1), which in turn corresponds to
10490 * a <schema> element information item in a well-formed information
10491 * set, which in turn corresponds to a valid schema.
10492 * TODO: (2.1) fragments of XML documents are not supported.
10493 *
10494 * 2.2 The referent is a <schema> element information item in
10495 * a well-formed information set, which in turn corresponds
10496 * to a valid schema.
10497 * TODO: (2.2) is not supported.
10498 */
10499 if (doc == NULL) {
10500 xmlErrorPtr lerr;
10501 lerr = xmlGetLastError();
10502 /*
10503 * Check if this a parser error, or if the document could
10504 * just not be located.
10505 * TODO: Try to find specific error codes to react only on
10506 * localisation failures.
10507 */
10508 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10509 /*
10510 * We assume a parser error here.
10511 */
10512 located = 1;
10513 /* TODO: Error code ?? */
10514 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10515 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10516 invokingNode, NULL,
10517 "Failed to parse the XML resource '%s'",
10518 schemaLocation, NULL);
10519 }
10520 }
10521 xmlFreeParserCtxt(parserCtxt);
10522 if ((doc == NULL) && located)
10523 goto exit_error;
10524 } else {
10525 xmlSchemaPErr(pctxt, NULL,
10526 XML_SCHEMAP_NOTHING_TO_PARSE,
10527 "No information for parsing was provided with the "
10528 "given schema parser context.\n",
10529 NULL, NULL);
10530 goto exit_failure;
10531 }
10532 /*
10533 * Preprocess the document.
10534 */
10535 if (doc != NULL) {
10536 xmlNodePtr docElem = NULL;
10537
10538 located = 1;
10539 docElem = xmlDocGetRootElement(doc);
10540 if (docElem == NULL) {
10541 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10542 invokingNode, NULL,
10543 "The document '%s' has no document element",
10544 schemaLocation, NULL);
10545 xmlFreeDoc(doc);
10546 doc = NULL;
10547 goto exit_error;
10548 }
10549 /*
10550 * Remove all the blank text nodes.
10551 */
10552 xmlSchemaCleanupDoc(pctxt, docElem);
10553 /*
10554 * Check the schema's top level element.
10555 */
10556 if (!IS_SCHEMA(docElem, "schema")) {
10557 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10558 invokingNode, NULL,
10559 "The XML document '%s' is not a schema document",
10560 schemaLocation, NULL);
10561 xmlFreeDoc(doc);
10562 doc = NULL;
10563 goto exit_error;
10564 }
10565 /*
10566 * Note that we don't apply a type check for the
10567 * targetNamespace value here.
10568 */
10569 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10570 "targetNamespace");
10571 }
10572
10573/* after_doc_loading: */
10574 if ((bkt == NULL) && located) {
10575 /* Only create a bucket if the schema was located. */
10576 bkt = xmlSchemaBucketCreate(pctxt, type,
10577 targetNamespace);
10578 if (bkt == NULL)
10579 goto exit_failure;
10580 }
10581 if (bkt != NULL) {
10582 bkt->schemaLocation = schemaLocation;
10583 bkt->located = located;
10584 if (doc != NULL) {
10585 bkt->doc = doc;
10586 bkt->targetNamespace = targetNamespace;
10587 bkt->origTargetNamespace = targetNamespace;
10588 if (preserveDoc)
10589 bkt->preserveDoc = 1;
10590 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010591 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010592 bkt->imported++;
10593 /*
10594 * Add it to the graph of schemas.
10595 */
10596 if (relation != NULL)
10597 relation->bucket = bkt;
10598 }
10599
10600exit:
10601 /*
10602 * Return the bucket explicitely; this is needed for the
10603 * main schema.
10604 */
10605 if (bucket != NULL)
10606 *bucket = bkt;
10607 return (0);
10608
10609exit_error:
10610 if ((doc != NULL) && (! preserveDoc)) {
10611 xmlFreeDoc(doc);
10612 if (bkt != NULL)
10613 bkt->doc = NULL;
10614 }
10615 return(pctxt->err);
10616
10617exit_failure:
10618 if ((doc != NULL) && (! preserveDoc)) {
10619 xmlFreeDoc(doc);
10620 if (bkt != NULL)
10621 bkt->doc = NULL;
10622 }
10623 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010624}
10625
William M. Brack2f2a6632004-08-20 23:09:47 +000010626/**
10627 * xmlSchemaParseImport:
10628 * @ctxt: a schema validation context
10629 * @schema: the schema being built
10630 * @node: a subtree containing XML Schema informations
10631 *
10632 * parse a XML schema Import definition
10633 * *WARNING* this interface is highly subject to change
10634 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010635 * Returns 0 in case of success, a positive error code if
10636 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010637 */
10638static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010639xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010640 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010641{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010642 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010643 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10644 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010645 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010646 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010647 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010648
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010649 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010650 return (-1);
10651
10652 /*
10653 * Check for illegal attributes.
10654 */
10655 attr = node->properties;
10656 while (attr != NULL) {
10657 if (attr->ns == NULL) {
10658 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10659 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10660 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010661 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010662 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010663 }
10664 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010665 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010666 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010667 }
10668 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010669 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010670 /*
10671 * Extract and validate attributes.
10672 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010673 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010674 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010675 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010676 xmlSchemaPSimpleTypeErr(pctxt,
10677 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010678 NULL, node,
10679 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010680 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010681 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010682 }
10683
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010684 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010685 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010686 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010687 xmlSchemaPSimpleTypeErr(pctxt,
10688 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010689 NULL, node,
10690 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010691 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010692 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010693 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010694 /*
10695 * And now for the children...
10696 */
10697 child = node->children;
10698 if (IS_SCHEMA(child, "annotation")) {
10699 /*
10700 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010701 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010702 */
10703 child = child->next;
10704 }
10705 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010706 xmlSchemaPContentErr(pctxt,
10707 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010708 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010709 "(annotation?)");
10710 }
10711 /*
10712 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010713 *
10714 * Note that it is important to use the original @targetNamespace
10715 * (or none at all), to rule out imports of schemas _with_ a
10716 * @targetNamespace if the importing schema is a chameleon schema
10717 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010718 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010719 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010720 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010721 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010722 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10723 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010724 * targetNamespace [attribute].
10725 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010726 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010727 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010728 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010729 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010730 "The value of the attribute 'namespace' must not match "
10731 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010732 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010733 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010734 }
10735 } else {
10736 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010737 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010738 * <schema> must have a targetNamespace [attribute].
10739 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010740 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010741 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010742 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010743 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010744 "The attribute 'namespace' must be existent if "
10745 "the importing schema has no target namespace",
10746 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010747 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010748 }
10749 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010750 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010751 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010752 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010753 if (schemaLocation != NULL)
10754 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10755 schemaLocation, node);
10756 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010757 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010758 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010759
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010760 if (ret != 0)
10761 return(ret);
10762
10763 /*
10764 * For <import>: "It is *not* an error for the application
10765 * schema reference strategy to fail."
10766 * So just don't parse if no schema document was found.
10767 * Note that we will get no bucket if the schema could not be
10768 * located or if there was no schemaLocation.
10769 */
10770 if ((bucket == NULL) && (schemaLocation != NULL)) {
10771 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10772 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10773 node, NULL,
10774 "Failed to locate a schema at location '%s'. "
10775 "Skipping the import", schemaLocation, NULL, NULL);
10776 }
10777
10778 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10779 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10780 }
10781
10782 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010783}
10784
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010785static int
10786xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10787 xmlSchemaPtr schema,
10788 xmlNodePtr node,
10789 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010790 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010791{
10792 xmlAttrPtr attr;
10793
10794 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10795 (schemaLocation == NULL))
10796 return (-1);
10797
10798 *schemaLocation = NULL;
10799 /*
10800 * Check for illegal attributes.
10801 * Applies for both <include> and <redefine>.
10802 */
10803 attr = node->properties;
10804 while (attr != NULL) {
10805 if (attr->ns == NULL) {
10806 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10807 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10808 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010809 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010810 }
10811 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10812 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010813 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010814 }
10815 attr = attr->next;
10816 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010817 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010818 /*
10819 * Preliminary step, extract the URI-Reference and make an URI
10820 * from the base.
10821 */
10822 /*
10823 * Attribute "schemaLocation" is mandatory.
10824 */
10825 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10826 if (attr != NULL) {
10827 xmlChar *base = NULL;
10828 xmlChar *uri = NULL;
10829
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010830 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010831 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10832 (const xmlChar **) schemaLocation) != 0)
10833 goto exit_error;
10834 base = xmlNodeGetBase(node->doc, node);
10835 if (base == NULL) {
10836 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10837 } else {
10838 uri = xmlBuildURI(*schemaLocation, base);
10839 xmlFree(base);
10840 }
10841 if (uri == NULL) {
10842 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10843 "could not build an URI from the schemaLocation")
10844 goto exit_failure;
10845 }
10846 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10847 xmlFree(uri);
10848 } else {
10849 xmlSchemaPMissingAttrErr(pctxt,
10850 XML_SCHEMAP_S4S_ATTR_MISSING,
10851 NULL, node, "schemaLocation", NULL);
10852 goto exit_error;
10853 }
10854 /*
10855 * Report self-inclusion and self-redefinition.
10856 */
10857 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010858 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010859 xmlSchemaPCustomErr(pctxt,
10860 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010861 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010862 "The schema document '%s' cannot redefine itself.",
10863 *schemaLocation);
10864 } else {
10865 xmlSchemaPCustomErr(pctxt,
10866 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010867 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010868 "The schema document '%s' cannot include itself.",
10869 *schemaLocation);
10870 }
10871 goto exit_error;
10872 }
10873
10874 return(0);
10875exit_error:
10876 return(pctxt->err);
10877exit_failure:
10878 return(-1);
10879}
10880
10881static int
10882xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10883 xmlSchemaPtr schema,
10884 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010885 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010886{
10887 xmlNodePtr child = NULL;
10888 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010889 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010890 int isChameleon = 0, wasChameleon = 0;
10891 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010892
10893 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10894 return (-1);
10895
10896 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010897 * Parse attributes. Note that the returned schemaLocation will
10898 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010899 */
10900 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010901 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010902 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010903 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010904 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010905 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010906 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010907 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10908 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010909 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010910 return(res);
10911 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010912 * If we get no schema bucket back, then this means that the schema
10913 * document could not be located or was broken XML or was not
10914 * a schema document.
10915 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010916 if ((bucket == NULL) || (bucket->doc == NULL)) {
10917 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10918 /*
10919 * WARNING for <include>:
10920 * We will raise an error if the schema cannot be located
10921 * for inclusions, since the that was the feedback from the
10922 * schema people. I.e. the following spec piece will *not* be
10923 * satisfied:
10924 * SPEC src-include: "It is not an error for the ·actual value· of the
10925 * schemaLocation [attribute] to fail to resolve it all, in which
10926 * case no corresponding inclusion is performed.
10927 * So do we need a warning report here?"
10928 */
10929 res = XML_SCHEMAP_SRC_INCLUDE;
10930 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10931 node, NULL,
10932 "Failed to load the document '%s' for inclusion",
10933 schemaLocation, NULL);
10934 } else {
10935 /*
10936 * NOTE: This was changed to raise an error even if no redefinitions
10937 * are specified.
10938 *
10939 * SPEC src-redefine (1)
10940 * "If there are any element information items among the [children]
10941 * other than <annotation> then the ·actual value· of the
10942 * schemaLocation [attribute] must successfully resolve."
10943 * TODO: Ask the WG if a the location has always to resolve
10944 * here as well!
10945 */
10946 res = XML_SCHEMAP_SRC_REDEFINE;
10947 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10948 node, NULL,
10949 "Failed to load the document '%s' for redefinition",
10950 schemaLocation, NULL);
10951 }
10952 } else {
10953 /*
10954 * Check targetNamespace sanity before parsing the new schema.
10955 * TODO: Note that we won't check further content if the
10956 * targetNamespace was bad.
10957 */
10958 if (bucket->origTargetNamespace != NULL) {
10959 /*
10960 * SPEC src-include (2.1)
10961 * "SII has a targetNamespace [attribute], and its ·actual
10962 * value· is identical to the ·actual value· of the targetNamespace
10963 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10964 */
10965 if (pctxt->targetNamespace == NULL) {
10966 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10967 XML_SCHEMAP_SRC_INCLUDE,
10968 node, NULL,
10969 "The target namespace of the included/redefined schema "
10970 "'%s' has to be absent, since the including/redefining "
10971 "schema has no target namespace",
10972 schemaLocation, NULL);
10973 goto exit_error;
10974 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10975 pctxt->targetNamespace)) {
10976 /* TODO: Change error function. */
10977 xmlSchemaPCustomErrExt(pctxt,
10978 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010979 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010980 "The target namespace '%s' of the included/redefined "
10981 "schema '%s' differs from '%s' of the "
10982 "including/redefining schema",
10983 bucket->origTargetNamespace, schemaLocation,
10984 pctxt->targetNamespace);
10985 goto exit_error;
10986 }
10987 } else if (pctxt->targetNamespace != NULL) {
10988 /*
10989 * Chameleons: the original target namespace will
10990 * differ from the resulting namespace.
10991 */
10992 isChameleon = 1;
10993 if (bucket->parsed &&
10994 (bucket->targetNamespace != pctxt->targetNamespace)) {
10995 /*
10996 * This is a sanity check, I dunno yet if this can happen.
10997 */
10998 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10999 "trying to use an already parsed schema for a "
11000 "different targetNamespace");
11001 return(-1);
11002 }
11003 bucket->targetNamespace = pctxt->targetNamespace;
11004 }
11005 }
11006 /*
11007 * Parse the schema.
11008 */
11009 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11010 if (isChameleon) {
11011 /* TODO: Get rid of this flag on the schema itself. */
11012 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11013 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11014 } else
11015 wasChameleon = 1;
11016 }
11017 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11018 /* Restore chameleon flag. */
11019 if (isChameleon && (!wasChameleon))
11020 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11021 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011022 /*
11023 * And now for the children...
11024 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011025 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011026 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011027 /*
11028 * Parse (simpleType | complexType | group | attributeGroup))*
11029 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011030 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011031 /*
11032 * How to proceed if the redefined schema was not located?
11033 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011034 pctxt->isRedefine = 1;
11035 while (IS_SCHEMA(child, "annotation") ||
11036 IS_SCHEMA(child, "simpleType") ||
11037 IS_SCHEMA(child, "complexType") ||
11038 IS_SCHEMA(child, "group") ||
11039 IS_SCHEMA(child, "attributeGroup")) {
11040 if (IS_SCHEMA(child, "annotation")) {
11041 /*
11042 * TODO: discard or not?
11043 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011044 } else if (IS_SCHEMA(child, "simpleType")) {
11045 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11046 } else if (IS_SCHEMA(child, "complexType")) {
11047 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011048 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011049 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011050 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011051 xmlSchemaParseModelGroupDefinition(pctxt,
11052 schema, child);
11053 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011054 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011055 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11056 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011057 }
11058 child = child->next;
11059 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011060 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011061 pctxt->isRedefine = 0;
11062 } else {
11063 if (IS_SCHEMA(child, "annotation")) {
11064 /*
11065 * TODO: discard or not?
11066 */
11067 child = child->next;
11068 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011069 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011070 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011071 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011072 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11073 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011074 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011075 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11076 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011077 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011078 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011079 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011080 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011081 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011082 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011083
11084exit_error:
11085 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011086}
11087
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011088static int
11089xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11090 xmlNodePtr node)
11091{
11092 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011093#ifndef ENABLE_REDEFINE
11094 TODO
11095 return(0);
11096#endif
11097 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11098 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011099 if (res != 0)
11100 return(res);
11101 return(0);
11102}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011103
11104static int
11105xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11106 xmlNodePtr node)
11107{
11108 int res;
11109
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011110 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11111 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011112 if (res != 0)
11113 return(res);
11114 return(0);
11115}
11116
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011117/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011118 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011119 * @ctxt: a schema validation context
11120 * @schema: the schema being built
11121 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 * @type: the "compositor" type
11123 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011124 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011125 * parse a XML schema Sequence definition.
11126 * Applies parts of:
11127 * Schema Representation Constraint:
11128 * Redefinition Constraints and Semantics (src-redefine)
11129 * (6.1), (6.1.1), (6.1.2)
11130 *
11131 * Schema Component Constraint:
11132 * All Group Limited (cos-all-limited) (2)
11133 * TODO: Actually this should go to component-level checks,
11134 * but is done here due to performance. Move it to an other layer
11135 * is schema construction via an API is implemented.
11136 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011137 * *WARNING* this interface is highly subject to change
11138 *
William M. Bracke7091952004-05-11 15:09:58 +000011139 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011140 * 1 in case of success.
11141 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011142static xmlSchemaTreeItemPtr
11143xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11144 xmlNodePtr node, xmlSchemaTypeType type,
11145 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011146{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147 xmlSchemaModelGroupPtr item;
11148 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011149 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011150 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011151 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011152
11153 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011154 return (NULL);
11155 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011157 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011158 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 if (item == NULL)
11160 return (NULL);
11161
11162 if (withParticle) {
11163 if (type == XML_SCHEMA_TYPE_ALL) {
11164 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011165 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011166 } else {
11167 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011168 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11169 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11170 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011171 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011172 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11173 /*
11174 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011175 */
11176 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11177 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011178 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 particle->children = (xmlSchemaTreeItemPtr) item;
11180 /*
11181 * Check for illegal attributes.
11182 */
11183 attr = node->properties;
11184 while (attr != NULL) {
11185 if (attr->ns == NULL) {
11186 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11187 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11188 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011189 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 }
11192 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011193 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011194 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011195 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011197 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011198 } else {
11199 /*
11200 * Check for illegal attributes.
11201 */
11202 attr = node->properties;
11203 while (attr != NULL) {
11204 if (attr->ns == NULL) {
11205 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011206 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011207 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011208 }
11209 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011210 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011211 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 }
11213 attr = attr->next;
11214 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011215 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011216
William M. Brack2f2a6632004-08-20 23:09:47 +000011217 /*
11218 * Extract and validate attributes.
11219 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011220 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011221 /*
11222 * And now for the children...
11223 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011224 child = node->children;
11225 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011226 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011228 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 if (type == XML_SCHEMA_TYPE_ALL) {
11230 xmlSchemaParticlePtr part, last = NULL;
11231
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011232 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011234 schema, child, &isElemRef, 0);
11235 /*
11236 * SPEC cos-all-limited (2)
11237 * "The {max occurs} of all the particles in the {particles}
11238 * of the ('all') group must be 0 or 1.
11239 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011240 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011241 if (isElemRef)
11242 hasRefs++;
11243 if (part->minOccurs > 1) {
11244 xmlSchemaPCustomErr(ctxt,
11245 XML_SCHEMAP_COS_ALL_LIMITED,
11246 NULL, child,
11247 "Invalid value for minOccurs (must be 0 or 1)",
11248 NULL);
11249 /* Reset to 1. */
11250 part->minOccurs = 1;
11251 }
11252 if (part->maxOccurs > 1) {
11253 xmlSchemaPCustomErr(ctxt,
11254 XML_SCHEMAP_COS_ALL_LIMITED,
11255 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011256 "Invalid value for maxOccurs (must be 0 or 1)",
11257 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011258 /* Reset to 1. */
11259 part->maxOccurs = 1;
11260 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011261 if (last == NULL)
11262 item->children = (xmlSchemaTreeItemPtr) part;
11263 else
11264 last->next = (xmlSchemaTreeItemPtr) part;
11265 last = part;
11266 }
11267 child = child->next;
11268 }
11269 if (child != NULL) {
11270 xmlSchemaPContentErr(ctxt,
11271 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011272 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 "(annotation?, (annotation?, element*)");
11274 }
11275 } else {
11276 /* choice + sequence */
11277 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11278
11279 while ((IS_SCHEMA(child, "element")) ||
11280 (IS_SCHEMA(child, "group")) ||
11281 (IS_SCHEMA(child, "any")) ||
11282 (IS_SCHEMA(child, "choice")) ||
11283 (IS_SCHEMA(child, "sequence"))) {
11284
11285 if (IS_SCHEMA(child, "element")) {
11286 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011287 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11288 if (part && isElemRef)
11289 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011291 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011293 if (part != NULL)
11294 hasRefs++;
11295 /*
11296 * Handle redefinitions.
11297 */
11298 if (ctxt->isRedefine && ctxt->redef &&
11299 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11300 part && part->children)
11301 {
11302 if ((xmlSchemaGetQNameRefName(part->children) ==
11303 ctxt->redef->refName) &&
11304 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11305 ctxt->redef->refTargetNs))
11306 {
11307 /*
11308 * SPEC src-redefine:
11309 * (6.1) "If it has a <group> among its contents at
11310 * some level the ·actual value· of whose ref
11311 * [attribute] is the same as the ·actual value· of
11312 * its own name attribute plus target namespace, then
11313 * all of the following must be true:"
11314 * (6.1.1) "It must have exactly one such group."
11315 */
11316 if (ctxt->redefCounter != 0) {
11317 xmlChar *str = NULL;
11318
11319 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11320 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11321 "The redefining model group definition "
11322 "'%s' must not contain more than one "
11323 "reference to the redefined definition",
11324 xmlSchemaFormatQName(&str,
11325 ctxt->redef->refTargetNs,
11326 ctxt->redef->refName),
11327 NULL);
11328 FREE_AND_NULL(str)
11329 part = NULL;
11330 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11331 ((WXS_PARTICLE(part))->maxOccurs != 1))
11332 {
11333 xmlChar *str = NULL;
11334 /*
11335 * SPEC src-redefine:
11336 * (6.1.2) "The ·actual value· of both that
11337 * group's minOccurs and maxOccurs [attribute]
11338 * must be 1 (or ·absent·).
11339 */
11340 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11341 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11342 "The redefining model group definition "
11343 "'%s' must not contain a reference to the "
11344 "redefined definition with a "
11345 "maxOccurs/minOccurs other than 1",
11346 xmlSchemaFormatQName(&str,
11347 ctxt->redef->refTargetNs,
11348 ctxt->redef->refName),
11349 NULL);
11350 FREE_AND_NULL(str)
11351 part = NULL;
11352 }
11353 ctxt->redef->reference = WXS_BASIC_CAST part;
11354 ctxt->redefCounter++;
11355 }
11356 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011357 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011358 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011359 xmlSchemaParseAny(ctxt, schema, child);
11360 } else if (IS_SCHEMA(child, "choice")) {
11361 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11362 XML_SCHEMA_TYPE_CHOICE, 1);
11363 } else if (IS_SCHEMA(child, "sequence")) {
11364 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11365 XML_SCHEMA_TYPE_SEQUENCE, 1);
11366 }
11367 if (part != NULL) {
11368 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011369 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011370 else
11371 last->next = part;
11372 last = part;
11373 }
11374 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011376 if (child != NULL) {
11377 xmlSchemaPContentErr(ctxt,
11378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011379 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011380 "(annotation?, (element | group | choice | sequence | any)*)");
11381 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011382 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011383 if ((max == 0) && (min == 0))
11384 return (NULL);
11385 if (hasRefs) {
11386 /*
11387 * We need to resolve references.
11388 */
11389 WXS_ADD_PENDING(ctxt, item);
11390 }
11391 if (withParticle)
11392 return ((xmlSchemaTreeItemPtr) particle);
11393 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011395}
11396
11397/**
11398 * xmlSchemaParseRestriction:
11399 * @ctxt: a schema validation context
11400 * @schema: the schema being built
11401 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011402 *
11403 * parse a XML schema Restriction definition
11404 * *WARNING* this interface is highly subject to change
11405 *
11406 * Returns the type definition or NULL in case of error
11407 */
11408static xmlSchemaTypePtr
11409xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011411{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011412 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011413 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011414 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011415
11416 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11417 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011418 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011419 type = ctxt->ctxtType;
11420 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011421
11422 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011423 * Check for illegal attributes.
11424 */
11425 attr = node->properties;
11426 while (attr != NULL) {
11427 if (attr->ns == NULL) {
11428 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11429 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011430 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011432 }
11433 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011434 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011435 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011436 }
11437 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011439 /*
11440 * Extract and validate attributes.
11441 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011442 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011443 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011444 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011445 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011446 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011447 * Extract the base type. The "base" attribute is mandatory if inside
11448 * a complex type or if redefining.
11449 *
11450 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011451 * among its [children]), the simple type definition which is
11452 * the {content type} of the type definition ·resolved· to by
11453 * the ·actual value· of the base [attribute]"
11454 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011455 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011456 &(type->baseNs), &(type->base)) == 0)
11457 {
11458 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11459 xmlSchemaPMissingAttrErr(ctxt,
11460 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011461 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011462 } else if ((ctxt->isRedefine) &&
11463 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11464 {
11465 if (type->base == NULL) {
11466 xmlSchemaPMissingAttrErr(ctxt,
11467 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011468 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011469 } else if ((! xmlStrEqual(type->base, type->name)) ||
11470 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11471 {
11472 xmlChar *str1 = NULL, *str2 = NULL;
11473 /*
11474 * REDEFINE: SPEC src-redefine (5)
11475 * "Within the [children], each <simpleType> must have a
11476 * <restriction> among its [children] ... the ·actual value· of
11477 * whose base [attribute] must be the same as the ·actual value·
11478 * of its own name attribute plus target namespace;"
11479 */
11480 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011481 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011482 "value '%s' of the 'base' attribute does not match the "
11483 "type's designation '%s'",
11484 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11485 xmlSchemaFormatQName(&str1, type->targetNamespace,
11486 type->name), NULL);
11487 FREE_AND_NULL(str1);
11488 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011489 /* Avoid confusion and erase the values. */
11490 type->base = NULL;
11491 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011492 }
11493 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011494 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011495 /*
11496 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011497 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011498 child = node->children;
11499 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011500 /*
11501 * Add the annotation to the simple type ancestor.
11502 */
11503 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011504 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011505 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011506 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011507 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11508 /*
11509 * Corresponds to <simpleType><restriction><simpleType>.
11510 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011511 if (IS_SCHEMA(child, "simpleType")) {
11512 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011514 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011515 * Either the base [attribute] or the simpleType [child] of the
11516 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011520 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011521 "The attribute 'base' and the <simpleType> child are "
11522 "mutually exclusive", NULL);
11523 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011524 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011525 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011526 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011527 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011531 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011532 "Either the attribute 'base' or a <simpleType> child "
11533 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011534 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11536 /*
11537 * Corresponds to <complexType><complexContent><restriction>...
11538 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011539 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 * Model groups <all>, <choice> and <sequence>.
11541 */
11542 if (IS_SCHEMA(child, "all")) {
11543 type->subtypes = (xmlSchemaTypePtr)
11544 xmlSchemaParseModelGroup(ctxt, schema, child,
11545 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011546 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011547 } else if (IS_SCHEMA(child, "choice")) {
11548 type->subtypes = (xmlSchemaTypePtr)
11549 xmlSchemaParseModelGroup(ctxt,
11550 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11551 child = child->next;
11552 } else if (IS_SCHEMA(child, "sequence")) {
11553 type->subtypes = (xmlSchemaTypePtr)
11554 xmlSchemaParseModelGroup(ctxt, schema, child,
11555 XML_SCHEMA_TYPE_SEQUENCE, 1);
11556 child = child->next;
11557 /*
11558 * Model group reference <group>.
11559 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011560 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011561 type->subtypes = (xmlSchemaTypePtr)
11562 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011563 /*
11564 * Note that the reference will be resolved in
11565 * xmlSchemaResolveTypeReferences();
11566 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 child = child->next;
11568 }
11569 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011570 /*
11571 * Corresponds to <complexType><simpleContent><restriction>...
11572 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573 * "1.1 the simple type definition corresponding to the <simpleType>
11574 * among the [children] of <restriction> if there is one;"
11575 */
11576 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011577 /*
11578 * We will store the to-be-restricted simple type in
11579 * type->contentTypeDef *temporarily*.
11580 */
11581 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011582 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011583 if ( type->contentTypeDef == NULL)
11584 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011585 child = child->next;
11586 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011587 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011588
11589 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011590 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011591 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 /*
11593 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011595 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011596
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011599 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011600 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011601 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11602 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011603 * *Single Facet Value*
11604 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011605 while ((IS_SCHEMA(child, "minInclusive")) ||
11606 (IS_SCHEMA(child, "minExclusive")) ||
11607 (IS_SCHEMA(child, "maxInclusive")) ||
11608 (IS_SCHEMA(child, "maxExclusive")) ||
11609 (IS_SCHEMA(child, "totalDigits")) ||
11610 (IS_SCHEMA(child, "fractionDigits")) ||
11611 (IS_SCHEMA(child, "pattern")) ||
11612 (IS_SCHEMA(child, "enumeration")) ||
11613 (IS_SCHEMA(child, "whiteSpace")) ||
11614 (IS_SCHEMA(child, "length")) ||
11615 (IS_SCHEMA(child, "maxLength")) ||
11616 (IS_SCHEMA(child, "minLength"))) {
11617 facet = xmlSchemaParseFacet(ctxt, schema, child);
11618 if (facet != NULL) {
11619 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011620 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011621 else
11622 lastfacet->next = facet;
11623 lastfacet = facet;
11624 lastfacet->next = NULL;
11625 }
11626 child = child->next;
11627 }
11628 /*
11629 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011630 */
11631 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011632 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11633
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011634 facet = type->facets;
11635 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011636 facetLink = (xmlSchemaFacetLinkPtr)
11637 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011639 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011640 xmlFree(facetLink);
11641 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011642 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 facetLink->facet = facet;
11644 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011645 if (lastFacetLink == NULL)
11646 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011647 else
11648 lastFacetLink->next = facetLink;
11649 lastFacetLink = facetLink;
11650 facet = facet->next;
11651 } while (facet != NULL);
11652 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011653 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011654 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11655 /*
11656 * Attribute uses/declarations.
11657 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011658 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11659 (xmlSchemaItemListPtr *) &(type->attrUses),
11660 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11661 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011662 /*
11663 * Attribute wildcard.
11664 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011665 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011666 type->attributeWildcard =
11667 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011668 child = child->next;
11669 }
11670 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011671 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011672 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11673 xmlSchemaPContentErr(ctxt,
11674 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011675 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011676 "annotation?, (group | all | choice | sequence)?, "
11677 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011678 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011679 xmlSchemaPContentErr(ctxt,
11680 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011681 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011682 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11683 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11684 "length | minLength | maxLength | enumeration | whiteSpace | "
11685 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11686 } else {
11687 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011688 xmlSchemaPContentErr(ctxt,
11689 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011690 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011691 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11692 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11693 "length | minLength | maxLength | enumeration | whiteSpace | "
11694 "pattern)*))");
11695 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011696 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011697 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011698}
11699
11700/**
11701 * xmlSchemaParseExtension:
11702 * @ctxt: a schema validation context
11703 * @schema: the schema being built
11704 * @node: a subtree containing XML Schema informations
11705 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011706 * Parses an <extension>, which is found inside a
11707 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011708 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011709 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011710 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011711 */
11712static xmlSchemaTypePtr
11713xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011714 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011715{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011716 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011717 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011718 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011719
11720 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11721 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011722 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011723 type = ctxt->ctxtType;
11724 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011725
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011726 /*
11727 * Check for illegal attributes.
11728 */
11729 attr = node->properties;
11730 while (attr != NULL) {
11731 if (attr->ns == NULL) {
11732 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11733 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011734 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011736 }
11737 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011738 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011739 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011740 }
11741 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011743
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011744 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011745
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011746 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011747 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011748 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011749 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11750 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011752 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011753 XML_SCHEMAP_S4S_ATTR_MISSING,
11754 NULL, node, "base", NULL);
11755 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011756 /*
11757 * And now for the children...
11758 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011759 child = node->children;
11760 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011761 /*
11762 * Add the annotation to the type ancestor.
11763 */
11764 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011765 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011766 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011767 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011768 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11769 /*
11770 * Corresponds to <complexType><complexContent><extension>... and:
11771 *
11772 * Model groups <all>, <choice>, <sequence> and <group>.
11773 */
11774 if (IS_SCHEMA(child, "all")) {
11775 type->subtypes = (xmlSchemaTypePtr)
11776 xmlSchemaParseModelGroup(ctxt, schema,
11777 child, XML_SCHEMA_TYPE_ALL, 1);
11778 child = child->next;
11779 } else if (IS_SCHEMA(child, "choice")) {
11780 type->subtypes = (xmlSchemaTypePtr)
11781 xmlSchemaParseModelGroup(ctxt, schema,
11782 child, XML_SCHEMA_TYPE_CHOICE, 1);
11783 child = child->next;
11784 } else if (IS_SCHEMA(child, "sequence")) {
11785 type->subtypes = (xmlSchemaTypePtr)
11786 xmlSchemaParseModelGroup(ctxt, schema,
11787 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11788 child = child->next;
11789 } else if (IS_SCHEMA(child, "group")) {
11790 type->subtypes = (xmlSchemaTypePtr)
11791 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011792 /*
11793 * Note that the reference will be resolved in
11794 * xmlSchemaResolveTypeReferences();
11795 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011796 child = child->next;
11797 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011798 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011799 if (child != NULL) {
11800 /*
11801 * Attribute uses/declarations.
11802 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011803 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11804 (xmlSchemaItemListPtr *) &(type->attrUses),
11805 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11806 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011807 /*
11808 * Attribute wildcard.
11809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810 if (IS_SCHEMA(child, "anyAttribute")) {
11811 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011812 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11813 child = child->next;
11814 }
11815 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011816 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011817 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011819 xmlSchemaPContentErr(ctxt,
11820 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011821 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011822 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011823 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011824 } else {
11825 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011826 xmlSchemaPContentErr(ctxt,
11827 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011828 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011829 "(annotation?, ((attribute | attributeGroup)*, "
11830 "anyAttribute?))");
11831 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011832 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011833 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011834}
11835
11836/**
11837 * xmlSchemaParseSimpleContent:
11838 * @ctxt: a schema validation context
11839 * @schema: the schema being built
11840 * @node: a subtree containing XML Schema informations
11841 *
11842 * parse a XML schema SimpleContent definition
11843 * *WARNING* this interface is highly subject to change
11844 *
11845 * Returns the type definition or NULL in case of error
11846 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011847static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011848xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011849 xmlSchemaPtr schema, xmlNodePtr node,
11850 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011851{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011852 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011853 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011854 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011855
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011856 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11857 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011858 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011859 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011860 /* Not a component, don't create it. */
11861 type = ctxt->ctxtType;
11862 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11863 /*
11864 * Check for illegal attributes.
11865 */
11866 attr = node->properties;
11867 while (attr != NULL) {
11868 if (attr->ns == NULL) {
11869 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011870 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011871 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011872 }
11873 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011874 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011875 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011876 }
11877 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011878 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011879
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011880 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011881
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011882 /*
11883 * And now for the children...
11884 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011885 child = node->children;
11886 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011887 /*
11888 * Add the annotation to the complex type ancestor.
11889 */
11890 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011891 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011892 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011893 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011894 if (child == NULL) {
11895 xmlSchemaPContentErr(ctxt,
11896 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011897 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011898 "(annotation?, (restriction | extension))");
11899 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011900 if (child == NULL) {
11901 xmlSchemaPContentErr(ctxt,
11902 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011903 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011904 "(annotation?, (restriction | extension))");
11905 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011906 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011907 xmlSchemaParseRestriction(ctxt, schema, child,
11908 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011909 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011910 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011911 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011912 xmlSchemaParseExtension(ctxt, schema, child,
11913 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011914 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011915 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011916 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011917 if (child != NULL) {
11918 xmlSchemaPContentErr(ctxt,
11919 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011920 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011921 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011922 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011923 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011924}
11925
11926/**
11927 * xmlSchemaParseComplexContent:
11928 * @ctxt: a schema validation context
11929 * @schema: the schema being built
11930 * @node: a subtree containing XML Schema informations
11931 *
11932 * parse a XML schema ComplexContent definition
11933 * *WARNING* this interface is highly subject to change
11934 *
11935 * Returns the type definition or NULL in case of error
11936 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011937static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011938xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011939 xmlSchemaPtr schema, xmlNodePtr node,
11940 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011941{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011942 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011943 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011944 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011945
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011946 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11947 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011948 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011949 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011950 /* Not a component, don't create it. */
11951 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011952 /*
11953 * Check for illegal attributes.
11954 */
11955 attr = node->properties;
11956 while (attr != NULL) {
11957 if (attr->ns == NULL) {
11958 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011959 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011960 {
11961 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011963 }
11964 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11965 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011966 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011967 }
11968 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011970
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011971 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011972
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011973 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011974 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011975 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011976 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011977 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11978 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011979 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011980 child = node->children;
11981 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011982 /*
11983 * Add the annotation to the complex type ancestor.
11984 */
11985 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011986 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011987 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011988 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011989 if (child == NULL) {
11990 xmlSchemaPContentErr(ctxt,
11991 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011992 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011993 NULL, "(annotation?, (restriction | extension))");
11994 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011995 if (child == NULL) {
11996 xmlSchemaPContentErr(ctxt,
11997 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011998 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011999 NULL, "(annotation?, (restriction | extension))");
12000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012001 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012002 xmlSchemaParseRestriction(ctxt, schema, child,
12003 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012004 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012005 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012006 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012007 xmlSchemaParseExtension(ctxt, schema, child,
12008 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012009 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012010 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012011 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012012 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012013 xmlSchemaPContentErr(ctxt,
12014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012015 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012016 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012017 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012018 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012019}
12020
12021/**
12022 * xmlSchemaParseComplexType:
12023 * @ctxt: a schema validation context
12024 * @schema: the schema being built
12025 * @node: a subtree containing XML Schema informations
12026 *
12027 * parse a XML schema Complex Type definition
12028 * *WARNING* this interface is highly subject to change
12029 *
12030 * Returns the type definition or NULL in case of error
12031 */
12032static xmlSchemaTypePtr
12033xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012034 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012035{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012036 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012037 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012038 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012039 xmlAttrPtr attr;
12040 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012041#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012042 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012043#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012044 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012045
Daniel Veillard4255d502002-04-16 15:50:10 +000012046
12047 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12048 return (NULL);
12049
Daniel Veillard01fa6152004-06-29 17:04:39 +000012050 ctxtType = ctxt->ctxtType;
12051
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012052 if (topLevel) {
12053 attr = xmlSchemaGetPropNode(node, "name");
12054 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012055 xmlSchemaPMissingAttrErr(ctxt,
12056 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012057 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012058 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012059 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12060 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012061 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012064 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012065 /*
12066 * Parse as local complex type definition.
12067 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012068#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012069 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012070 type = xmlSchemaAddType(ctxt, schema,
12071 XML_SCHEMA_TYPE_COMPLEX,
12072 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012073 ctxt->targetNamespace, node, 0);
12074#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012075 type = xmlSchemaAddType(ctxt, schema,
12076 XML_SCHEMA_TYPE_COMPLEX,
12077 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012078#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012079 if (type == NULL)
12080 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012081 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012082 type->node = node;
12083 type->type = XML_SCHEMA_TYPE_COMPLEX;
12084 /*
12085 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012086 */
12087 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012088 /*
12089 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012090 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012091 type = xmlSchemaAddType(ctxt, schema,
12092 XML_SCHEMA_TYPE_COMPLEX,
12093 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012094 if (type == NULL)
12095 return (NULL);
12096 type->node = node;
12097 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012098 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012099 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012100 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012101 /*
12102 * Handle attributes.
12103 */
12104 attr = node->properties;
12105 while (attr != NULL) {
12106 if (attr->ns == NULL) {
12107 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12108 /*
12109 * Attribute "id".
12110 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012111 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012112 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12113 /*
12114 * Attribute "mixed".
12115 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012116 if (xmlSchemaPGetBoolNodeValue(ctxt,
12117 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012118 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12119 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012120 /*
12121 * Attributes of global complex type definitions.
12122 */
12123 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12124 /* Pass. */
12125 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12126 /*
12127 * Attribute "abstract".
12128 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012129 if (xmlSchemaPGetBoolNodeValue(ctxt,
12130 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012131 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12132 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12133 /*
12134 * Attribute "final".
12135 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012136 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012137 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012138 if (xmlSchemaPValAttrBlockFinal(attrValue,
12139 &(type->flags),
12140 -1,
12141 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12142 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12143 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012144 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012145 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012146 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012147 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012148 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012149 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012150 } else
12151 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012152 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12153 /*
12154 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155 */
12156 attrValue = xmlSchemaGetNodeContent(ctxt,
12157 (xmlNodePtr) attr);
12158 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012159 -1,
12160 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012162 -1, -1, -1) != 0) {
12163 xmlSchemaPSimpleTypeErr(ctxt,
12164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012165 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012167 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012168 } else
12169 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012170 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012171 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012173 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012174 } else {
12175 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012176 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012177 }
12178 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012179 xmlSchemaPIllegalAttrErr(ctxt,
12180 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012181 }
12182 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012183 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012184 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012185 /*
12186 * Apply default "block" values.
12187 */
12188 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12189 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12190 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12191 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12192 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012193 if (! final) {
12194 /*
12195 * Apply default "block" values.
12196 */
12197 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12198 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12199 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12200 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12201 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012202 /*
12203 * And now for the children...
12204 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012205 child = node->children;
12206 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012207 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012208 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012209 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012210 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012211 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012213 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012214 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012215 * Specifying mixed='true' when the <simpleContent>
12216 * alternative is chosen has no effect
12217 */
William M. Bracke7091952004-05-11 15:09:58 +000012218 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12219 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012220 xmlSchemaParseSimpleContent(ctxt, schema, child,
12221 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012222 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012223 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012224 /*
12225 * <complexType><complexContent>...
12226 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012227 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012228 xmlSchemaParseComplexContent(ctxt, schema, child,
12229 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012231 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012232 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012233 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12234 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012235 * SPEC
12236 * "...the third alternative (neither <simpleContent> nor
12237 * <complexContent>) is chosen. This case is understood as shorthand
12238 * for complex content restricting the ·ur-type definition·, and the
12239 * details of the mappings should be modified as necessary.
12240 */
12241 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12242 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012243 /*
12244 * Parse model groups.
12245 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012246 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012247 type->subtypes = (xmlSchemaTypePtr)
12248 xmlSchemaParseModelGroup(ctxt, schema, child,
12249 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012250 child = child->next;
12251 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012252 type->subtypes = (xmlSchemaTypePtr)
12253 xmlSchemaParseModelGroup(ctxt, schema, child,
12254 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012255 child = child->next;
12256 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012257 type->subtypes = (xmlSchemaTypePtr)
12258 xmlSchemaParseModelGroup(ctxt, schema, child,
12259 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012260 child = child->next;
12261 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012262 type->subtypes = (xmlSchemaTypePtr)
12263 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012264 /*
12265 * Note that the reference will be resolved in
12266 * xmlSchemaResolveTypeReferences();
12267 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012268 child = child->next;
12269 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012270 /*
12271 * Parse attribute decls/refs.
12272 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012273 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12274 (xmlSchemaItemListPtr *) &(type->attrUses),
12275 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12276 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012277 /*
12278 * Parse attribute wildcard.
12279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012281 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12282 child = child->next;
12283 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012284 }
12285 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012286 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012287 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012288 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012289 NULL, "(annotation?, (simpleContent | complexContent | "
12290 "((group | all | choice | sequence)?, ((attribute | "
12291 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012292 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012293 /*
12294 * REDEFINE: SPEC src-redefine (5)
12295 */
12296 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12297 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012298 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012299 "<complexType> must have a <restriction> or <extension> "
12300 "grand-child", NULL);
12301 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012302 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012303 return (type);
12304}
12305
Daniel Veillard4255d502002-04-16 15:50:10 +000012306/************************************************************************
12307 * *
12308 * Validating using Schemas *
12309 * *
12310 ************************************************************************/
12311
12312/************************************************************************
12313 * *
12314 * Reading/Writing Schemas *
12315 * *
12316 ************************************************************************/
12317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318#if 0 /* Will be enabled if it is clear what options are needed. */
12319/**
12320 * xmlSchemaParserCtxtSetOptions:
12321 * @ctxt: a schema parser context
12322 * @options: a combination of xmlSchemaParserOption
12323 *
12324 * Sets the options to be used during the parse.
12325 *
12326 * Returns 0 in case of success, -1 in case of an
12327 * API error.
12328 */
12329static int
12330xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12331 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012332
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012333{
12334 int i;
12335
12336 if (ctxt == NULL)
12337 return (-1);
12338 /*
12339 * WARNING: Change the start value if adding to the
12340 * xmlSchemaParseOption.
12341 */
12342 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12343 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344 return (-1);
12345 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012346 }
12347 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012348 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012349}
12350
12351/**
12352 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012353 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012354 *
12355 * Returns the option combination of the parser context.
12356 */
12357static int
12358xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012359
12360{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012361 if (ctxt == NULL)
12362 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012363 else
12364 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012365}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012366#endif
12367
Daniel Veillard4255d502002-04-16 15:50:10 +000012368/**
12369 * xmlSchemaNewParserCtxt:
12370 * @URL: the location of the schema
12371 *
12372 * Create an XML Schemas parse context for that file/resource expected
12373 * to contain an XML Schemas file.
12374 *
12375 * Returns the parser context or NULL in case of error
12376 */
12377xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012378xmlSchemaNewParserCtxt(const char *URL)
12379{
Daniel Veillard4255d502002-04-16 15:50:10 +000012380 xmlSchemaParserCtxtPtr ret;
12381
12382 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012383 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012384
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012385 ret = xmlSchemaParserCtxtCreate();
12386 if (ret == NULL)
12387 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012388 ret->dict = xmlDictCreate();
12389 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012390 return (ret);
12391}
12392
12393/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012394 * xmlSchemaNewMemParserCtxt:
12395 * @buffer: a pointer to a char array containing the schemas
12396 * @size: the size of the array
12397 *
12398 * Create an XML Schemas parse context for that memory buffer expected
12399 * to contain an XML Schemas file.
12400 *
12401 * Returns the parser context or NULL in case of error
12402 */
12403xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012404xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12405{
Daniel Veillard6045c902002-10-09 21:13:59 +000012406 xmlSchemaParserCtxtPtr ret;
12407
12408 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012409 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012410 ret = xmlSchemaParserCtxtCreate();
12411 if (ret == NULL)
12412 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012413 ret->buffer = buffer;
12414 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012415 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012416 return (ret);
12417}
12418
12419/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012420 * xmlSchemaNewDocParserCtxt:
12421 * @doc: a preparsed document tree
12422 *
12423 * Create an XML Schemas parse context for that document.
12424 * NB. The document may be modified during the parsing process.
12425 *
12426 * Returns the parser context or NULL in case of error
12427 */
12428xmlSchemaParserCtxtPtr
12429xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12430{
12431 xmlSchemaParserCtxtPtr ret;
12432
12433 if (doc == NULL)
12434 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012435 ret = xmlSchemaParserCtxtCreate();
12436 if (ret == NULL)
12437 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012438 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012439 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012440 /* The application has responsibility for the document */
12441 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012442
12443 return (ret);
12444}
12445
12446/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012447 * xmlSchemaFreeParserCtxt:
12448 * @ctxt: the schema parser context
12449 *
12450 * Free the resources associated to the schema parser context
12451 */
12452void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012453xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12454{
Daniel Veillard4255d502002-04-16 15:50:10 +000012455 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012456 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012457 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012458 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012459 if (ctxt->vctxt != NULL) {
12460 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12461 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012462 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12463 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12464 ctxt->constructor = NULL;
12465 ctxt->ownsConstructor = 0;
12466 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012467 if (ctxt->attrProhibs != NULL)
12468 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012469 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012470 xmlFree(ctxt);
12471}
12472
12473/************************************************************************
12474 * *
12475 * Building the content models *
12476 * *
12477 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012478
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012479static void
12480xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012481 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012482{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012483 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012484 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012485 xmlSchemaSubstGroupPtr substGroup;
12486 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012487
12488 elemDecl = (xmlSchemaElementPtr) particle->children;
12489 /*
12490 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012491 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012492 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012493 if (end == NULL)
12494 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012495 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012496 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012497 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012498 XML_SCHEMAP_INTERNAL,
12499 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12500 "declaration is marked having a subst. group but none "
12501 "available.\n", elemDecl->name, NULL);
12502 return;
12503 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012504 if (counter >= 0) {
12505 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012506 * NOTE that we put the declaration in, even if it's abstract.
12507 * However, an error will be raised during *validation* if an element
12508 * information item shall be validated against an abstract element
12509 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012510 */
12511 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12512 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12513 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12514 /*
12515 * Add subst. group members.
12516 */
12517 for (i = 0; i < substGroup->members->nbItems; i++) {
12518 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12519 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12520 member->name, member->targetNamespace, member);
12521 }
12522 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012523 /*
12524 * NOTE that we put the declaration in, even if it's abstract,
12525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012526 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012527 xmlAutomataNewTransition2(pctxt->am,
12528 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012529 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12530 /*
12531 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012532 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012533 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012535 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12536 member->name, member->targetNamespace,
12537 1, 1, member);
12538 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012539 }
12540 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012541 xmlAutomataStatePtr hop;
12542 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12543 UNBOUNDED : particle->maxOccurs - 1;
12544 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12545
12546 counter =
12547 xmlAutomataNewCounter(pctxt->am, minOccurs,
12548 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012549 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012550
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012552 xmlAutomataNewTransition2(pctxt->am,
12553 start, NULL,
12554 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012555 hop);
12556 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012557 * Add subst. group members.
12558 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012559 for (i = 0; i < substGroup->members->nbItems; i++) {
12560 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12561 xmlAutomataNewEpsilon(pctxt->am,
12562 xmlAutomataNewTransition2(pctxt->am,
12563 start, NULL,
12564 member->name, member->targetNamespace, member),
12565 hop);
12566 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012567 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12568 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12569 }
12570 if (particle->minOccurs == 0)
12571 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012572 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012573}
12574
12575static void
12576xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12577 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012578{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012579 if (((xmlSchemaElementPtr) particle->children)->flags &
12580 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012581 /*
12582 * Substitution groups.
12583 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012584 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012585 } else {
12586 xmlSchemaElementPtr elemDecl;
12587 xmlAutomataStatePtr start;
12588
12589 elemDecl = (xmlSchemaElementPtr) particle->children;
12590
12591 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012593 if (particle->maxOccurs == 1) {
12594 start = ctxt->state;
12595 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012596 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12597 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12598 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012599 /* Special case. */
12600 start = ctxt->state;
12601 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12602 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012604 } else {
12605 int counter;
12606 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12607 UNBOUNDED : particle->maxOccurs - 1;
12608 int minOccurs = particle->minOccurs < 1 ?
12609 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012610
12611 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012612 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12613 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12614 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12615 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12616 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12617 NULL, counter);
12618 }
12619 if (particle->minOccurs == 0)
12620 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12621 }
12622}
12623
Daniel Veillard4255d502002-04-16 15:50:10 +000012624/**
12625 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012626 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012627 * @particle: the particle component
12628 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012629 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012630 * Create the automaton for the {content type} of a complex type.
12631 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012632 */
12633static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012634xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012635 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012636{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012637 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012638 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012639 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012640 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012641 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012642 /*
12643 * Just return in this case. A missing "term" of the particle
12644 * might arise due to an invalid "term" component.
12645 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012646 return;
12647 }
12648
12649 switch (particle->children->type) {
12650 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012651 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012652 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012653 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012654
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012655 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012657 start = pctxt->state;
12658 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012659
12660 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012661 if (wild->any == 1) {
12662 /*
12663 * We need to add both transitions:
12664 *
12665 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012666 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012667 pctxt->state =
12668 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012669 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012670 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012671 /*
12672 * 2. the {"*"} for elements in no namespace.
12673 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012674 pctxt->state =
12675 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012676 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012677 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012678
12679 } else if (wild->nsSet != NULL) {
12680 ns = wild->nsSet;
12681 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012682 pctxt->state = start;
12683 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12684 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12685 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012686 ns = ns->next;
12687 } while (ns != NULL);
12688
12689 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012690 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12691 start, end, BAD_CAST "*", wild->negNsSet->value,
12692 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012694 } else {
12695 int counter;
12696 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012697 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012698 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012700 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012701
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012702 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12703 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012704 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012705 pctxt->state =
12706 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012707 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012708 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12709 pctxt->state =
12710 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012711 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012712 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012714 ns = wild->nsSet;
12715 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012716 pctxt->state =
12717 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012718 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012719 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012720 ns = ns->next;
12721 } while (ns != NULL);
12722
12723 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012724 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012725 start, hop, BAD_CAST "*", wild->negNsSet->value,
12726 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012728 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12729 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012730 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012731 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012732 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012733 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012734 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012735 break;
12736 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012737 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012738 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012739 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012740 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012741 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012742
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012743 /*
12744 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012745 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012746 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012747 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12748 sub = particle->children->children;
12749 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012750 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012751 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012752 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 }
12754 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012755 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012756
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012757 if (particle->maxOccurs >= UNBOUNDED) {
12758 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012759 xmlAutomataStatePtr tmp;
12760 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012761
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012762 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012763 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012764 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012765
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012766 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012767 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012768
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012769 sub = particle->children->children;
12770 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012771 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012772 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012773 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012774 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012775 tmp = pctxt->state;
12776 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012777 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012778 pctxt->state =
12779 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012780 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012781
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012782 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012783 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012784 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012785 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012786
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012787 sub = particle->children->children;
12788 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012789 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012790 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012791 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012792 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012793 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012794 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012795 /*
12796 * epsilon needed to block previous trans from
12797 * being allowed to enter back from another
12798 * construct
12799 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012800 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12801 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012802 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012803 xmlAutomataNewEpsilon(pctxt->am,
12804 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012805 }
12806 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012807 } else if ((particle->maxOccurs > 1)
12808 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012809 xmlAutomataStatePtr tmp;
12810 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012811
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012812 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012813 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012814 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012815
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012816 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012817 particle->minOccurs - 1,
12818 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012819
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012820 sub = particle->children->children;
12821 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012822 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012823 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012824 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012825 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012826 tmp = pctxt->state;
12827 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012828 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012829 pctxt->state =
12830 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012831 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012832 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012833 xmlAutomataNewEpsilon(pctxt->am,
12834 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012835 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012836 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012837 sub = particle->children->children;
12838 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012839 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012840 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012841 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012842 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012843 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012844 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12845 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012846 }
12847 }
12848 }
12849 break;
12850 }
12851 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012852 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012853 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012854
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012855 start = pctxt->state;
12856 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012857
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012858 /*
12859 * iterate over the subtypes and remerge the end with an
12860 * epsilon transition
12861 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012862 if (particle->maxOccurs == 1) {
12863 sub = particle->children->children;
12864 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012865 pctxt->state = start;
12866 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012867 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012868 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012869 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012870 }
12871 } else {
12872 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012873 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012874 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12875 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012876 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012877 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012878
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012879 /*
12880 * use a counter to keep track of the number of transtions
12881 * which went through the choice.
12882 */
12883 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012884 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12885 hop = xmlAutomataNewState(pctxt->am);
12886 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012887
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012888 sub = particle->children->children;
12889 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012890 pctxt->state = base;
12891 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012892 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012893 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012894 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012895 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012896 xmlAutomataNewEpsilon(pctxt->am, start, base);
12897 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12898 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012899 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012900 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012901 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012902 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012903 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012904 break;
12905 }
12906 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012907 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012908 xmlSchemaParticlePtr sub;
12909 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012910 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012911
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012912 sub = (xmlSchemaParticlePtr) particle->children->children;
12913 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012914 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012915 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012916 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012917 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012918
12919 elemDecl = (xmlSchemaElementPtr) sub->children;
12920 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012921 PERROR_INT("xmlSchemaBuildAContentModel",
12922 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012923 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012924 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012925 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012926 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012927 * {particles} of the group must be 0 or 1; this is
12928 * already ensured during the parse of the content of
12929 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012930 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012931 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12932 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012933
Daniel Veillarda980bef2005-07-18 21:34:03 +000012934 /*
12935 * This is an abstract group, we need to share
12936 * the same counter for all the element transitions
12937 * derived from the group
12938 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012939 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012940 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012941 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12942 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012943 } else {
12944 if ((sub->minOccurs == 1) &&
12945 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012946 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12947 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012948 elemDecl->name,
12949 elemDecl->targetNamespace,
12950 1, 1, elemDecl);
12951 } else if ((sub->minOccurs == 0) &&
12952 (sub->maxOccurs == 1)) {
12953
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012954 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12955 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012956 elemDecl->name,
12957 elemDecl->targetNamespace,
12958 0,
12959 1,
12960 elemDecl);
12961 }
12962 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012963 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012964 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012965 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012966 pctxt->state =
12967 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012968 break;
12969 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012970 case XML_SCHEMA_TYPE_GROUP:
12971 /*
12972 * If we hit a model group definition, then this means that
12973 * it was empty, thus was not substituted for the containing
12974 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012975 * TODO: But the group should be substituted and not occur at
12976 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012977 */
12978 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012979 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012980 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12981 "xmlSchemaBuildAContentModel",
12982 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012983 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012984 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012985 }
12986}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012987
Daniel Veillard4255d502002-04-16 15:50:10 +000012988/**
12989 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012990 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012991 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012992 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012993 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012994 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012995 */
12996static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012997xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012998 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012999{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013000 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13001 (type->contModel != NULL) ||
13002 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13003 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013004 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013005
13006#ifdef DEBUG_CONTENT
13007 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013008 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013009#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013010 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013011 ctxt->am = xmlNewAutomata();
13012 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013013 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013014 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013015 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013016 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013017 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013018 /*
13019 * Build the automaton.
13020 */
13021 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013022 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013023 type->contModel = xmlAutomataCompile(ctxt->am);
13024 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013025 xmlSchemaPCustomErr(ctxt,
13026 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013027 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013028 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013029 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013030 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013031 XML_SCHEMAP_NOT_DETERMINISTIC,
13032 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013033 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013034 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013035 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013036#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013037 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013038 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013039 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013040#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013041 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013042 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013043 xmlFreeAutomata(ctxt->am);
13044 ctxt->am = NULL;
13045}
13046
13047/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013048 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013049 * @elem: the schema element context
13050 * @ctxt: the schema parser context
13051 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013052 * Resolves the references of an element declaration
13053 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013054 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013055 */
13056static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013057xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13058 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013059{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013060 if ((ctxt == NULL) || (elemDecl == NULL) ||
13061 ((elemDecl != NULL) &&
13062 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013063 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013064 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013065
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013066 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013067 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013068
13069 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013070 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013071 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013072 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013073 elemDecl->namedTypeNs);
13074 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013075 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013076 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013077 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013078 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013079 XML_SCHEMA_TYPE_BASIC, "type definition");
13080 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013081 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013082 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013083 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013084 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013085
Daniel Veillardc0826a72004-08-10 14:17:33 +000013086 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013087 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013088 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013090 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13091 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013092 if (substHead == NULL) {
13093 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013094 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013095 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013096 "substitutionGroup", elemDecl->substGroup,
13097 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013098 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013099 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013100 /*
13101 * Set the "substitution group affiliation".
13102 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013103 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013104 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013105 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013106 * The type definitions is set to:
13107 * SPEC "...the {type definition} of the element
13108 * declaration ·resolved· to by the ·actual value·
13109 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013110 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013111 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013112 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013113 }
13114 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013115 /*
13116 * SPEC "The definition of anyType serves as the default type definition
13117 * for element declarations whose XML representation does not specify one."
13118 */
13119 if ((elemDecl->subtypes == NULL) &&
13120 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013121 (elemDecl->substGroup == NULL))
13122 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013123}
13124
13125/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013126 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013127 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013128 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013129 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013130 * Checks and builds the "member type definitions" property of the union
13131 * simple type. This handles part (1), part (2) is done in
13132 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13133 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013134 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013135 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013136static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013137xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13138 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013139{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013140
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013141 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013142 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013143
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013144 /*
13145 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13146 * define the explicit members as the type definitions ·resolved·
13147 * to by the items in the ·actual value· of the memberTypes [attribute],
13148 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013149 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013150 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013151 /*
13152 * Resolve references.
13153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013154 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013155 lastLink = NULL;
13156 while (link != NULL) {
13157 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013159 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13160 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13161
13162 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013163 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013165 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013166 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13167 /*
13168 * Remove the member type link.
13169 */
13170 if (lastLink == NULL)
13171 type->memberTypes = link->next;
13172 else
13173 lastLink->next = link->next;
13174 newLink = link;
13175 link = link->next;
13176 xmlFree(newLink);
13177 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013178 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013179 lastLink = link;
13180 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013181 }
13182 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 /*
13184 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013185 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013187 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13189 if (link == NULL) {
13190 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13191 return (-1);
13192 }
13193 link->type = memberType;
13194 link->next = NULL;
13195 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 type->memberTypes = link;
13197 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198 lastLink->next = link;
13199 lastLink = link;
13200 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013202 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013203}
13204
Daniel Veillard4255d502002-04-16 15:50:10 +000013205/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013206 * xmlSchemaIsDerivedFromBuiltInType:
13207 * @ctxt: the schema parser context
13208 * @type: the type definition
13209 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013210 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013211 *
13212 * Returns 1 if the type has the given value type, or
13213 * is derived from such a type.
13214 */
William M. Brack803812b2004-06-03 02:11:24 +000013215static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013216xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013217{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013218 if (type == NULL)
13219 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013220 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013221 return (0);
13222 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13223 if (type->builtInType == valType)
13224 return(1);
13225 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13226 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13227 return (0);
13228 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13229 } else
13230 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013231
13232 return (0);
13233}
13234
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013235#if 0
13236/**
13237 * xmlSchemaIsDerivedFromBuiltInType:
13238 * @ctxt: the schema parser context
13239 * @type: the type definition
13240 * @valType: the value type
13241 *
13242 *
13243 * Returns 1 if the type has the given value type, or
13244 * is derived from such a type.
13245 */
13246static int
13247xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13248{
13249 if (type == NULL)
13250 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013251 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013252 return (0);
13253 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13254 if (type->builtInType == valType)
13255 return(1);
13256 return (0);
13257 } else
13258 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13259
13260 return (0);
13261}
13262#endif
13263
13264static xmlSchemaTypePtr
13265xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13266{
13267 if (type == NULL)
13268 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013269 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013270 return (NULL);
13271 if (type->type == XML_SCHEMA_TYPE_BASIC)
13272 return(type);
13273 else
13274 return(xmlSchemaQueryBuiltInType(type->subtypes));
13275
13276 return (NULL);
13277}
13278
Daniel Veillard3646d642004-06-02 19:19:14 +000013279/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013280 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013281 * @type: the simpleType definition
13282 *
13283 * Returns the primitive type of the given type or
13284 * NULL in case of error.
13285 */
13286static xmlSchemaTypePtr
13287xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13288{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013289
Daniel Veillard01fa6152004-06-29 17:04:39 +000013290 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013291 /*
13292 * Note that anySimpleType is actually not a primitive type
13293 * but we need that here.
13294 */
13295 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13296 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013297 return (type);
13298 type = type->baseType;
13299 }
13300
13301 return (NULL);
13302}
13303
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013304#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013305/**
13306 * xmlSchemaGetBuiltInTypeAncestor:
13307 * @type: the simpleType definition
13308 *
13309 * Returns the primitive type of the given type or
13310 * NULL in case of error.
13311 */
13312static xmlSchemaTypePtr
13313xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13314{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013315 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013316 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013317 while (type != NULL) {
13318 if (type->type == XML_SCHEMA_TYPE_BASIC)
13319 return (type);
13320 type = type->baseType;
13321 }
13322
13323 return (NULL);
13324}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013325#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013326
Daniel Veillard01fa6152004-06-29 17:04:39 +000013327/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013328 * xmlSchemaCloneWildcardNsConstraints:
13329 * @ctxt: the schema parser context
13330 * @dest: the destination wildcard
13331 * @source: the source wildcard
13332 *
13333 * Clones the namespace constraints of source
13334 * and assignes them to dest.
13335 * Returns -1 on internal error, 0 otherwise.
13336 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013337static int
13338xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013339 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013340 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013341{
13342 xmlSchemaWildcardNsPtr cur, tmp, last;
13343
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013344 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013345 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013346 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013347 cur = source->nsSet;
13348 last = NULL;
13349 while (cur != NULL) {
13350 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13351 if (tmp == NULL)
13352 return(-1);
13353 tmp->value = cur->value;
13354 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013355 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013356 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013357 last->next = tmp;
13358 last = tmp;
13359 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013360 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013361 if (dest->negNsSet != NULL)
13362 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013363 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013364 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13365 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013366 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013367 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013368 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013369 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013370 return(0);
13371}
13372
Daniel Veillard50355f02004-06-08 17:52:16 +000013373/**
13374 * xmlSchemaUnionWildcards:
13375 * @ctxt: the schema parser context
13376 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013377 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013378 *
13379 * Unions the namespace constraints of the given wildcards.
13380 * @completeWild will hold the resulting union.
13381 * Returns a positive error code on failure, -1 in case of an
13382 * internal error, 0 otherwise.
13383 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013384static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013385xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013386 xmlSchemaWildcardPtr completeWild,
13387 xmlSchemaWildcardPtr curWild)
13388{
13389 xmlSchemaWildcardNsPtr cur, curB, tmp;
13390
13391 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013392 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013393 * value.
13394 */
13395 if ((completeWild->any == curWild->any) &&
13396 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13397 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013398
Daniel Veillard3646d642004-06-02 19:19:14 +000013399 if ((completeWild->negNsSet == NULL) ||
13400 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013401
Daniel Veillard3646d642004-06-02 19:19:14 +000013402 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013403 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013404
13405 /*
13406 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013407 */
13408 cur = completeWild->nsSet;
13409 while (cur != NULL) {
13410 found = 0;
13411 curB = curWild->nsSet;
13412 while (curB != NULL) {
13413 if (cur->value == curB->value) {
13414 found = 1;
13415 break;
13416 }
13417 curB = curB->next;
13418 }
13419 if (!found)
13420 break;
13421 cur = cur->next;
13422 }
13423 if (found)
13424 return(0);
13425 } else
13426 return(0);
13427 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013429 /*
13430 * 2 If either O1 or O2 is any, then any must be the value
13431 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013433 if (completeWild->any == 0) {
13434 completeWild->any = 1;
13435 if (completeWild->nsSet != NULL) {
13436 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13437 completeWild->nsSet = NULL;
13438 }
13439 if (completeWild->negNsSet != NULL) {
13440 xmlFree(completeWild->negNsSet);
13441 completeWild->negNsSet = NULL;
13442 }
13443 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013444 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013445 }
13446 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013448 * then the union of those sets must be the value.
13449 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013450 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013451 int found;
13452 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013453
Daniel Veillard3646d642004-06-02 19:19:14 +000013454 cur = curWild->nsSet;
13455 start = completeWild->nsSet;
13456 while (cur != NULL) {
13457 found = 0;
13458 curB = start;
13459 while (curB != NULL) {
13460 if (cur->value == curB->value) {
13461 found = 1;
13462 break;
13463 }
13464 curB = curB->next;
13465 }
13466 if (!found) {
13467 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013468 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013469 return (-1);
13470 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013471 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013472 completeWild->nsSet = tmp;
13473 }
13474 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013475 }
13476
Daniel Veillard3646d642004-06-02 19:19:14 +000013477 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013479 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013480 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013481 * or ·absent·), then a pair of not and ·absent· must be the value.
13482 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013483 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013484 (curWild->negNsSet != NULL) &&
13485 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13486 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013487
13488 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013489 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013491 * 5.
13492 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013494 (completeWild->negNsSet->value != NULL) &&
13495 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013497 (curWild->negNsSet->value != NULL) &&
13498 (completeWild->nsSet != NULL))) {
13499
13500 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501
Daniel Veillard3646d642004-06-02 19:19:14 +000013502 if (completeWild->nsSet != NULL) {
13503 cur = completeWild->nsSet;
13504 curB = curWild->negNsSet;
13505 } else {
13506 cur = curWild->nsSet;
13507 curB = completeWild->negNsSet;
13508 }
13509 nsFound = 0;
13510 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013512 absentFound = 1;
13513 else if (cur->value == curB->value)
13514 nsFound = 1;
13515 if (nsFound && absentFound)
13516 break;
13517 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013519
13520 if (nsFound && absentFound) {
13521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013522 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013523 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013525 completeWild->any = 1;
13526 if (completeWild->nsSet != NULL) {
13527 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13528 completeWild->nsSet = NULL;
13529 }
13530 if (completeWild->negNsSet != NULL) {
13531 xmlFree(completeWild->negNsSet);
13532 completeWild->negNsSet = NULL;
13533 }
13534 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013535 /*
13536 * 5.2 If the set S includes the negated namespace name
13537 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013538 * be the value.
13539 */
13540 if (completeWild->nsSet != NULL) {
13541 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13542 completeWild->nsSet = NULL;
13543 }
13544 if (completeWild->negNsSet == NULL) {
13545 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13546 if (completeWild->negNsSet == NULL)
13547 return (-1);
13548 }
13549 completeWild->negNsSet->value = NULL;
13550 } else if ((!nsFound) && absentFound) {
13551 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013552 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013553 * namespace name, then the union is not expressible.
13554 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013555 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013556 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013557 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013559 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013560 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 /*
13562 * 5.4 If the set S does not include either the negated namespace
13563 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013564 * and a namespace name must be the value.
13565 */
13566 if (completeWild->negNsSet == NULL) {
13567 if (completeWild->nsSet != NULL) {
13568 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13569 completeWild->nsSet = NULL;
13570 }
13571 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13572 if (completeWild->negNsSet == NULL)
13573 return (-1);
13574 completeWild->negNsSet->value = curWild->negNsSet->value;
13575 }
13576 }
13577 return (0);
13578 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013579 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013580 * 6.
13581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013583 (completeWild->negNsSet->value == NULL) &&
13584 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013586 (curWild->negNsSet->value == NULL) &&
13587 (completeWild->nsSet != NULL))) {
13588
13589 if (completeWild->nsSet != NULL) {
13590 cur = completeWild->nsSet;
13591 } else {
13592 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013593 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013594 while (cur != NULL) {
13595 if (cur->value == NULL) {
13596 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013598 * value.
13599 */
13600 completeWild->any = 1;
13601 if (completeWild->nsSet != NULL) {
13602 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13603 completeWild->nsSet = NULL;
13604 }
13605 if (completeWild->negNsSet != NULL) {
13606 xmlFree(completeWild->negNsSet);
13607 completeWild->negNsSet = NULL;
13608 }
13609 return (0);
13610 }
13611 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013613 if (completeWild->negNsSet == NULL) {
13614 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013615 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013616 * and ·absent· must be the value.
13617 */
13618 if (completeWild->nsSet != NULL) {
13619 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13620 completeWild->nsSet = NULL;
13621 }
13622 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13623 if (completeWild->negNsSet == NULL)
13624 return (-1);
13625 completeWild->negNsSet->value = NULL;
13626 }
13627 return (0);
13628 }
13629 return (0);
13630
13631}
13632
Daniel Veillard50355f02004-06-08 17:52:16 +000013633/**
13634 * xmlSchemaIntersectWildcards:
13635 * @ctxt: the schema parser context
13636 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013637 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013638 *
13639 * Intersects the namespace constraints of the given wildcards.
13640 * @completeWild will hold the resulting intersection.
13641 * Returns a positive error code on failure, -1 in case of an
13642 * internal error, 0 otherwise.
13643 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013644static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013646 xmlSchemaWildcardPtr completeWild,
13647 xmlSchemaWildcardPtr curWild)
13648{
William M. Brack803812b2004-06-03 02:11:24 +000013649 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013650
13651 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013653 * value.
13654 */
13655 if ((completeWild->any == curWild->any) &&
13656 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13657 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013658
Daniel Veillard3646d642004-06-02 19:19:14 +000013659 if ((completeWild->negNsSet == NULL) ||
13660 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013661
Daniel Veillard3646d642004-06-02 19:19:14 +000013662 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013663 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013664
13665 /*
13666 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013667 */
13668 cur = completeWild->nsSet;
13669 while (cur != NULL) {
13670 found = 0;
13671 curB = curWild->nsSet;
13672 while (curB != NULL) {
13673 if (cur->value == curB->value) {
13674 found = 1;
13675 break;
13676 }
13677 curB = curB->next;
13678 }
13679 if (!found)
13680 break;
13681 cur = cur->next;
13682 }
13683 if (found)
13684 return(0);
13685 } else
13686 return(0);
13687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013689 /*
13690 * 2 If either O1 or O2 is any, then the other must be the value.
13691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013692 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013693 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013694 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013695 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013696 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013697 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13699 * name or ·absent·) and the other is a set of (namespace names or
13700 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 * the set, minus ·absent· if it was in the set, must be the value.
13702 */
13703 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13704 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13705 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013706
Daniel Veillard3646d642004-06-02 19:19:14 +000013707 if (completeWild->nsSet == NULL) {
13708 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013709 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013710 return(-1);
13711 } else
13712 neg = curWild->negNsSet->value;
13713 /*
13714 * Remove absent and negated.
13715 */
13716 prev = NULL;
13717 cur = completeWild->nsSet;
13718 while (cur != NULL) {
13719 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013721 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 prev->next = cur->next;
13724 xmlFree(cur);
13725 break;
13726 }
13727 prev = cur;
13728 cur = cur->next;
13729 }
13730 if (neg != NULL) {
13731 prev = NULL;
13732 cur = completeWild->nsSet;
13733 while (cur != NULL) {
13734 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013736 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013737 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013738 prev->next = cur->next;
13739 xmlFree(cur);
13740 break;
13741 }
13742 prev = cur;
13743 cur = cur->next;
13744 }
13745 }
13746
13747 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013749 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013751 * then the intersection of those sets must be the value.
13752 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013754 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013755
Daniel Veillard3646d642004-06-02 19:19:14 +000013756 cur = completeWild->nsSet;
13757 prev = NULL;
13758 while (cur != NULL) {
13759 found = 0;
13760 curB = curWild->nsSet;
13761 while (curB != NULL) {
13762 if (cur->value == curB->value) {
13763 found = 1;
13764 break;
13765 }
13766 curB = curB->next;
13767 }
13768 if (!found) {
13769 if (prev == NULL)
13770 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013771 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013772 prev->next = cur->next;
13773 tmp = cur->next;
13774 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013776 continue;
13777 }
13778 prev = cur;
13779 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 }
13781
Daniel Veillard3646d642004-06-02 19:19:14 +000013782 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 }
13784 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013785 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 */
13787 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013788 (curWild->negNsSet != NULL) &&
13789 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013791 (curWild->negNsSet->value != NULL)) {
13792
13793 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013794 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013796 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 }
13798 /*
13799 * 6 If the one is a negation of a namespace name and the other
13800 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013801 * of a namespace name must be the value.
13802 */
13803 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13804 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 (completeWild->negNsSet->value == NULL)) {
13806 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013807 }
13808 return(0);
13809}
13810
Daniel Veillard50355f02004-06-08 17:52:16 +000013811/**
13812 * xmlSchemaIsWildcardNsConstraintSubset:
13813 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013814 * @sub: the first wildcard
13815 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013816 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013817 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13818 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013819 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013820 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013821 */
13822static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013823xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13824 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013825{
Daniel Veillard50355f02004-06-08 17:52:16 +000013826 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013827 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013828 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013829 if (super->any)
13830 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013831 /*
13832 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13833 * 2.2 super must be a pair of not and the same value.
13834 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013835 if ((sub->negNsSet != NULL) &&
13836 (super->negNsSet != NULL) &&
13837 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 return (0);
13839 /*
13840 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013841 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013842 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013843 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013844 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013845 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013846 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013847 xmlSchemaWildcardNsPtr cur, curB;
13848 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013849
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013850 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013851 while (cur != NULL) {
13852 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013853 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013854 while (curB != NULL) {
13855 if (cur->value == curB->value) {
13856 found = 1;
13857 break;
13858 }
13859 curB = curB->next;
13860 }
13861 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013862 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013863 cur = cur->next;
13864 }
13865 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013866 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013867 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013868 xmlSchemaWildcardNsPtr cur;
13869 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013870 * 3.2.2 super must be a pair of not and a namespace name or
13871 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013872 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013873 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013875 if (cur->value == super->negNsSet->value)
13876 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013877 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013879 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013880 }
13881 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013882 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013883}
13884
Daniel Veillard50355f02004-06-08 17:52:16 +000013885static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013886xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013887 int *fixed,
13888 const xmlChar **value,
13889 xmlSchemaValPtr *val)
13890{
13891 *fixed = 0;
13892 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013893 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013894 *val = NULL;
13895
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013896 if (attruse->defValue != NULL) {
13897 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013898 if (val != NULL)
13899 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013900 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013901 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013902 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013903 } else if ((attruse->attrDecl != NULL) &&
13904 (attruse->attrDecl->defValue != NULL)) {
13905 *value = attruse->attrDecl->defValue;
13906 if (val != NULL)
13907 *val = attruse->attrDecl->defVal;
13908 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013909 *fixed = 1;
13910 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013911 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013912 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013913}
Daniel Veillard3646d642004-06-02 19:19:14 +000013914/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013915 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013916 * @wild: the wildcard
13917 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013918 *
13919 * Validation Rule: Wildcard allows Namespace Name
13920 * (cvc-wildcard-namespace)
13921 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013922 * Returns 0 if the given namespace matches the wildcard,
13923 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013924 */
13925static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013926xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13927 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013928{
13929 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013931
13932 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013933 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013934 else if (wild->nsSet != NULL) {
13935 xmlSchemaWildcardNsPtr cur;
13936
13937 cur = wild->nsSet;
13938 while (cur != NULL) {
13939 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013940 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013941 cur = cur->next;
13942 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013943 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013944 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013945 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013947 return(1);
13948}
13949
13950#define XML_SCHEMA_ACTION_DERIVE 0
13951#define XML_SCHEMA_ACTION_REDEFINE 1
13952
13953#define WXS_ACTION_STR(a) \
13954((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13955
13956/*
13957* Schema Component Constraint:
13958* Derivation Valid (Restriction, Complex)
13959* derivation-ok-restriction (2) - (4)
13960*
13961* ATTENTION:
13962* In XML Schema 1.1 this will be:
13963* Validation Rule:
13964* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13965*
13966*/
13967static int
13968xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13969 int action,
13970 xmlSchemaBasicItemPtr item,
13971 xmlSchemaBasicItemPtr baseItem,
13972 xmlSchemaItemListPtr uses,
13973 xmlSchemaItemListPtr baseUses,
13974 xmlSchemaWildcardPtr wild,
13975 xmlSchemaWildcardPtr baseWild)
13976{
13977 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013978 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013979 const xmlChar *bEffValue;
13980 int effFixed;
13981
13982 if (uses != NULL) {
13983 for (i = 0; i < uses->nbItems; i++) {
13984 cur = uses->items[i];
13985 found = 0;
13986 if (baseUses == NULL)
13987 goto not_found;
13988 for (j = 0; j < baseUses->nbItems; j++) {
13989 bcur = baseUses->items[j];
13990 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13991 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13992 (WXS_ATTRUSE_DECL_TNS(cur) ==
13993 WXS_ATTRUSE_DECL_TNS(bcur)))
13994 {
13995 /*
13996 * (2.1) "If there is an attribute use in the {attribute
13997 * uses} of the {base type definition} (call this B) whose
13998 * {attribute declaration} has the same {name} and {target
13999 * namespace}, then all of the following must be true:"
14000 */
14001 found = 1;
14002
14003 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14004 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14005 {
14006 xmlChar *str = NULL;
14007 /*
14008 * (2.1.1) "one of the following must be true:"
14009 * (2.1.1.1) "B's {required} is false."
14010 * (2.1.1.2) "R's {required} is true."
14011 */
14012 xmlSchemaPAttrUseErr4(pctxt,
14013 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14014 WXS_ITEM_NODE(item), item, cur,
14015 "The 'optional' attribute use is inconsistent "
14016 "with the corresponding 'required' attribute use of "
14017 "the %s %s",
14018 WXS_ACTION_STR(action),
14019 xmlSchemaGetComponentDesignation(&str, baseItem),
14020 NULL, NULL);
14021 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014022 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014023 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014024 WXS_ATTRUSE_TYPEDEF(cur),
14025 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14026 {
14027 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14028
14029 /*
14030 * SPEC (2.1.2) "R's {attribute declaration}'s
14031 * {type definition} must be validly derived from
14032 * B's {type definition} given the empty set as
14033 * defined in Type Derivation OK (Simple) (§3.14.6)."
14034 */
14035 xmlSchemaPAttrUseErr4(pctxt,
14036 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14037 WXS_ITEM_NODE(item), item, cur,
14038 "The attribute declaration's %s "
14039 "is not validly derived from "
14040 "the corresponding %s of the "
14041 "attribute declaration in the %s %s",
14042 xmlSchemaGetComponentDesignation(&strA,
14043 WXS_ATTRUSE_TYPEDEF(cur)),
14044 xmlSchemaGetComponentDesignation(&strB,
14045 WXS_ATTRUSE_TYPEDEF(bcur)),
14046 WXS_ACTION_STR(action),
14047 xmlSchemaGetComponentDesignation(&strC, baseItem));
14048 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14049 FREE_AND_NULL(strA);
14050 FREE_AND_NULL(strB);
14051 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014052 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014053 } else {
14054 /*
14055 * 2.1.3 [Definition:] Let the effective value
14056 * constraint of an attribute use be its {value
14057 * constraint}, if present, otherwise its {attribute
14058 * declaration}'s {value constraint} .
14059 */
14060 xmlSchemaGetEffectiveValueConstraint(bcur,
14061 &effFixed, &bEffValue, NULL);
14062 /*
14063 * 2.1.3 ... one of the following must be true
14064 *
14065 * 2.1.3.1 B's ·effective value constraint· is
14066 * ·absent· or default.
14067 */
14068 if ((bEffValue != NULL) &&
14069 (effFixed == 1)) {
14070 const xmlChar *rEffValue = NULL;
14071
14072 xmlSchemaGetEffectiveValueConstraint(bcur,
14073 &effFixed, &rEffValue, NULL);
14074 /*
14075 * 2.1.3.2 R's ·effective value constraint· is
14076 * fixed with the same string as B's.
14077 * MAYBE TODO: Compare the computed values.
14078 * Hmm, it says "same string" so
14079 * string-equality might really be sufficient.
14080 */
14081 if ((effFixed == 0) ||
14082 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14083 {
14084 xmlChar *str = NULL;
14085
14086 xmlSchemaPAttrUseErr4(pctxt,
14087 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14088 WXS_ITEM_NODE(item), item, cur,
14089 "The effective value constraint of the "
14090 "attribute use is inconsistent with "
14091 "its correspondent in the %s %s",
14092 WXS_ACTION_STR(action),
14093 xmlSchemaGetComponentDesignation(&str,
14094 baseItem),
14095 NULL, NULL);
14096 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014097 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014098 }
14099 }
14100 }
14101 break;
14102 }
14103 }
14104not_found:
14105 if (!found) {
14106 /*
14107 * (2.2) "otherwise the {base type definition} must have an
14108 * {attribute wildcard} and the {target namespace} of the
14109 * R's {attribute declaration} must be ·valid· with respect
14110 * to that wildcard, as defined in Wildcard allows Namespace
14111 * Name (§3.10.4)."
14112 */
14113 if ((baseWild == NULL) ||
14114 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14115 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14116 {
14117 xmlChar *str = NULL;
14118
14119 xmlSchemaPAttrUseErr4(pctxt,
14120 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14121 WXS_ITEM_NODE(item), item, cur,
14122 "Neither a matching attribute use, "
14123 "nor a matching wildcard exists in the %s %s",
14124 WXS_ACTION_STR(action),
14125 xmlSchemaGetComponentDesignation(&str, baseItem),
14126 NULL, NULL);
14127 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014128 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014129 }
14130 }
14131 }
14132 }
14133 /*
14134 * SPEC derivation-ok-restriction (3):
14135 * (3) "For each attribute use in the {attribute uses} of the {base type
14136 * definition} whose {required} is true, there must be an attribute
14137 * use with an {attribute declaration} with the same {name} and
14138 * {target namespace} as its {attribute declaration} in the {attribute
14139 * uses} of the complex type definition itself whose {required} is true.
14140 */
14141 if (baseUses != NULL) {
14142 for (j = 0; j < baseUses->nbItems; j++) {
14143 bcur = baseUses->items[j];
14144 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14145 continue;
14146 found = 0;
14147 if (uses != NULL) {
14148 for (i = 0; i < uses->nbItems; i++) {
14149 cur = uses->items[i];
14150 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14151 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14152 (WXS_ATTRUSE_DECL_TNS(cur) ==
14153 WXS_ATTRUSE_DECL_TNS(bcur))) {
14154 found = 1;
14155 break;
14156 }
14157 }
14158 }
14159 if (!found) {
14160 xmlChar *strA = NULL, *strB = NULL;
14161
14162 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14163 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14164 NULL, item,
14165 "A matching attribute use for the "
14166 "'required' %s of the %s %s is missing",
14167 xmlSchemaGetComponentDesignation(&strA, bcur),
14168 WXS_ACTION_STR(action),
14169 xmlSchemaGetComponentDesignation(&strB, baseItem),
14170 NULL);
14171 FREE_AND_NULL(strA);
14172 FREE_AND_NULL(strB);
14173 }
14174 }
14175 }
14176 /*
14177 * derivation-ok-restriction (4)
14178 */
14179 if (wild != NULL) {
14180 /*
14181 * (4) "If there is an {attribute wildcard}, all of the
14182 * following must be true:"
14183 */
14184 if (baseWild == NULL) {
14185 xmlChar *str = NULL;
14186
14187 /*
14188 * (4.1) "The {base type definition} must also have one."
14189 */
14190 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14191 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14192 NULL, item,
14193 "The %s has an attribute wildcard, "
14194 "but the %s %s '%s' does not have one",
14195 WXS_ITEM_TYPE_NAME(item),
14196 WXS_ACTION_STR(action),
14197 WXS_ITEM_TYPE_NAME(baseItem),
14198 xmlSchemaGetComponentQName(&str, baseItem));
14199 FREE_AND_NULL(str);
14200 return(pctxt->err);
14201 } else if ((baseWild->any == 0) &&
14202 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14203 {
14204 xmlChar *str = NULL;
14205 /*
14206 * (4.2) "The complex type definition's {attribute wildcard}'s
14207 * {namespace constraint} must be a subset of the {base type
14208 * definition}'s {attribute wildcard}'s {namespace constraint},
14209 * as defined by Wildcard Subset (§3.10.6)."
14210 */
14211 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14212 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14213 NULL, item,
14214 "The attribute wildcard is not a valid "
14215 "subset of the wildcard in the %s %s '%s'",
14216 WXS_ACTION_STR(action),
14217 WXS_ITEM_TYPE_NAME(baseItem),
14218 xmlSchemaGetComponentQName(&str, baseItem),
14219 NULL);
14220 FREE_AND_NULL(str);
14221 return(pctxt->err);
14222 }
14223 /* 4.3 Unless the {base type definition} is the ·ur-type
14224 * definition·, the complex type definition's {attribute
14225 * wildcard}'s {process contents} must be identical to or
14226 * stronger than the {base type definition}'s {attribute
14227 * wildcard}'s {process contents}, where strict is stronger
14228 * than lax is stronger than skip.
14229 */
14230 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14231 (wild->processContents < baseWild->processContents)) {
14232 xmlChar *str = NULL;
14233 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14234 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14235 NULL, baseItem,
14236 "The {process contents} of the attribute wildcard is "
14237 "weaker than the one in the %s %s '%s'",
14238 WXS_ACTION_STR(action),
14239 WXS_ITEM_TYPE_NAME(baseItem),
14240 xmlSchemaGetComponentQName(&str, baseItem),
14241 NULL);
14242 FREE_AND_NULL(str)
14243 return(pctxt->err);
14244 }
14245 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014246 return(0);
14247}
14248
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014249
14250static int
14251xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14252 xmlSchemaBasicItemPtr item,
14253 xmlSchemaWildcardPtr *completeWild,
14254 xmlSchemaItemListPtr list,
14255 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014256/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014257 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014258 * @ctxt: the schema parser context
14259 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014260 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014261 *
14262 * Builds the wildcard and the attribute uses on the given complex type.
14263 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014264 *
14265 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14266 * strings, so recheck this if we start to hardcode some schemata, since
14267 * they might not be in the same dict.
14268 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014269 */
14270static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014271xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014272 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014273{
14274 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014275 xmlSchemaAttributeUsePtr use;
14276 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014277
Daniel Veillard01fa6152004-06-29 17:04:39 +000014278 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014279 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014280 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014281 return (-1);
14282 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014283 baseType = type->baseType;
14284 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014285 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014286 return(-1);
14287
14288 uses = type->attrUses;
14289 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014290 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014291 * Expand attribute group references. And build the 'complete'
14292 * wildcard, i.e. intersect multiple wildcards.
14293 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014294 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014295 if (uses != NULL) {
14296 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014297 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014298 * This one will transfer all attr. prohibitions
14299 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014300 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014301 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14302 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14303 pctxt->attrProhibs) == -1)
14304 {
14305 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14306 "failed to expand attributes");
14307 }
14308 if (pctxt->attrProhibs->nbItems != 0)
14309 prohibs = pctxt->attrProhibs;
14310 } else {
14311 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14312 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14313 NULL) == -1)
14314 {
14315 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14316 "failed to expand attributes");
14317 }
14318 }
14319 }
14320 /*
14321 * Inherit the attribute uses of the base type.
14322 */
14323 if (baseUses != NULL) {
14324 int i, j;
14325 xmlSchemaAttributeUseProhibPtr pro;
14326
14327 if (WXS_IS_RESTRICTION(type)) {
14328 int usesCount;
14329 xmlSchemaAttributeUsePtr tmp;
14330
14331 if (uses != NULL)
14332 usesCount = uses->nbItems;
14333 else
14334 usesCount = 0;
14335
14336 /* Restriction. */
14337 for (i = 0; i < baseUses->nbItems; i++) {
14338 use = baseUses->items[i];
14339 if (prohibs) {
14340 /*
14341 * Filter out prohibited uses.
14342 */
14343 for (j = 0; j < prohibs->nbItems; j++) {
14344 pro = prohibs->items[j];
14345 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14346 (WXS_ATTRUSE_DECL_TNS(use) ==
14347 pro->targetNamespace))
14348 {
14349 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014350 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014351 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014352 }
14353 if (usesCount) {
14354 /*
14355 * Filter out existing uses.
14356 */
14357 for (j = 0; j < usesCount; j++) {
14358 tmp = uses->items[j];
14359 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14360 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14361 (WXS_ATTRUSE_DECL_TNS(use) ==
14362 WXS_ATTRUSE_DECL_TNS(tmp)))
14363 {
14364 goto inherit_next;
14365 }
14366 }
14367 }
14368 if (uses == NULL) {
14369 type->attrUses = xmlSchemaItemListCreate();
14370 if (type->attrUses == NULL)
14371 goto exit_failure;
14372 uses = type->attrUses;
14373 }
14374 xmlSchemaItemListAddSize(uses, 2, use);
14375inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014376 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014377 } else {
14378 /* Extension. */
14379 for (i = 0; i < baseUses->nbItems; i++) {
14380 use = baseUses->items[i];
14381 if (uses == NULL) {
14382 type->attrUses = xmlSchemaItemListCreate();
14383 if (type->attrUses == NULL)
14384 goto exit_failure;
14385 uses = type->attrUses;
14386 }
14387 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14388 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014389 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014390 }
14391 /*
14392 * Shrink attr. uses.
14393 */
14394 if (uses) {
14395 if (uses->nbItems == 0) {
14396 xmlSchemaItemListFree(uses);
14397 type->attrUses = NULL;
14398 }
14399 /*
14400 * TODO: We could shrink the size of the array
14401 * to fit the actual number of items.
14402 */
14403 }
14404 /*
14405 * Compute the complete wildcard.
14406 */
14407 if (WXS_IS_EXTENSION(type)) {
14408 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014409 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014410 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14411 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014412 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014413 if (type->attributeWildcard != NULL) {
14414 /*
14415 * Union the complete wildcard with the base wildcard.
14416 * SPEC {attribute wildcard}
14417 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14418 * and {annotation} are those of the ·complete wildcard·,
14419 * and whose {namespace constraint} is the intensional union
14420 * of the {namespace constraint} of the ·complete wildcard·
14421 * and of the ·base wildcard·, as defined in Attribute
14422 * Wildcard Union (§3.10.6)."
14423 */
14424 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14425 baseType->attributeWildcard) == -1)
14426 goto exit_failure;
14427 } else {
14428 /*
14429 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14430 * then the ·base wildcard·."
14431 */
14432 type->attributeWildcard = baseType->attributeWildcard;
14433 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014434 } else {
14435 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014436 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14437 * ·complete wildcard"
14438 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014439 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014440 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014441 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014442 /*
14443 * SPEC {attribute wildcard}
14444 * (3.1) "If the <restriction> alternative is chosen, then the
14445 * ·complete wildcard·;"
14446 * NOOP
14447 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014448 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014449
Daniel Veillard3646d642004-06-02 19:19:14 +000014450 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014451
14452exit_failure:
14453 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014454}
14455
14456/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014457 * xmlSchemaTypeFinalContains:
14458 * @schema: the schema
14459 * @type: the type definition
14460 * @final: the final
14461 *
14462 * Evaluates if a type definition contains the given "final".
14463 * This does take "finalDefault" into account as well.
14464 *
14465 * Returns 1 if the type does containt the given "final",
14466 * 0 otherwise.
14467 */
14468static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014469xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014470{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014471 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014472 return (0);
14473 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014474 return (1);
14475 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014477}
14478
14479/**
14480 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14481 * @type: the Union Simple Type
14482 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014483 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014484 * returns NULL otherwise.
14485 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014486static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014487xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14488{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014489 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014490 if (type->memberTypes != NULL)
14491 return (type->memberTypes);
14492 else
14493 type = type->baseType;
14494 }
14495 return (NULL);
14496}
14497
14498/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014499 * xmlSchemaGetParticleTotalRangeMin:
14500 * @particle: the particle
14501 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014502 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014503 * (all and sequence) + (choice)
14504 *
14505 * Returns the minimun Effective Total Range.
14506 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014507static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014508xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014509{
14510 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014511 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014512 return (0);
14513 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014514 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014515 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014516 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517
14518 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014519 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014520 while (part != NULL) {
14521 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14522 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014523 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014524 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014525 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014526 if (cur == 0)
14527 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014528 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014529 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014530 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014531 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014532 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014533 } else {
14534 /* <all> and <sequence> */
14535 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014536 xmlSchemaParticlePtr part =
14537 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014538
14539 if (part == NULL)
14540 return (0);
14541 do {
14542 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14543 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014544 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014545 else
14546 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014547 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014548 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014549 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014550 }
14551}
14552
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014553/**
14554 * xmlSchemaGetParticleTotalRangeMax:
14555 * @particle: the particle
14556 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014557 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014558 * (all and sequence) + (choice)
14559 *
14560 * Returns the maximum Effective Total Range.
14561 */
14562static int
14563xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14564{
14565 if ((particle->children == NULL) ||
14566 (particle->children->children == NULL))
14567 return (0);
14568 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14569 int max = -1, cur;
14570 xmlSchemaParticlePtr part =
14571 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014572
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014573 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14574 if (part->children == NULL)
14575 continue;
14576 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14577 (part->children->type == XML_SCHEMA_TYPE_ANY))
14578 cur = part->maxOccurs;
14579 else
14580 cur = xmlSchemaGetParticleTotalRangeMax(part);
14581 if (cur == UNBOUNDED)
14582 return (UNBOUNDED);
14583 if ((max < cur) || (max == -1))
14584 max = cur;
14585 }
14586 /* TODO: Handle overflows? */
14587 return (particle->maxOccurs * max);
14588 } else {
14589 /* <all> and <sequence> */
14590 int sum = 0, cur;
14591 xmlSchemaParticlePtr part =
14592 (xmlSchemaParticlePtr) particle->children->children;
14593
14594 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14595 if (part->children == NULL)
14596 continue;
14597 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14598 (part->children->type == XML_SCHEMA_TYPE_ANY))
14599 cur = part->maxOccurs;
14600 else
14601 cur = xmlSchemaGetParticleTotalRangeMax(part);
14602 if (cur == UNBOUNDED)
14603 return (UNBOUNDED);
14604 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14605 return (UNBOUNDED);
14606 sum += cur;
14607 }
14608 /* TODO: Handle overflows? */
14609 return (particle->maxOccurs * sum);
14610 }
14611}
14612
14613/**
14614 * xmlSchemaIsParticleEmptiable:
14615 * @particle: the particle
14616 *
14617 * Schema Component Constraint: Particle Emptiable
14618 * Checks whether the given particle is emptiable.
14619 *
14620 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014621 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014622static int
14623xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14624{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014625 /*
14626 * SPEC (1) "Its {min occurs} is 0."
14627 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014628 if ((particle == NULL) || (particle->minOccurs == 0) ||
14629 (particle->children == NULL))
14630 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014631 /*
14632 * SPEC (2) "Its {term} is a group and the minimum part of the
14633 * effective total range of that group, [...] is 0."
14634 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014635 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014636 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014637 return (1);
14638 }
14639 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014640}
14641
14642/**
14643 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014644 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014645 * @type: the derived simple type definition
14646 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014647 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014648 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014649 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014650 * Type Derivation OK (Simple) (cos-st-derived-OK)
14651 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014652 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014653 * derived from @baseType.
14654 *
14655 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014656 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014657static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014658xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014659 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014660 xmlSchemaTypePtr baseType,
14661 int subset)
14662{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014663 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 * 1 They are the same type definition.
14665 * TODO: The identy check might have to be more complex than this.
14666 */
14667 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 return (0);
14669 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014670 * 2.1 restriction is not in the subset, or in the {final}
14671 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014672 *
14673 * NOTE that this will be used also via "xsi:type".
14674 *
14675 * TODO: Revise this, it looks strange. How can the "type"
14676 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014677 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014678 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014679 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014680 return(-1);
14681 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014682 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014683 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014684 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014685 (xmlSchemaTypeFinalContains(type->baseType,
14686 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14687 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014688 }
14689 /* 2.2 */
14690 if (type->baseType == baseType) {
14691 /*
14692 * 2.2.1 D's ·base type definition· is B.
14693 */
14694 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014695 }
14696 /*
14697 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14698 * and is validly derived from B given the subset, as defined by this
14699 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014700 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014701 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014702 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014703 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014704 return (0);
14705 }
14706 /*
14707 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014708 * definition·.
14709 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014710 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14711 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014712 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014713 }
14714 /*
14715 * 2.2.4 B's {variety} is union and D is validly derived from a type
14716 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014717 * defined by this constraint.
14718 *
14719 * NOTE: This seems not to involve built-in types, since there is no
14720 * built-in Union Simple Type.
14721 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014722 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014723 xmlSchemaTypeLinkPtr cur;
14724
14725 cur = baseType->memberTypes;
14726 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014727 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014728 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014729 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014730 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014731 type, cur->type, subset) == 0)
14732 {
14733 /*
14734 * It just has to be validly derived from at least one
14735 * member-type.
14736 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014737 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014738 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014740 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014741 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014742 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14743}
14744
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014745/**
14746 * xmlSchemaCheckTypeDefCircularInternal:
14747 * @pctxt: the schema parser context
14748 * @ctxtType: the type definition
14749 * @ancestor: an ancestor of @ctxtType
14750 *
14751 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014752 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014753 *
14754 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14755 * circular, 0 otherwise.
14756 */
14757static int
14758xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14759 xmlSchemaTypePtr ctxtType,
14760 xmlSchemaTypePtr ancestor)
14761{
14762 int ret;
14763
14764 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14765 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014766
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014767 if (ctxtType == ancestor) {
14768 xmlSchemaPCustomErr(pctxt,
14769 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014770 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 "The definition is circular", NULL);
14772 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14773 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014774 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14775 /*
14776 * Avoid inifinite recursion on circular types not yet checked.
14777 */
14778 return (0);
14779 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014780 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14781 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14782 ancestor->baseType);
14783 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14784 return (ret);
14785}
14786
14787/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014788 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014789 * @item: the complex/simple type definition
14790 * @ctxt: the parser context
14791 * @name: the name
14792 *
14793 * Checks for circular type definitions.
14794 */
14795static void
14796xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014797 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014798{
14799 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014800 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14801 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014803 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14804 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014805}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014806
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014807/*
14808* Simple Type Definition Representation OK (src-simple-type) 4
14809*
14810* "4 Circular union type definition is disallowed. That is, if the
14811* <union> alternative is chosen, there must not be any entries in the
14812* memberTypes [attribute] at any depth which resolve to the component
14813* corresponding to the <simpleType>."
14814*
14815* Note that this should work on the *representation* of a component,
14816* thus assumes any union types in the member types not being yet
14817* substituted. At this stage we need the variety of the types
14818* to be already computed.
14819*/
14820static int
14821xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14822 xmlSchemaTypePtr ctxType,
14823 xmlSchemaTypeLinkPtr members)
14824{
14825 xmlSchemaTypeLinkPtr member;
14826 xmlSchemaTypePtr memberType;
14827
14828 member = members;
14829 while (member != NULL) {
14830 memberType = member->type;
14831 while ((memberType != NULL) &&
14832 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14833 if (memberType == ctxType) {
14834 xmlSchemaPCustomErr(pctxt,
14835 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014836 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014837 "The union type definition is circular", NULL);
14838 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14839 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014840 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014841 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14842 {
14843 int res;
14844 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14845 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14846 ctxType,
14847 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14848 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14849 if (res != 0)
14850 return(res);
14851 }
14852 memberType = memberType->baseType;
14853 }
14854 member = member->next;
14855 }
14856 return(0);
14857}
14858
14859static int
14860xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14861 xmlSchemaTypePtr type)
14862{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014863 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014864 return(0);
14865 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14866 type->memberTypes));
14867}
14868
Daniel Veillard01fa6152004-06-29 17:04:39 +000014869/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014870 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014871 * @item: the complex/simple type definition
14872 * @ctxt: the parser context
14873 * @name: the name
14874 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014875 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014876 */
14877static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014878xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014879 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014880{
14881 if (typeDef == NULL)
14882 return;
14883
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014884 /*
14885 * Resolve the base type.
14886 */
14887 if (typeDef->baseType == NULL) {
14888 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14889 typeDef->base, typeDef->baseNs);
14890 if (typeDef->baseType == NULL) {
14891 xmlSchemaPResCompAttrErr(ctxt,
14892 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014893 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014894 "base", typeDef->base, typeDef->baseNs,
14895 XML_SCHEMA_TYPE_SIMPLE, NULL);
14896 return;
14897 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014898 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014899 if (WXS_IS_SIMPLE(typeDef)) {
14900 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014901 /*
14902 * Resolve the memberTypes.
14903 */
14904 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14905 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014906 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014907 /*
14908 * Resolve the itemType.
14909 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014910 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14911
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014912 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014913 typeDef->base, typeDef->baseNs);
14914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014915 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014916 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14917 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014918 typeDef->subtypes = NULL;
14919 xmlSchemaPResCompAttrErr(ctxt,
14920 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014921 WXS_BASIC_CAST typeDef, typeDef->node,
14922 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014923 XML_SCHEMA_TYPE_SIMPLE, NULL);
14924 }
14925 }
14926 return;
14927 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014928 }
14929 /*
14930 * The ball of letters below means, that if we have a particle
14931 * which has a QName-helper component as its {term}, we want
14932 * to resolve it...
14933 */
14934 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14935 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14936 XML_SCHEMA_TYPE_PARTICLE) &&
14937 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14938 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14939 XML_SCHEMA_EXTRA_QNAMEREF))
14940 {
14941 xmlSchemaQNameRefPtr ref =
14942 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14943 xmlSchemaModelGroupDefPtr groupDef;
14944
14945 /*
14946 * URGENT TODO: Test this.
14947 */
14948 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14949 /*
14950 * Resolve the MG definition reference.
14951 */
14952 groupDef =
14953 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14954 ref->itemType, ref->name, ref->targetNamespace);
14955 if (groupDef == NULL) {
14956 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14957 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14958 "ref", ref->name, ref->targetNamespace, ref->itemType,
14959 NULL);
14960 /* Remove the particle. */
14961 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14962 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14963 /* Remove the particle. */
14964 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14965 else {
14966 /*
14967 * Assign the MG definition's {model group} to the
14968 * particle's {term}.
14969 */
14970 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14971
14972 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14973 /*
14974 * SPEC cos-all-limited (1.2)
14975 * "1.2 the {term} property of a particle with
14976 * {max occurs}=1 which is part of a pair which constitutes
14977 * the {content type} of a complex type definition."
14978 */
14979 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14980 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14981 /* TODO: error code */
14982 XML_SCHEMAP_COS_ALL_LIMITED,
14983 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14984 "The particle's {max occurs} must be 1, since the "
14985 "reference resolves to an 'all' model group",
14986 NULL, NULL);
14987 }
14988 }
14989 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014990 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014991}
14992
14993
14994
14995/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014996 * xmlSchemaCheckSTPropsCorrect:
14997 * @ctxt: the schema parser context
14998 * @type: the simple type definition
14999 *
15000 * Checks st-props-correct.
15001 *
15002 * Returns 0 if the properties are correct,
15003 * if not, a positive error code and -1 on internal
15004 * errors.
15005 */
15006static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015007xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015008 xmlSchemaTypePtr type)
15009{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015010 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015011 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015012
Daniel Veillardc0826a72004-08-10 14:17:33 +000015013 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015014 /*
15015 * Schema Component Constraint: Simple Type Definition Properties Correct
15016 *
15017 * NOTE: This is somehow redundant, since we actually built a simple type
15018 * to have all the needed information; this acts as an self test.
15019 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015020 /* Base type: If the datatype has been ·derived· by ·restriction·
15021 * then the Simple Type Definition component from which it is ·derived·,
15022 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015023 */
15024 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015025 /*
15026 * TODO: Think about: "modulo the impact of Missing
15027 * Sub-components (§5.3)."
15028 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015029 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015030 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015031 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015032 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015033 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015034
Daniel Veillard01fa6152004-06-29 17:04:39 +000015035 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015036 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015037 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015038 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015039 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015040 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015041 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015042 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15044 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015045 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015046 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015047 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015048 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015049 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015050 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015051 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015052 "the simple ur-type definition as base type, not '%s'",
15053 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015054 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015055 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15056 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015057 /*
15058 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015060 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15061 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015062 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015063 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015064 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015065 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015066 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15067 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015068 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015069
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015070 /*
15071 * 3 The {final} of the {base type definition} must not contain restriction.
15072 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015073 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015074 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15075 xmlSchemaPCustomErr(ctxt,
15076 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015077 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015078 "The 'final' of its base type '%s' must not contain "
15079 "'restriction'",
15080 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015081 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015082 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015084
15085 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015086 * 2 All simple type definitions must be derived ultimately from the ·simple
15087 * ur-type definition (so· circular definitions are disallowed). That is, it
15088 * must be possible to reach a built-in primitive datatype or the ·simple
15089 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015090 *
15091 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015092 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015093 return (0);
15094}
15095
15096/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015097 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015098 * @ctxt: the schema parser context
15099 * @type: the simple type definition
15100 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015101 * Schema Component Constraint:
15102 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15103
15104 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015105 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015106 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015107 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015108 * a positive error code otherwise.
15109 */
15110static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015111xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015112 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015113{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015114 xmlChar *str = NULL;
15115
Daniel Veillard01fa6152004-06-29 17:04:39 +000015116 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015117 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15118 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015119 return (-1);
15120 }
15121
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015122 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015123 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015124 /*
15125 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015126 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015127 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015128 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015130 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015131 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015132 "The base type '%s' is not an atomic simple type",
15133 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015134 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015135 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15136 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015137 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015138 * restriction.
15139 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015140 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015141 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015142 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015143 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015144 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015145 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015146 "The final of its base type '%s' must not contain 'restriction'",
15147 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015148 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015149 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15150 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015151
15152 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015153 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015154 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015155 * Primitive datatypes.
15156 */
15157 if (type->facets != NULL) {
15158 xmlSchemaFacetPtr facet;
15159 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015160
Daniel Veillard01fa6152004-06-29 17:04:39 +000015161 primitive = xmlSchemaGetPrimitiveType(type);
15162 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015163 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15164 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015165 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015166 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015167 facet = type->facets;
15168 do {
15169 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015170 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015172 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015173 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015174 }
15175 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015176 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015178 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015179 }
15180 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015181 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15182 * of the {base type definition} (call this BF),then the DF's {value}
15183 * must be a valid restriction of BF's {value} as defined in
15184 * [XML Schemas: Datatypes]."
15185 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015187 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015188 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015189 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015190 xmlSchemaTypePtr itemType = NULL;
15191
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015192 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015193 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015194 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15195 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015196 return (-1);
15197 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015198 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015199 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015201 * 2.1 The {item type definition} must have a {variety} of atomic or
15202 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015203 * must be atomic).
15204 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015205 if ((! WXS_IS_ATOMIC(itemType)) &&
15206 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015207 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015208 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015209 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015210 "The item type '%s' does not have a variety of atomic or union",
15211 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015212 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015213 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015214 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015215 xmlSchemaTypeLinkPtr member;
15216
15217 member = itemType->memberTypes;
15218 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015219 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015220 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015221 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015222 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015223 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015224 "member type '%s' of this item type is not atomic",
15225 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015226 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015227 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15228 }
15229 member = member->next;
15230 }
15231 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015232
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015233 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015234 xmlSchemaFacetPtr facet;
15235 /*
15236 * This is the case if we have: <simpleType><list ..
15237 */
15238 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015239 * 2.3.1
15240 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015241 * contain list.
15242 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015243 if (xmlSchemaTypeFinalContains(itemType,
15244 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15245 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015246 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015247 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015248 "The final of its item type '%s' must not contain 'list'",
15249 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015250 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015251 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15252 }
15253 /*
15254 * 2.3.1.2 The {facets} must only contain the whiteSpace
15255 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015256 * OPTIMIZE TODO: the S4S already disallows any facet
15257 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015258 */
15259 if (type->facets != NULL) {
15260 facet = type->facets;
15261 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015262 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015263 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015264 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015265 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015266 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15267 }
15268 facet = facet->next;
15269 } while (facet != NULL);
15270 }
15271 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015272 * MAYBE TODO: (Hmm, not really) Datatypes states:
15273 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15274 * whose ·lexical space· allows space (such as string or anyURI)or
15275 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015276 * ·lexical space· allows space.
15277 */
15278 } else {
15279 /*
15280 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015281 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015282 */
15283 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015284 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015285 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15286 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015287 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015289 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015290 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015291 "The base type '%s' must be a list type",
15292 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015293 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015294 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15295 }
15296 /*
15297 * 2.3.2.2 The {final} of the {base type definition} must not
15298 * contain restriction.
15299 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015300 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015302 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015303 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015304 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015305 "The 'final' of the base type '%s' must not contain 'restriction'",
15306 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015308 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15309 }
15310 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015311 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015312 * from the {base type definition}'s {item type definition} given
15313 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15314 */
15315 {
15316 xmlSchemaTypePtr baseItemType;
15317
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015318 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015319 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015320 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15321 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015322 return (-1);
15323 }
15324 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015325 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015326 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015327 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015328 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015329 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015330 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015331 "The item type '%s' is not validly derived from "
15332 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015333 xmlSchemaGetComponentQName(&str, itemType),
15334 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15335 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015336
15337 FREE_AND_NULL(str)
15338 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015339 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015340 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15341 }
15342 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015343
Daniel Veillard01fa6152004-06-29 17:04:39 +000015344 if (type->facets != NULL) {
15345 xmlSchemaFacetPtr facet;
15346 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 /*
15348 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015349 * and enumeration facet components are allowed among the {facets}.
15350 */
15351 facet = type->facets;
15352 do {
15353 switch (facet->type) {
15354 case XML_SCHEMA_FACET_LENGTH:
15355 case XML_SCHEMA_FACET_MINLENGTH:
15356 case XML_SCHEMA_FACET_MAXLENGTH:
15357 case XML_SCHEMA_FACET_WHITESPACE:
15358 /*
15359 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015360 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015361 */
15362 case XML_SCHEMA_FACET_PATTERN:
15363 case XML_SCHEMA_FACET_ENUMERATION:
15364 break;
15365 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015366 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015367 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015368 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015369 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015370 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015371 * invalid facets.
15372 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015373 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015374 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015375 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015376 facet = facet->next;
15377 } while (facet != NULL);
15378 if (ok == 0)
15379 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15380 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015381 * SPEC (2.3.2.5) (same as 1.3.2)
15382 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015383 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015384 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015385 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015387 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015388 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015389 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015390 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015391 * atomic or list.
15392 */
15393 xmlSchemaTypeLinkPtr member;
15394
15395 member = type->memberTypes;
15396 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015397 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015398 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015399
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015400 if ((! WXS_IS_ATOMIC(member->type)) &&
15401 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015402 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015403 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015404 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015405 "The member type '%s' is neither an atomic, nor a list type",
15406 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015407 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015408 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15409 }
15410 member = member->next;
15411 }
15412 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015413 * 3.3.1 If the {base type definition} is the ·simple ur-type
15414 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015415 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015416 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015417 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015418 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015419 * {final} which does not contain union.
15420 */
15421 member = type->memberTypes;
15422 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015423 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015425 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015426 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015427 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015428 "The 'final' of member type '%s' contains 'union'",
15429 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015430 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015431 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15432 }
15433 member = member->next;
15434 }
15435 /*
15436 * 3.3.1.2 The {facets} must be empty.
15437 */
15438 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015439 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015440 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015441 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015442 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015443 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15444 }
15445 } else {
15446 /*
15447 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015448 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015449 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015450 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015451 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015452 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015453 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015454 "The base type '%s' is not a union type",
15455 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015456 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015457 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15458 }
15459 /*
15460 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15461 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015462 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015463 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015464 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015465 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015466 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015467 "The 'final' of its base type '%s' must not contain 'restriction'",
15468 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015469 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015470 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15471 }
15472 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015473 * 3.3.2.3 The {member type definitions}, in order, must be validly
15474 * derived from the corresponding type definitions in the {base
15475 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015476 * as defined in Type Derivation OK (Simple) (§3.14.6).
15477 */
15478 {
15479 xmlSchemaTypeLinkPtr baseMember;
15480
15481 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015482 * OPTIMIZE: if the type is restricting, it has no local defined
15483 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015484 * thus a check for equality can be skipped.
15485 */
15486 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015487 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015488 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015489 * types of it's base type. This check seems not necessary with
15490 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015491 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015492 */
15493 if (type->memberTypes != NULL) {
15494 member = type->memberTypes;
15495 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015496 if ((member == NULL) && (baseMember != NULL)) {
15497 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15498 "different number of member types in base");
15499 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015500 while (member != NULL) {
15501 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015502 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15503 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015504 }
15505 if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015506 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015507 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015508 xmlChar *strBMT = NULL, *strBT = NULL;
15509
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015510 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015511 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015512 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015513 "The member type %s is not validly "
15514 "derived from its corresponding member "
15515 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015516 xmlSchemaGetComponentQName(&str, member->type),
15517 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15518 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015519 FREE_AND_NULL(str)
15520 FREE_AND_NULL(strBMT)
15521 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015522 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015523 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015524 member = member->next;
15525 baseMember = baseMember->next;
15526 }
15527 }
15528 }
15529 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015530 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015531 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015532 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015533 if (type->facets != NULL) {
15534 xmlSchemaFacetPtr facet;
15535 int ok = 1;
15536
15537 facet = type->facets;
15538 do {
15539 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15540 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015541 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015542 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015543 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015544 ok = 0;
15545 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015546 facet = facet->next;
15547 } while (facet != NULL);
15548 if (ok == 0)
15549 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015550
Daniel Veillard01fa6152004-06-29 17:04:39 +000015551 }
15552 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015553 * SPEC (3.3.2.5) (same as 1.3.2)
15554 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015555 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015556 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015557 */
15558 }
15559 }
15560
15561 return (0);
15562}
15563
15564/**
15565 * xmlSchemaCheckSRCSimpleType:
15566 * @ctxt: the schema parser context
15567 * @type: the simple type definition
15568 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015569 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015570 *
15571 * Returns 0 if the constraints are satisfied,
15572 * if not a positive error code and -1 on internal
15573 * errors.
15574 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015575#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015576static int
15577xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15578 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015579{
15580 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015581 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015582 * must satisfy the conditions set out in Constraints on Simple Type
15583 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015584 */
15585 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015586 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015587 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015588 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015589 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015590 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015591 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015592 /*
15593 *
15594 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015595 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015596 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015598 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015599 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015600 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015601 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015602 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015603 /*
15604 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015605 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015606 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015607 return (0);
15608}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015609#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015610
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015611static int
15612xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15613{
15614 if (ctxt->vctxt == NULL) {
15615 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15616 if (ctxt->vctxt == NULL) {
15617 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015618 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015619 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015620 "failed to create a temp. validation context.\n",
15621 NULL, NULL);
15622 return (-1);
15623 }
15624 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015625 xmlSchemaSetValidErrors(ctxt->vctxt,
15626 ctxt->error, ctxt->warning, ctxt->userData);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015627 }
15628 return (0);
15629}
15630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015631static int
15632xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15633 xmlNodePtr node,
15634 xmlSchemaTypePtr type,
15635 const xmlChar *value,
15636 xmlSchemaValPtr *retVal,
15637 int fireErrors,
15638 int normalize,
15639 int isNormalized);
15640
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015641/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015642 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015643 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015644 * @type: the simple type definition
15645 * @value: the default value
15646 * @node: an optional node (the holder of the value)
15647 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648 * Schema Component Constraint: Element Default Valid (Immediate)
15649 * (cos-valid-default)
15650 * This will be used by the parser only. For the validator there's
15651 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015652 *
15653 * Returns 0 if the constraints are satisfied,
15654 * if not, a positive error code and -1 on internal
15655 * errors.
15656 */
15657static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015658xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15659 xmlNodePtr node,
15660 xmlSchemaTypePtr type,
15661 const xmlChar *value,
15662 xmlSchemaValPtr *val)
15663{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015664 int ret = 0;
15665
15666 /*
15667 * cos-valid-default:
15668 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015669 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015670 * definition the appropriate case among the following must be true:
15671 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015672 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015673 /*
15674 * Complex type.
15675 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015676 * SPEC (2.1) "its {content type} must be a simple type definition
15677 * or mixed."
15678 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015679 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015680 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015681 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015682 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15683 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015684 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015685 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015686 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015687 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015688 "For a string to be a valid default, the type definition "
15689 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015690 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015691 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15692 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015693 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015694 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015695 * 1 If the type definition is a simple type definition, then the string
15696 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015697 * Valid (§3.14.4).
15698 *
15699 * AND
15700 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 * 2.2.1 If the {content type} is a simple type definition, then the
15702 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015703 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015704 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015705 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015706 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015708 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015709 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015710 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015711 else
15712 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015713
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015714 if (ret < 0) {
15715 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15716 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015717 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015718
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015719 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015720}
15721
15722/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015723 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015724 * @ctxt: the schema parser context
15725 * @type: the complex type definition
15726 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015727 *.(4.6) Constraints on Complex Type Definition Schema Components
15728 * Schema Component Constraint:
15729 * Complex Type Definition Properties Correct (ct-props-correct)
15730 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015731 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015732 * Returns 0 if the constraints are satisfied, a positive
15733 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015734 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015735static int
15736xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15737 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015738{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015739 /*
15740 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15741 *
15742 * SPEC (1) "The values of the properties of a complex type definition must
15743 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015744 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015745 * Sub-components (§5.3)."
15746 */
15747 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015748 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015749 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015750 /*
15751 * SPEC (2) "If the {base type definition} is a simple type definition,
15752 * the {derivation method} must be extension."
15753 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015754 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015755 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015756 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015757 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015758 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015759 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015760 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 /*
15762 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15763 * definition·. That is, it must be possible to reach the ·ur-type
15764 * definition by repeatedly following the {base type definition}."
15765 *
15766 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015767 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015768 /*
15769 * NOTE that (4) and (5) need the following:
15770 * - attribute uses need to be already inherited (apply attr. prohibitions)
15771 * - attribute group references need to be expanded already
15772 * - simple types need to be typefixed already
15773 */
15774 if (type->attrUses &&
15775 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15776 {
15777 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15778 xmlSchemaAttributeUsePtr use, tmp;
15779 int i, j, hasId = 0;
15780
15781 for (i = uses->nbItems -1; i >= 0; i--) {
15782 use = uses->items[i];
15783
15784 /*
15785 * SPEC ct-props-correct
15786 * (4) "Two distinct attribute declarations in the
15787 * {attribute uses} must not have identical {name}s and
15788 * {target namespace}s."
15789 */
15790 if (i > 0) {
15791 for (j = i -1; j >= 0; j--) {
15792 tmp = uses->items[j];
15793 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15794 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15795 (WXS_ATTRUSE_DECL_TNS(use) ==
15796 WXS_ATTRUSE_DECL_TNS(tmp)))
15797 {
15798 xmlChar *str = NULL;
15799
15800 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15801 XML_SCHEMAP_AG_PROPS_CORRECT,
15802 NULL, WXS_BASIC_CAST type,
15803 "Duplicate %s",
15804 xmlSchemaGetComponentDesignation(&str, use),
15805 NULL);
15806 FREE_AND_NULL(str);
15807 /*
15808 * Remove the duplicate.
15809 */
15810 if (xmlSchemaItemListRemove(uses, i) == -1)
15811 goto exit_failure;
15812 goto next_use;
15813 }
15814 }
15815 }
15816 /*
15817 * SPEC ct-props-correct
15818 * (5) "Two distinct attribute declarations in the
15819 * {attribute uses} must not have {type definition}s which
15820 * are or are derived from ID."
15821 */
15822 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15823 if (xmlSchemaIsDerivedFromBuiltInType(
15824 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15825 {
15826 if (hasId) {
15827 xmlChar *str = NULL;
15828
15829 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15830 XML_SCHEMAP_AG_PROPS_CORRECT,
15831 NULL, WXS_BASIC_CAST type,
15832 "There must not exist more than one attribute "
15833 "declaration of type 'xs:ID' "
15834 "(or derived from 'xs:ID'). The %s violates this "
15835 "constraint",
15836 xmlSchemaGetComponentDesignation(&str, use),
15837 NULL);
15838 FREE_AND_NULL(str);
15839 if (xmlSchemaItemListRemove(uses, i) == -1)
15840 goto exit_failure;
15841 }
15842
15843 hasId = 1;
15844 }
15845 }
15846next_use: {}
15847 }
15848 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015849 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015850exit_failure:
15851 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015852}
15853
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015854static int
15855xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15856 xmlSchemaTypePtr typeB)
15857{
15858 /*
15859 * TODO: This should implement component-identity
15860 * in the future.
15861 */
15862 if ((typeA == NULL) || (typeB == NULL))
15863 return (0);
15864 return (typeA == typeB);
15865}
15866
15867/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015868 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015869 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015870 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015871 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015872 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015873 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015874 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015875 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15876 *
15877 * STATUS: completed
15878 *
15879 * Returns 0 if the constraints are satisfied, or 1
15880 * if not.
15881 */
15882static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015883xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015884 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015885 xmlSchemaTypePtr baseType,
15886 int set)
15887{
15888 int equal = xmlSchemaAreEqualTypes(type, baseType);
15889 /* TODO: Error codes. */
15890 /*
15891 * SPEC "For a complex type definition (call it D, for derived)
15892 * to be validly derived from a type definition (call this
15893 * B, for base) given a subset of {extension, restriction}
15894 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015895 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015896 if (! equal) {
15897 /*
15898 * SPEC (1) "If B and D are not the same type definition, then the
15899 * {derivation method} of D must not be in the subset."
15900 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015901 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15902 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015903 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015904 } else {
15905 /*
15906 * SPEC (2.1) "B and D must be the same type definition."
15907 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015908 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015909 }
15910 /*
15911 * SPEC (2.2) "B must be D's {base type definition}."
15912 */
15913 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015914 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015915 /*
15916 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15917 * definition·."
15918 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015919 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015920 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015921
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015922 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015923 /*
15924 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15925 * must be validly derived from B given the subset as defined by this
15926 * constraint."
15927 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015928 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015929 baseType, set));
15930 } else {
15931 /*
15932 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15933 * must be validly derived from B given the subset as defined in Type
15934 * Derivation OK (Simple) (§3.14.6).
15935 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015936 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015937 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015938 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015939}
15940
15941/**
15942 * xmlSchemaCheckCOSDerivedOK:
15943 * @type: the derived simple type definition
15944 * @baseType: the base type definition
15945 *
15946 * Calls:
15947 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015948 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015949 * Checks wheter @type can be validly derived from @baseType.
15950 *
15951 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015952 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015953static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015954xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015955 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015956 xmlSchemaTypePtr baseType,
15957 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015958{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015959 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015960 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015961 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015962 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015963}
15964
William M. Brack2f2a6632004-08-20 23:09:47 +000015965/**
15966 * xmlSchemaCheckCOSCTExtends:
15967 * @ctxt: the schema parser context
15968 * @type: the complex type definition
15969 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015970 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015971 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015972 * Derivation Valid (Extension) (cos-ct-extends)
15973 *
15974 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015975 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015976 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015977 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015978 *
15979 * Returns 0 if the constraints are satisfied, a positive
15980 * error code if not and -1 if an internal error occured.
15981 */
15982static int
15983xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15984 xmlSchemaTypePtr type)
15985{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015986 xmlSchemaTypePtr base = type->baseType;
15987 /*
15988 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15989 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015990 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015991 /*
15992 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 * then all of the following must be true:"
15994 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015995 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015996 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015997 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015998 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015999 */
16000 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16001 xmlSchemaPCustomErr(ctxt,
16002 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016003 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016004 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016005 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016006 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16007 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016008
16009 /*
16010 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16011 * since they are automatically satisfied through the
16012 * inheriting mechanism.
16013 * Note that even if redefining components, the inheriting mechanism
16014 * is used.
16015 */
16016#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016017 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016018 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016019 * uses}
16020 * of the complex type definition itself, that is, for every attribute
16021 * use in the {attribute uses} of the {base type definition}, there
16022 * must be an attribute use in the {attribute uses} of the complex
16023 * type definition itself whose {attribute declaration} has the same
16024 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016025 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016026 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016027 if (base->attrUses != NULL) {
16028 int i, j, found;
16029 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016030
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016031 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16032 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16033 found = 0;
16034 if (type->attrUses != NULL) {
16035 use = (WXS_LIST_CAST type->attrUses)->items[j];
16036 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16037 {
16038 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16039 WXS_ATTRUSE_DECL_NAME(buse)) &&
16040 (WXS_ATTRUSE_DECL_TNS(use) ==
16041 WXS_ATTRUSE_DECL_TNS(buse)) &&
16042 (WXS_ATTRUSE_TYPEDEF(use) ==
16043 WXS_ATTRUSE_TYPEDEF(buse))
16044 {
16045 found = 1;
16046 break;
16047 }
16048 }
16049 }
16050 if (! found) {
16051 xmlChar *str = NULL;
16052
16053 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16054 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16055 NULL, WXS_BASIC_CAST type,
16056 /*
16057 * TODO: The report does not indicate that also the
16058 * type needs to be the same.
16059 */
16060 "This type is missing a matching correspondent "
16061 "for its {base type}'s %s in its {attribute uses}",
16062 xmlSchemaGetComponentDesignation(&str,
16063 buse->children),
16064 NULL);
16065 FREE_AND_NULL(str)
16066 }
16067 }
16068 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016069 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016070 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16071 * definition must also have one, and the base type definition's
16072 * {attribute wildcard}'s {namespace constraint} must be a subset
16073 * of the complex type definition's {attribute wildcard}'s {namespace
16074 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016075 */
16076
16077 /*
16078 * MAYBE TODO: Enable if ever needed. But this will be needed only
16079 * if created the type via a schema construction API.
16080 */
16081 if (base->attributeWildcard != NULL) {
16082 if (type->attributeWilcard == NULL) {
16083 xmlChar *str = NULL;
16084
16085 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16086 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16087 NULL, type,
16088 "The base %s has an attribute wildcard, "
16089 "but this type is missing an attribute wildcard",
16090 xmlSchemaGetComponentDesignation(&str, base));
16091 FREE_AND_NULL(str)
16092
16093 } else if (xmlSchemaCheckCOSNSSubset(
16094 base->attributeWildcard, type->attributeWildcard))
16095 {
16096 xmlChar *str = NULL;
16097
16098 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16099 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16100 NULL, type,
16101 "The attribute wildcard is not a valid "
16102 "superset of the one in the base %s",
16103 xmlSchemaGetComponentDesignation(&str, base));
16104 FREE_AND_NULL(str)
16105 }
16106 }
16107#endif
16108 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016109 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016110 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016111 if ((type->contentTypeDef != NULL) &&
16112 (type->contentTypeDef == base->contentTypeDef)) {
16113 /*
16114 * SPEC (1.4.1) "The {content type} of the {base type definition}
16115 * and the {content type} of the complex type definition itself
16116 * must be the same simple type definition"
16117 * PASS
16118 */
16119 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16120 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16121 /*
16122 * SPEC (1.4.2) "The {content type} of both the {base type
16123 * definition} and the complex type definition itself must
16124 * be empty."
16125 * PASS
16126 */
16127 } else {
16128 /*
16129 * SPEC (1.4.3) "All of the following must be true:"
16130 */
16131 if (type->subtypes == NULL) {
16132 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016133 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 * definition itself must specify a particle.
16135 */
16136 xmlSchemaPCustomErr(ctxt,
16137 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016138 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016139 "The content type must specify a particle", NULL);
16140 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16141 }
16142 /*
16143 * SPEC (1.4.3.2) "One of the following must be true:"
16144 */
16145 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16146 /*
16147 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16148 * definition} must be empty.
16149 * PASS
16150 */
16151 } else {
16152 /*
16153 * SPEC (1.4.3.2.2) "All of the following must be true:"
16154 */
16155 if ((type->contentType != base->contentType) ||
16156 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16157 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16158 /*
16159 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16160 * or both must be element-only."
16161 */
16162 xmlSchemaPCustomErr(ctxt,
16163 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016164 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016165 "The content type of both, the type and its base "
16166 "type, must either 'mixed' or 'element-only'", NULL);
16167 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016170 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 * complex type definition must be a ·valid extension·
16172 * of the {base type definition}'s particle, as defined
16173 * in Particle Valid (Extension) (§3.9.6)."
16174 *
16175 * NOTE that we won't check "Particle Valid (Extension)",
16176 * since it is ensured by the derivation process in
16177 * xmlSchemaTypeFixup(). We need to implement this when heading
16178 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016179 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016180 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016181 }
16182 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016183 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016185 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016186 } else {
16187 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016189 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016190 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016191 if (type->contentTypeDef != base) {
16192 /*
16193 * SPEC (2.1) "The {content type} must be the same simple type
16194 * definition."
16195 */
16196 xmlSchemaPCustomErr(ctxt,
16197 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016198 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016199 "The content type must be the simple base type", NULL);
16200 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16201 }
16202 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16203 /*
16204 * SPEC (2.2) "The {final} of the {base type definition} must not
16205 * contain extension"
16206 * NOTE that this is the same as (1.1).
16207 */
16208 xmlSchemaPCustomErr(ctxt,
16209 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016210 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016211 "The 'final' of the base type definition "
16212 "contains 'extension'", NULL);
16213 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016214 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016215 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016216 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016217}
16218
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016219/**
16220 * xmlSchemaCheckDerivationOKRestriction:
16221 * @ctxt: the schema parser context
16222 * @type: the complex type definition
16223 *
16224 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16227 *
16228 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016229 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016230 * (5.4.2) ???
16231 *
16232 * ATTENTION:
16233 * In XML Schema 1.1 this will be:
16234 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016235 *
16236 * Returns 0 if the constraints are satisfied, a positive
16237 * error code if not and -1 if an internal error occured.
16238 */
16239static int
16240xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16241 xmlSchemaTypePtr type)
16242{
16243 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016244
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016245 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016246 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016248 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016249 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016250 if (! WXS_IS_COMPLEX(base)) {
16251 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16252 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16253 type->node, WXS_BASIC_CAST type,
16254 "The base type must be a complex type", NULL, NULL);
16255 return(ctxt->err);
16256 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16258 /*
16259 * SPEC (1) "The {base type definition} must be a complex type
16260 * definition whose {final} does not contain restriction."
16261 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016262 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16263 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16264 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016265 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016266 "contains 'restriction'", NULL, NULL);
16267 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016268 }
16269 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016270 * SPEC (2), (3) and (4)
16271 * Those are handled in a separate function, since the
16272 * same constraints are needed for redefinition of
16273 * attribute groups as well.
16274 */
16275 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16276 XML_SCHEMA_ACTION_DERIVE,
16277 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16278 type->attrUses, base->attrUses,
16279 type->attributeWildcard,
16280 base->attributeWildcard) == -1)
16281 {
16282 return(-1);
16283 }
16284 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016285 * SPEC (5) "One of the following must be true:"
16286 */
16287 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16288 /*
16289 * SPEC (5.1) "The {base type definition} must be the
16290 * ·ur-type definition·."
16291 * PASS
16292 */
16293 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16294 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16295 /*
16296 * SPEC (5.2.1) "The {content type} of the complex type definition
16297 * must be a simple type definition"
16298 *
16299 * SPEC (5.2.2) "One of the following must be true:"
16300 */
16301 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016302 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16303 {
16304 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016305 /*
16306 * SPEC (5.2.2.1) "The {content type} of the {base type
16307 * definition} must be a simple type definition from which
16308 * the {content type} is validly derived given the empty
16309 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016310 *
16311 * ATTENTION TODO: This seems not needed if the type implicitely
16312 * derived from the base type.
16313 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016314 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016315 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16316 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016317 if (err != 0) {
16318 xmlChar *strA = NULL, *strB = NULL;
16319
16320 if (err == -1)
16321 return(-1);
16322 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16323 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16324 NULL, WXS_BASIC_CAST type,
16325 "The {content type} %s is not validly derived from the "
16326 "base type's {content type} %s",
16327 xmlSchemaGetComponentDesignation(&strA,
16328 type->contentTypeDef),
16329 xmlSchemaGetComponentDesignation(&strB,
16330 base->contentTypeDef));
16331 FREE_AND_NULL(strA);
16332 FREE_AND_NULL(strB);
16333 return(ctxt->err);
16334 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016335 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16336 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016337 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 /*
16339 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16340 * and have a particle which is ·emptiable· as defined in
16341 * Particle Emptiable (§3.9.6)."
16342 * PASS
16343 */
16344 } else {
16345 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016346 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16347 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016348 "The content type of the base type must be either "
16349 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016350 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016351 }
16352 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16353 /*
16354 * SPEC (5.3.1) "The {content type} of the complex type itself must
16355 * be empty"
16356 */
16357 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16358 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016359 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016360 * definition} must also be empty."
16361 * PASS
16362 */
16363 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16364 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16365 xmlSchemaIsParticleEmptiable(
16366 (xmlSchemaParticlePtr) base->subtypes)) {
16367 /*
16368 * SPEC (5.3.2.2) "The {content type} of the {base type
16369 * definition} must be elementOnly or mixed and have a particle
16370 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16371 * PASS
16372 */
16373 } else {
16374 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016375 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16376 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 "The content type of the base type must be either "
16378 "empty or 'mixed' (or 'elements-only') and an emptiable "
16379 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016380 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 }
16382 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016383 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 /*
16385 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16386 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016387 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016388 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016389 /*
16390 * SPEC (5.4.1.2) "The {content type} of the complex type
16391 * definition itself and of the {base type definition} must be
16392 * mixed"
16393 */
16394 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016395 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16396 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016397 "If the content type is 'mixed', then the content type of the "
16398 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016399 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 /*
16402 * SPEC (5.4.2) "The particle of the complex type definition itself
16403 * must be a ·valid restriction· of the particle of the {content
16404 * type} of the {base type definition} as defined in Particle Valid
16405 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016406 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016407 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 } else {
16410 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016411 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16412 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016413 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016414 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016415 }
16416 return (0);
16417}
16418
16419/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016420 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 * @ctxt: the schema parser context
16422 * @type: the complex type definition
16423 *
16424 * (3.4.6) Constraints on Complex Type Definition Schema Components
16425 *
16426 * Returns 0 if the constraints are satisfied, a positive
16427 * error code if not and -1 if an internal error occured.
16428 */
16429static int
16430xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16431 xmlSchemaTypePtr type)
16432{
16433 int ret;
16434 /*
16435 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016436 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016437 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16438 if (ret != 0)
16439 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016440 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016441 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16442 else
16443 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16444 return (ret);
16445}
16446
16447/**
16448 * xmlSchemaCheckSRCCT:
16449 * @ctxt: the schema parser context
16450 * @type: the complex type definition
16451 *
16452 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016453 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016454 * Complex Type Definition Representation OK (src-ct)
16455 *
16456 * Returns 0 if the constraints are satisfied, a positive
16457 * error code if not and -1 if an internal error occured.
16458 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016459static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016460xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016461 xmlSchemaTypePtr type)
16462{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016463 xmlSchemaTypePtr base;
16464 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465
16466 /*
16467 * TODO: Adjust the error codes here, as I used
16468 * XML_SCHEMAP_SRC_CT_1 only yet.
16469 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016470 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016471 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016472 /*
16473 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016474 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016475 * must be a complex type definition;
16476 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016477 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016478 xmlChar *str = NULL;
16479 xmlSchemaPCustomErr(ctxt,
16480 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016481 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016482 "If using <complexContent>, the base type is expected to be "
16483 "a complex type. The base type '%s' is a simple type",
16484 xmlSchemaFormatQName(&str, base->targetNamespace,
16485 base->name));
16486 FREE_AND_NULL(str)
16487 return (XML_SCHEMAP_SRC_CT_1);
16488 }
16489 } else {
16490 /*
16491 * SPEC
16492 * 2 If the <simpleContent> alternative is chosen, all of the
16493 * following must be true:
16494 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16495 * base [attribute] must be one of the following:
16496 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016497 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016498 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016499 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016500 /*
16501 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016502 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016503 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016504 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016505 xmlSchemaPCustomErr(ctxt,
16506 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016507 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016508 "If using <simpleContent> and <restriction>, the base "
16509 "type must be a complex type. The base type '%s' is "
16510 "a simple type",
16511 xmlSchemaFormatQName(&str, base->targetNamespace,
16512 base->name));
16513 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016514 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016515 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016516 } else {
16517 /* Base type is a complex type. */
16518 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16519 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16520 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016521 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016522 * simple type definition;
16523 * PASS
16524 */
16525 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016527 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016529 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016530 type->name);
16531 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016533 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016534 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016535
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016536 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016537 * 2.1.2 only if the <restriction> alternative is also
16538 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 * is mixed and a particle emptiable.
16540 */
16541 if (! xmlSchemaIsParticleEmptiable(
16542 (xmlSchemaParticlePtr) base->subtypes)) {
16543 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016544 } else
16545 /*
16546 * Attention: at this point the <simpleType> child is in
16547 * ->contentTypeDef (put there during parsing).
16548 */
16549 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016550 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016551 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016552 * 2.2 If clause 2.1.2 above is satisfied, then there
16553 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016554 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 /* TODO: Change error code to ..._SRC_CT_2_2. */
16557 xmlSchemaPCustomErr(ctxt,
16558 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016559 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016560 "A <simpleType> is expected among the children "
16561 "of <restriction>, if <simpleContent> is used and "
16562 "the base type '%s' is a complex type",
16563 xmlSchemaFormatQName(&str, base->targetNamespace,
16564 base->name));
16565 FREE_AND_NULL(str)
16566 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016567 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016568 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016569 ret = XML_SCHEMAP_SRC_CT_1;
16570 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016571 }
16572 if (ret > 0) {
16573 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016574 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016575 xmlSchemaPCustomErr(ctxt,
16576 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016577 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016578 "If <simpleContent> and <restriction> is used, the "
16579 "base type must be a simple type or a complex type with "
16580 "mixed content and particle emptiable. The base type "
16581 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016582 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016583 base->name));
16584 } else {
16585 xmlSchemaPCustomErr(ctxt,
16586 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016587 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016588 "If <simpleContent> and <extension> is used, the "
16589 "base type must be a simple type. The base type '%s' "
16590 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016592 base->name));
16593 }
16594 FREE_AND_NULL(str)
16595 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016596 }
16597 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016598 * SPEC (3) "The corresponding complex type definition component must
16599 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016600 * Definition Schema Components (§3.4.6);"
16601 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016602 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016603 /*
16604 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016605 * above for {attribute wildcard} is satisfied, the intensional
16606 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016607 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016608 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016609 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016610 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016611}
William M. Brack2f2a6632004-08-20 23:09:47 +000016612
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016613#ifdef ENABLE_PARTICLE_RESTRICTION
16614/**
16615 * xmlSchemaCheckParticleRangeOK:
16616 * @ctxt: the schema parser context
16617 * @type: the complex type definition
16618 *
16619 * (3.9.6) Constraints on Particle Schema Components
16620 * Schema Component Constraint:
16621 * Occurrence Range OK (range-ok)
16622 *
16623 * STATUS: complete
16624 *
16625 * Returns 0 if the constraints are satisfied, a positive
16626 * error code if not and -1 if an internal error occured.
16627 */
16628static int
16629xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16630 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016631{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016632 if (rmin < bmin)
16633 return (1);
16634 if ((bmax != UNBOUNDED) &&
16635 (rmax > bmax))
16636 return (1);
16637 return (0);
16638}
16639
16640/**
16641 * xmlSchemaCheckRCaseNameAndTypeOK:
16642 * @ctxt: the schema parser context
16643 * @r: the restricting element declaration particle
16644 * @b: the base element declaration particle
16645 *
16646 * (3.9.6) Constraints on Particle Schema Components
16647 * Schema Component Constraint:
16648 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16649 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016650 *
16651 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016652 * MISSING (3.2.3)
16653 * CLARIFY: (3.2.2)
16654 *
16655 * Returns 0 if the constraints are satisfied, a positive
16656 * error code if not and -1 if an internal error occured.
16657 */
16658static int
16659xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16660 xmlSchemaParticlePtr r,
16661 xmlSchemaParticlePtr b)
16662{
16663 xmlSchemaElementPtr elemR, elemB;
16664
16665 /* TODO: Error codes (rcase-NameAndTypeOK). */
16666 elemR = (xmlSchemaElementPtr) r->children;
16667 elemB = (xmlSchemaElementPtr) b->children;
16668 /*
16669 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16670 * the same."
16671 */
16672 if ((elemR != elemB) &&
16673 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16674 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16675 return (1);
16676 /*
16677 * SPEC (2) "R's occurrence range is a valid restriction of B's
16678 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16679 */
16680 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16681 b->minOccurs, b->maxOccurs) != 0)
16682 return (1);
16683 /*
16684 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16685 * {scope} are global."
16686 */
16687 if (elemR == elemB)
16688 return (0);
16689 /*
16690 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16691 */
16692 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16693 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16694 return (1);
16695 /*
16696 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16697 * or is not fixed, or R's declaration's {value constraint} is fixed
16698 * with the same value."
16699 */
16700 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16701 ((elemR->value == NULL) ||
16702 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16703 /* TODO: Equality of the initial value or normalized or canonical? */
16704 (! xmlStrEqual(elemR->value, elemB->value))))
16705 return (1);
16706 /*
16707 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16708 * definitions} is a subset of B's declaration's {identity-constraint
16709 * definitions}, if any."
16710 */
16711 if (elemB->idcs != NULL) {
16712 /* TODO */
16713 }
16714 /*
16715 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16716 * superset of B's declaration's {disallowed substitutions}."
16717 */
16718 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16719 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16720 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16721 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16722 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16723 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16724 return (1);
16725 /*
16726 * SPEC (3.2.5) "R's {type definition} is validly derived given
16727 * {extension, list, union} from B's {type definition}"
16728 *
16729 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16730 * set, if the corresponding constraints handle "restriction" and
16731 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016732 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016733 */
16734 {
16735 int set = 0;
16736
16737 set |= SUBSET_EXTENSION;
16738 set |= SUBSET_LIST;
16739 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016740 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016741 elemB->subtypes, set) != 0)
16742 return (1);
16743 }
16744 return (0);
16745}
16746
16747/**
16748 * xmlSchemaCheckRCaseNSCompat:
16749 * @ctxt: the schema parser context
16750 * @r: the restricting element declaration particle
16751 * @b: the base wildcard particle
16752 *
16753 * (3.9.6) Constraints on Particle Schema Components
16754 * Schema Component Constraint:
16755 * Particle Derivation OK (Elt:Any -- NSCompat)
16756 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016757 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016758 * STATUS: complete
16759 *
16760 * Returns 0 if the constraints are satisfied, a positive
16761 * error code if not and -1 if an internal error occured.
16762 */
16763static int
16764xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16765 xmlSchemaParticlePtr r,
16766 xmlSchemaParticlePtr b)
16767{
16768 /* TODO:Error codes (rcase-NSCompat). */
16769 /*
16770 * SPEC "For an element declaration particle to be a ·valid restriction·
16771 * of a wildcard particle all of the following must be true:"
16772 *
16773 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16774 * with respect to the wildcard's {namespace constraint} as defined by
16775 * Wildcard allows Namespace Name (§3.10.4)."
16776 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016777 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016778 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16779 return (1);
16780 /*
16781 * SPEC (2) "R's occurrence range is a valid restriction of B's
16782 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16783 */
16784 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16785 b->minOccurs, b->maxOccurs) != 0)
16786 return (1);
16787
16788 return (0);
16789}
16790
16791/**
16792 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16793 * @ctxt: the schema parser context
16794 * @r: the restricting element declaration particle
16795 * @b: the base model group particle
16796 *
16797 * (3.9.6) Constraints on Particle Schema Components
16798 * Schema Component Constraint:
16799 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16800 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016801 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016802 * STATUS: TODO
16803 *
16804 * Returns 0 if the constraints are satisfied, a positive
16805 * error code if not and -1 if an internal error occured.
16806 */
16807static int
16808xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16809 xmlSchemaParticlePtr r,
16810 xmlSchemaParticlePtr b)
16811{
16812 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16813 TODO
16814 return (0);
16815}
16816
16817/**
16818 * xmlSchemaCheckRCaseNSSubset:
16819 * @ctxt: the schema parser context
16820 * @r: the restricting wildcard particle
16821 * @b: the base wildcard particle
16822 *
16823 * (3.9.6) Constraints on Particle Schema Components
16824 * Schema Component Constraint:
16825 * Particle Derivation OK (Any:Any -- NSSubset)
16826 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016827 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016828 * STATUS: complete
16829 *
16830 * Returns 0 if the constraints are satisfied, a positive
16831 * error code if not and -1 if an internal error occured.
16832 */
16833static int
16834xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16835 xmlSchemaParticlePtr r,
16836 xmlSchemaParticlePtr b,
16837 int isAnyTypeBase)
16838{
16839 /* TODO: Error codes (rcase-NSSubset). */
16840 /*
16841 * SPEC (1) "R's occurrence range is a valid restriction of B's
16842 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16843 */
16844 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16845 b->minOccurs, b->maxOccurs))
16846 return (1);
16847 /*
16848 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16849 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16850 */
16851 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16852 (xmlSchemaWildcardPtr) b->children))
16853 return (1);
16854 /*
16855 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16856 * definition·, R's {process contents} must be identical to or stronger
16857 * than B's {process contents}, where strict is stronger than lax is
16858 * stronger than skip."
16859 */
16860 if (! isAnyTypeBase) {
16861 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16862 ((xmlSchemaWildcardPtr) b->children)->processContents)
16863 return (1);
16864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016865
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016866 return (0);
16867}
16868
16869/**
16870 * xmlSchemaCheckCOSParticleRestrict:
16871 * @ctxt: the schema parser context
16872 * @type: the complex type definition
16873 *
16874 * (3.9.6) Constraints on Particle Schema Components
16875 * Schema Component Constraint:
16876 * Particle Valid (Restriction) (cos-particle-restrict)
16877 *
16878 * STATUS: TODO
16879 *
16880 * Returns 0 if the constraints are satisfied, a positive
16881 * error code if not and -1 if an internal error occured.
16882 */
16883static int
16884xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16885 xmlSchemaParticlePtr r,
16886 xmlSchemaParticlePtr b)
16887{
16888 int ret = 0;
16889
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016890 /*part = WXS_TYPE_PARTICLE(type);
16891 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016892 */
16893
16894 TODO
16895
16896 /*
16897 * SPEC (1) "They are the same particle."
16898 */
16899 if (r == b)
16900 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016901
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016902
16903 return (0);
16904}
16905
16906/**
16907 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16908 * @ctxt: the schema parser context
16909 * @r: the model group particle
16910 * @b: the base wildcard particle
16911 *
16912 * (3.9.6) Constraints on Particle Schema Components
16913 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016914 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016915 * NSRecurseCheckCardinality)
16916 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016917 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016918 * STATUS: TODO: subst-groups
16919 *
16920 * Returns 0 if the constraints are satisfied, a positive
16921 * error code if not and -1 if an internal error occured.
16922 */
16923static int
16924xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16925 xmlSchemaParticlePtr r,
16926 xmlSchemaParticlePtr b)
16927{
16928 xmlSchemaParticlePtr part;
16929 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16930 if ((r->children == NULL) || (r->children->children == NULL))
16931 return (-1);
16932 /*
16933 * SPEC "For a group particle to be a ·valid restriction· of a
16934 * wildcard particle..."
16935 *
16936 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016937 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016938 * Particle Valid (Restriction) (§3.9.6)."
16939 */
16940 part = (xmlSchemaParticlePtr) r->children->children;
16941 do {
16942 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16943 return (1);
16944 part = (xmlSchemaParticlePtr) part->next;
16945 } while (part != NULL);
16946 /*
16947 * SPEC (2) "The effective total range of the group [...] is a
16948 * valid restriction of B's occurrence range as defined by
16949 * Occurrence Range OK (§3.9.6)."
16950 */
16951 if (xmlSchemaCheckParticleRangeOK(
16952 xmlSchemaGetParticleTotalRangeMin(r),
16953 xmlSchemaGetParticleTotalRangeMax(r),
16954 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016955 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016956 return (0);
16957}
16958
16959/**
16960 * xmlSchemaCheckRCaseRecurse:
16961 * @ctxt: the schema parser context
16962 * @r: the <all> or <sequence> model group particle
16963 * @b: the base <all> or <sequence> model group particle
16964 *
16965 * (3.9.6) Constraints on Particle Schema Components
16966 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016967 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016968 Recurse)
16969 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016970 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016971 * STATUS: ?
16972 * TODO: subst-groups
16973 *
16974 * Returns 0 if the constraints are satisfied, a positive
16975 * error code if not and -1 if an internal error occured.
16976 */
16977static int
16978xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16979 xmlSchemaParticlePtr r,
16980 xmlSchemaParticlePtr b)
16981{
16982 /* xmlSchemaParticlePtr part; */
16983 /* TODO: Error codes (rcase-Recurse). */
16984 if ((r->children == NULL) || (b->children == NULL) ||
16985 (r->children->type != b->children->type))
16986 return (-1);
16987 /*
16988 * SPEC "For an all or sequence group particle to be a ·valid
16989 * restriction· of another group particle with the same {compositor}..."
16990 *
16991 * SPEC (1) "R's occurrence range is a valid restriction of B's
16992 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16993 */
16994 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16995 b->minOccurs, b->maxOccurs))
16996 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016997
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016998
16999 return (0);
17000}
17001
17002#endif
17003
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017004#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17005 xmlSchemaPCustomErrExt(pctxt, \
17006 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017007 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017008 "It is an error for both '%s' and '%s' to be specified on the "\
17009 "same type definition", \
17010 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17011 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17012
17013#define FACET_RESTR_ERR(fac1, msg) \
17014 xmlSchemaPCustomErr(pctxt, \
17015 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017016 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017017 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017018
17019#define FACET_RESTR_FIXED_ERR(fac) \
17020 xmlSchemaPCustomErr(pctxt, \
17021 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017022 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017023 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017024 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017025
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017026static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017027xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17028 xmlSchemaFacetPtr facet1,
17029 xmlSchemaFacetPtr facet2,
17030 int lessGreater,
17031 int orEqual,
17032 int ofBase)
17033{
17034 xmlChar *msg = NULL;
17035
17036 msg = xmlStrdup(BAD_CAST "'");
17037 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17038 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17039 if (lessGreater == 0)
17040 msg = xmlStrcat(msg, BAD_CAST " equal to");
17041 if (lessGreater == 1)
17042 msg = xmlStrcat(msg, BAD_CAST " greater than");
17043 else
17044 msg = xmlStrcat(msg, BAD_CAST " less than");
17045
17046 if (orEqual)
17047 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17048 msg = xmlStrcat(msg, BAD_CAST " '");
17049 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17050 if (ofBase)
17051 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17052 else
17053 msg = xmlStrcat(msg, BAD_CAST "'");
17054
17055 xmlSchemaPCustomErr(pctxt,
17056 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017057 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017058 (const char *) msg, NULL);
17059
17060 if (msg != NULL)
17061 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017062}
17063
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017064/*
17065* xmlSchemaDeriveAndValidateFacets:
17066*
17067* Schema Component Constraint: Simple Type Restriction (Facets)
17068* (st-restrict-facets)
17069*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017070static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017071xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17072 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017073{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017074 xmlSchemaTypePtr base = type->baseType;
17075 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017076 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017077 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17078 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17079 fmininc = NULL, fmaxinc = NULL,
17080 fminexc = NULL, fmaxexc = NULL,
17081 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17082 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17083 bfmininc = NULL, bfmaxinc = NULL,
17084 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017085 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017086
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017087 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017088 * SPEC st-restrict-facets 1:
17089 * "The {variety} of R is the same as that of B."
17090 */
17091 /*
17092 * SPEC st-restrict-facets 2:
17093 * "If {variety} is atomic, the {primitive type definition}
17094 * of R is the same as that of B."
17095 *
17096 * NOTE: we leave 1 & 2 out for now, since this will be
17097 * satisfied by the derivation process.
17098 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17099 */
17100 /*
17101 * SPEC st-restrict-facets 3:
17102 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017103 * of B, eliminating duplicates. To eliminate duplicates,
17104 * when a facet of the same kind occurs in both S and the
17105 * {facets} of B, the one in the {facets} of B is not
17106 * included, with the exception of enumeration and pattern
17107 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017108 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017109 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017111 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17112 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017113
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017114 last = type->facetSet;
17115 if (last != NULL)
17116 while (last->next != NULL)
17117 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017118
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017119 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17120 facet = cur->facet;
17121 switch (facet->type) {
17122 case XML_SCHEMA_FACET_LENGTH:
17123 flength = facet; break;
17124 case XML_SCHEMA_FACET_MINLENGTH:
17125 fminlen = facet; break;
17126 case XML_SCHEMA_FACET_MININCLUSIVE:
17127 fmininc = facet; break;
17128 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17129 fminexc = facet; break;
17130 case XML_SCHEMA_FACET_MAXLENGTH:
17131 fmaxlen = facet; break;
17132 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17133 fmaxinc = facet; break;
17134 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17135 fmaxexc = facet; break;
17136 case XML_SCHEMA_FACET_TOTALDIGITS:
17137 ftotdig = facet; break;
17138 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17139 ffracdig = facet; break;
17140 default:
17141 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017142 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017143 }
17144 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17145 facet = cur->facet;
17146 switch (facet->type) {
17147 case XML_SCHEMA_FACET_LENGTH:
17148 bflength = facet; break;
17149 case XML_SCHEMA_FACET_MINLENGTH:
17150 bfminlen = facet; break;
17151 case XML_SCHEMA_FACET_MININCLUSIVE:
17152 bfmininc = facet; break;
17153 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17154 bfminexc = facet; break;
17155 case XML_SCHEMA_FACET_MAXLENGTH:
17156 bfmaxlen = facet; break;
17157 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17158 bfmaxinc = facet; break;
17159 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17160 bfmaxexc = facet; break;
17161 case XML_SCHEMA_FACET_TOTALDIGITS:
17162 bftotdig = facet; break;
17163 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17164 bffracdig = facet; break;
17165 default:
17166 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017167 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017168 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017169 /*
17170 * length and minLength or maxLength (2.2) + (3.2)
17171 */
17172 if (flength && (fminlen || fmaxlen)) {
17173 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17174 "either of 'minLength' or 'maxLength' to be specified on "
17175 "the same type definition")
17176 }
17177 /*
17178 * Mutual exclusions in the same derivation step.
17179 */
17180 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017181 /*
17182 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017183 */
17184 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17185 }
17186 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017187 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017188 * SCC "minInclusive and minExclusive"
17189 */
17190 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017191 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017192
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017193 if (flength && bflength) {
17194 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017195 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017196 * The values have to be equal.
17197 */
17198 res = xmlSchemaCompareValues(flength->val, bflength->val);
17199 if (res == -2)
17200 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017201 if (res != 0)
17202 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17203 if ((res != 0) && (bflength->fixed)) {
17204 FACET_RESTR_FIXED_ERR(flength)
17205 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017207 }
17208 if (fminlen && bfminlen) {
17209 /*
17210 * SCC "minLength valid restriction"
17211 * minLength >= BASE minLength
17212 */
17213 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17214 if (res == -2)
17215 goto internal_error;
17216 if (res == -1)
17217 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17218 if ((res != 0) && (bfminlen->fixed)) {
17219 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017220 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017221 }
17222 if (fmaxlen && bfmaxlen) {
17223 /*
17224 * SCC "maxLength valid restriction"
17225 * maxLength <= BASE minLength
17226 */
17227 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17228 if (res == -2)
17229 goto internal_error;
17230 if (res == 1)
17231 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17232 if ((res != 0) && (bfmaxlen->fixed)) {
17233 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017234 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017235 }
17236 /*
17237 * SCC "length and minLength or maxLength"
17238 */
17239 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017240 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017241 if (flength) {
17242 if (! fminlen)
17243 flength = bflength;
17244 if (fminlen) {
17245 /* (1.1) length >= minLength */
17246 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17247 if (res == -2)
17248 goto internal_error;
17249 if (res == -1)
17250 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17251 }
17252 if (! fmaxlen)
17253 fmaxlen = bfmaxlen;
17254 if (fmaxlen) {
17255 /* (2.1) length <= maxLength */
17256 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17257 if (res == -2)
17258 goto internal_error;
17259 if (res == 1)
17260 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17261 }
17262 }
17263 if (fmaxinc) {
17264 /*
17265 * "maxInclusive"
17266 */
17267 if (fmininc) {
17268 /* SCC "maxInclusive >= minInclusive" */
17269 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17270 if (res == -2)
17271 goto internal_error;
17272 if (res == -1) {
17273 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17274 }
17275 }
17276 /*
17277 * SCC "maxInclusive valid restriction"
17278 */
17279 if (bfmaxinc) {
17280 /* maxInclusive <= BASE maxInclusive */
17281 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17282 if (res == -2)
17283 goto internal_error;
17284 if (res == 1)
17285 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17286 if ((res != 0) && (bfmaxinc->fixed)) {
17287 FACET_RESTR_FIXED_ERR(fmaxinc)
17288 }
17289 }
17290 if (bfmaxexc) {
17291 /* maxInclusive < BASE maxExclusive */
17292 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17293 if (res == -2)
17294 goto internal_error;
17295 if (res != -1) {
17296 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17297 }
17298 }
17299 if (bfmininc) {
17300 /* maxInclusive >= BASE minInclusive */
17301 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17302 if (res == -2)
17303 goto internal_error;
17304 if (res == -1) {
17305 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17306 }
17307 }
17308 if (bfminexc) {
17309 /* maxInclusive > BASE minExclusive */
17310 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17311 if (res == -2)
17312 goto internal_error;
17313 if (res != 1) {
17314 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17315 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017316 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017317 }
17318 if (fmaxexc) {
17319 /*
17320 * "maxExclusive >= minExclusive"
17321 */
17322 if (fminexc) {
17323 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17324 if (res == -2)
17325 goto internal_error;
17326 if (res == -1) {
17327 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17328 }
17329 }
17330 /*
17331 * "maxExclusive valid restriction"
17332 */
17333 if (bfmaxexc) {
17334 /* maxExclusive <= BASE maxExclusive */
17335 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17336 if (res == -2)
17337 goto internal_error;
17338 if (res == 1) {
17339 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17340 }
17341 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017342 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017343 }
17344 }
17345 if (bfmaxinc) {
17346 /* maxExclusive <= BASE maxInclusive */
17347 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17348 if (res == -2)
17349 goto internal_error;
17350 if (res == 1) {
17351 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17352 }
17353 }
17354 if (bfmininc) {
17355 /* maxExclusive > BASE minInclusive */
17356 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17357 if (res == -2)
17358 goto internal_error;
17359 if (res != 1) {
17360 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17361 }
17362 }
17363 if (bfminexc) {
17364 /* maxExclusive > BASE minExclusive */
17365 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17366 if (res == -2)
17367 goto internal_error;
17368 if (res != 1) {
17369 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17370 }
17371 }
17372 }
17373 if (fminexc) {
17374 /*
17375 * "minExclusive < maxInclusive"
17376 */
17377 if (fmaxinc) {
17378 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17379 if (res == -2)
17380 goto internal_error;
17381 if (res != -1) {
17382 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17383 }
17384 }
17385 /*
17386 * "minExclusive valid restriction"
17387 */
17388 if (bfminexc) {
17389 /* minExclusive >= BASE minExclusive */
17390 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17391 if (res == -2)
17392 goto internal_error;
17393 if (res == -1) {
17394 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17395 }
17396 if ((res != 0) && (bfminexc->fixed)) {
17397 FACET_RESTR_FIXED_ERR(fminexc)
17398 }
17399 }
17400 if (bfmaxinc) {
17401 /* minExclusive <= BASE maxInclusive */
17402 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17403 if (res == -2)
17404 goto internal_error;
17405 if (res == 1) {
17406 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17407 }
17408 }
17409 if (bfmininc) {
17410 /* minExclusive >= BASE minInclusive */
17411 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17412 if (res == -2)
17413 goto internal_error;
17414 if (res == -1) {
17415 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17416 }
17417 }
17418 if (bfmaxexc) {
17419 /* minExclusive < BASE maxExclusive */
17420 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17421 if (res == -2)
17422 goto internal_error;
17423 if (res != -1) {
17424 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17425 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017426 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017427 }
17428 if (fmininc) {
17429 /*
17430 * "minInclusive < maxExclusive"
17431 */
17432 if (fmaxexc) {
17433 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17434 if (res == -2)
17435 goto internal_error;
17436 if (res != -1) {
17437 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17438 }
17439 }
17440 /*
17441 * "minExclusive valid restriction"
17442 */
17443 if (bfmininc) {
17444 /* minInclusive >= BASE minInclusive */
17445 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17446 if (res == -2)
17447 goto internal_error;
17448 if (res == -1) {
17449 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17450 }
17451 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017452 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017453 }
17454 }
17455 if (bfmaxinc) {
17456 /* minInclusive <= BASE maxInclusive */
17457 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17458 if (res == -2)
17459 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017460 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017461 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17462 }
17463 }
17464 if (bfminexc) {
17465 /* minInclusive > BASE minExclusive */
17466 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17467 if (res == -2)
17468 goto internal_error;
17469 if (res != 1)
17470 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17471 }
17472 if (bfmaxexc) {
17473 /* minInclusive < BASE maxExclusive */
17474 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17475 if (res == -2)
17476 goto internal_error;
17477 if (res != -1)
17478 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17479 }
17480 }
17481 if (ftotdig && bftotdig) {
17482 /*
17483 * SCC " totalDigits valid restriction"
17484 * totalDigits <= BASE totalDigits
17485 */
17486 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17487 if (res == -2)
17488 goto internal_error;
17489 if (res == 1)
17490 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17491 -1, 1, 1);
17492 if ((res != 0) && (bftotdig->fixed)) {
17493 FACET_RESTR_FIXED_ERR(ftotdig)
17494 }
17495 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017496 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017497 /*
17498 * SCC "fractionDigits valid restriction"
17499 * fractionDigits <= BASE fractionDigits
17500 */
17501 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17502 if (res == -2)
17503 goto internal_error;
17504 if (res == 1)
17505 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17506 -1, 1, 1);
17507 if ((res != 0) && (bffracdig->fixed)) {
17508 FACET_RESTR_FIXED_ERR(ffracdig)
17509 }
17510 }
17511 /*
17512 * SCC "fractionDigits less than or equal to totalDigits"
17513 */
17514 if (! ftotdig)
17515 ftotdig = bftotdig;
17516 if (! ffracdig)
17517 ffracdig = bffracdig;
17518 if (ftotdig && ffracdig) {
17519 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17520 if (res == -2)
17521 goto internal_error;
17522 if (res == 1)
17523 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17524 -1, 1, 0);
17525 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017526 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017527 * *Enumerations* won' be added here, since only the first set
17528 * of enumerations in the ancestor-or-self axis is used
17529 * for validation, plus we need to use the base type of those
17530 * enumerations for whitespace.
17531 *
17532 * *Patterns*: won't be add here, since they are ORed at
17533 * type level and ANDed at ancestor level. This will
17534 * happed during validation by walking the base axis
17535 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017536 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017537 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17538 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017539 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017540 * Special handling of enumerations and patterns.
17541 * TODO: hmm, they should not appear in the set, so remove this.
17542 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017543 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017544 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017545 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017546 /*
17547 * Search for a duplicate facet in the current type.
17548 */
17549 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017550 /* err = 0; */
17551 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017552 while (link != NULL) {
17553 facet = link->facet;
17554 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017555 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017556 case XML_SCHEMA_FACET_WHITESPACE:
17557 /*
17558 * The whitespace must be stronger.
17559 */
17560 if (facet->whitespace < bfacet->whitespace) {
17561 FACET_RESTR_ERR(flength,
17562 "The 'whitespace' value has to be equal to "
17563 "or stronger than the 'whitespace' value of "
17564 "the base type")
17565 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017566 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017567 (facet->whitespace != bfacet->whitespace)) {
17568 FACET_RESTR_FIXED_ERR(facet)
17569 }
17570 break;
17571 default:
17572 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017574 /* Duplicate found. */
17575 break;
17576 }
17577 link = link->next;
17578 }
17579 /*
17580 * If no duplicate was found: add the base types's facet
17581 * to the set.
17582 */
17583 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017584 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017585 xmlMalloc(sizeof(xmlSchemaFacetLink));
17586 if (link == NULL) {
17587 xmlSchemaPErrMemory(pctxt,
17588 "deriving facets, creating a facet link", NULL);
17589 return (-1);
17590 }
17591 link->facet = cur->facet;
17592 link->next = NULL;
17593 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017594 type->facetSet = link;
17595 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017596 last->next = link;
17597 last = link;
17598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017599
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017600 }
17601
17602 return (0);
17603internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017604 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17605 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017606 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017607}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017608
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017609static int
17610xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17611 xmlSchemaTypePtr type)
17612{
17613 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17614 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017615 * The actual value is then formed by replacing any union type
17616 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017617 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017618 *
17619 * TODO: There's a bug entry at
17620 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17621 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017622 */
17623 link = type->memberTypes;
17624 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017625
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017626 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017627 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017628
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017629 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017630 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017632 link->type = subLink->type;
17633 if (subLink->next != NULL) {
17634 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017635 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017636 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 while (subLink != NULL) {
17638 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017639 xmlMalloc(sizeof(xmlSchemaTypeLink));
17640 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017641 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017642 NULL);
17643 return (-1);
17644 }
17645 newLink->type = subLink->type;
17646 prevLink->next = newLink;
17647 prevLink = newLink;
17648 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017649
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017650 subLink = subLink->next;
17651 }
17652 }
17653 }
17654 }
17655 link = link->next;
17656 }
17657 return (0);
17658}
17659
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017660static void
17661xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17662{
17663 int has = 0, needVal = 0, normVal = 0;
17664
17665 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17666 if (has) {
17667 needVal = (type->baseType->flags &
17668 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17669 normVal = (type->baseType->flags &
17670 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17671 }
17672 if (type->facets != NULL) {
17673 xmlSchemaFacetPtr fac;
17674
17675 for (fac = type->facets; fac != NULL; fac = fac->next) {
17676 switch (fac->type) {
17677 case XML_SCHEMA_FACET_WHITESPACE:
17678 break;
17679 case XML_SCHEMA_FACET_PATTERN:
17680 normVal = 1;
17681 has = 1;
17682 break;
17683 case XML_SCHEMA_FACET_ENUMERATION:
17684 needVal = 1;
17685 normVal = 1;
17686 has = 1;
17687 break;
17688 default:
17689 has = 1;
17690 break;
17691 }
17692 }
17693 }
17694 if (normVal)
17695 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17696 if (needVal)
17697 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17698 if (has)
17699 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17700
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017701 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017702 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17703 /*
17704 * OPTIMIZE VAL TODO: Some facets need a computed value.
17705 */
17706 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17707 (prim->builtInType != XML_SCHEMAS_STRING)) {
17708 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17709 }
17710 }
17711}
17712
17713static int
17714xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17715{
17716
17717
17718 /*
17719 * Evaluate the whitespace-facet value.
17720 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017721 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017722 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17723 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017724 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017725 return (0);
17726
17727 if (type->facetSet != NULL) {
17728 xmlSchemaFacetLinkPtr lin;
17729
17730 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17731 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17732 switch (lin->facet->whitespace) {
17733 case XML_SCHEMAS_FACET_PRESERVE:
17734 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17735 break;
17736 case XML_SCHEMAS_FACET_REPLACE:
17737 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17738 break;
17739 case XML_SCHEMAS_FACET_COLLAPSE:
17740 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17741 break;
17742 default:
17743 return (-1);
17744 }
17745 return (0);
17746 }
17747 }
17748 }
17749 /*
17750 * For all ·atomic· datatypes other than string (and types ·derived·
17751 * by ·restriction· from it) the value of whiteSpace is fixed to
17752 * collapse
17753 */
17754 {
17755 xmlSchemaTypePtr anc;
17756
17757 for (anc = type->baseType; anc != NULL &&
17758 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17759 anc = anc->baseType) {
17760
17761 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17762 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17763 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17764
17765 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17766 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17767 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17768
17769 } else
17770 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17771 break;
17772 }
17773 }
17774 return (0);
17775 }
17776 return (0);
17777}
17778
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017779static int
17780xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17781 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017782{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017783 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17784 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017785 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017786 return(0);
17787 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017788
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017789 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017790 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017791 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017792 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017793 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017794 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017795 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017796 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017797 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017798 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017799 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017800 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017801 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017802 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017803 * Corresponds to <simpleType><union>...
17804 */
17805 if (type->memberTypes == NULL) {
17806 /*
17807 * This one is really needed, so get out.
17808 */
17809 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17810 "union type has no member-types assigned");
17811 return(-1);
17812 }
17813 } else {
17814 /*
17815 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017816 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017817 if (type->baseType == NULL) {
17818 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17819 "type has no base-type assigned");
17820 return(-1);
17821 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017822 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017823 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17824 return(-1);
17825 /*
17826 * Variety
17827 * If the <restriction> alternative is chosen, then the
17828 * {variety} of the {base type definition}.
17829 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017830 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017831 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017832 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017833 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017834 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017835 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017836 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017837 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017838 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017839 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017840 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017841 * NOTE that we won't assign the memberTypes of the base,
17842 * since this will make trouble when freeing them; we will
17843 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017845 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017846 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017847 return(0);
17848}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017849
Daniel Veillard8651f532002-04-17 09:06:27 +000017850#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017851xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17852 xmlSchemaTypePtr type)
17853{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017854 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017855 xmlGenericError(xmlGenericErrorContext,
17856 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017857 type->node->doc->URL,
17858 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017859 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017860 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017861 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017862 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017863 switch (type->contentType) {
17864 case XML_SCHEMA_CONTENT_SIMPLE:
17865 xmlGenericError(xmlGenericErrorContext, "simple\n");
17866 break;
17867 case XML_SCHEMA_CONTENT_ELEMENTS:
17868 xmlGenericError(xmlGenericErrorContext, "elements\n");
17869 break;
17870 case XML_SCHEMA_CONTENT_UNKNOWN:
17871 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17872 break;
17873 case XML_SCHEMA_CONTENT_EMPTY:
17874 xmlGenericError(xmlGenericErrorContext, "empty\n");
17875 break;
17876 case XML_SCHEMA_CONTENT_MIXED:
17877 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017878 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017879 xmlGenericError(xmlGenericErrorContext,
17880 "mixed as emptiable particle\n");
17881 else
17882 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17883 break;
17884 /* Removed, since not used. */
17885 /*
17886 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17887 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17888 break;
17889 */
17890 case XML_SCHEMA_CONTENT_BASIC:
17891 xmlGenericError(xmlGenericErrorContext, "basic\n");
17892 break;
17893 default:
17894 xmlGenericError(xmlGenericErrorContext,
17895 "not registered !!!\n");
17896 break;
17897 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017898 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017899}
Daniel Veillard8651f532002-04-17 09:06:27 +000017900#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017901
17902/*
17903* 3.14.6 Constraints on Simple Type Definition Schema Components
17904*/
17905static int
17906xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17907 xmlSchemaTypePtr type)
17908{
17909 int res, olderrs = pctxt->nberrors;
17910
17911 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17912 return(-1);
17913
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017914 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017915 return(0);
17916
17917 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17918 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17919
17920 if (type->baseType == NULL) {
17921 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17922 "missing baseType");
17923 goto exit_failure;
17924 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017925 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017926 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017927 /*
17928 * If a member type of a union is a union itself, we need to substitute
17929 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017930 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17931 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017932 */
17933 if ((type->memberTypes != NULL) &&
17934 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17935 return(-1);
17936 /*
17937 * SPEC src-simple-type 1
17938 * "The corresponding simple type definition, if any, must satisfy
17939 * the conditions set out in Constraints on Simple Type Definition
17940 * Schema Components (§3.14.6)."
17941 */
17942 /*
17943 * Schema Component Constraint: Simple Type Definition Properties Correct
17944 * (st-props-correct)
17945 */
17946 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17947 HFAILURE HERROR
17948 /*
17949 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17950 * (cos-st-restricts)
17951 */
17952 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17953 HFAILURE HERROR
17954 /*
17955 * TODO: Removed the error report, since it got annoying to get an
17956 * extra error report, if anything failed until now.
17957 * Enable this if needed.
17958 *
17959 * xmlSchemaPErr(ctxt, type->node,
17960 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17961 * "Simple type '%s' does not satisfy the constraints "
17962 * "on simple type definitions.\n",
17963 * type->name, NULL);
17964 */
17965 /*
17966 * Schema Component Constraint: Simple Type Restriction (Facets)
17967 * (st-restrict-facets)
17968 */
17969 res = xmlSchemaCheckFacetValues(type, pctxt);
17970 HFAILURE HERROR
17971 if ((type->facetSet != NULL) ||
17972 (type->baseType->facetSet != NULL)) {
17973 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17974 HFAILURE HERROR
17975 }
17976 /*
17977 * Whitespace value.
17978 */
17979 res = xmlSchemaTypeFixupWhitespace(type);
17980 HFAILURE HERROR
17981 xmlSchemaTypeFixupOptimFacets(type);
17982
17983exit_error:
17984#ifdef DEBUG_TYPE
17985 xmlSchemaDebugFixedType(pctxt, type);
17986#endif
17987 if (olderrs != pctxt->nberrors)
17988 return(pctxt->err);
17989 return(0);
17990
17991exit_failure:
17992#ifdef DEBUG_TYPE
17993 xmlSchemaDebugFixedType(pctxt, type);
17994#endif
17995 return(-1);
17996}
17997
17998static int
17999xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18000 xmlSchemaTypePtr type)
18001{
18002 int res = 0, olderrs = pctxt->nberrors;
18003 xmlSchemaTypePtr baseType = type->baseType;
18004
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018005 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018006 return(0);
18007 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18008 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018009 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018010 "missing baseType");
18011 goto exit_failure;
18012 }
18013 /*
18014 * Fixup the base type.
18015 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018016 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018017 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018018 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18019 /*
18020 * Skip fixup if the base type is invalid.
18021 * TODO: Generate a warning!
18022 */
18023 return(0);
18024 }
18025 /*
18026 * This basically checks if the base type can be derived.
18027 */
18028 res = xmlSchemaCheckSRCCT(pctxt, type);
18029 HFAILURE HERROR
18030 /*
18031 * Fixup the content type.
18032 */
18033 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18034 /*
18035 * Corresponds to <complexType><simpleContent>...
18036 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018037 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018038 (baseType->contentTypeDef != NULL) &&
18039 (WXS_IS_RESTRICTION(type))) {
18040 xmlSchemaTypePtr contentBase, content;
18041#ifdef ENABLE_NAMED_LOCALS
18042 char buf[30];
18043 const xmlChar *tmpname;
18044#endif
18045 /*
18046 * SPEC (1) If <restriction> + base type is <complexType>,
18047 * "whose own {content type} is a simple type..."
18048 */
18049 if (type->contentTypeDef != NULL) {
18050 /*
18051 * SPEC (1.1) "the simple type definition corresponding to the
18052 * <simpleType> among the [children] of <restriction> if there
18053 * is one;"
18054 * Note that this "<simpleType> among the [children]" was put
18055 * into ->contentTypeDef during parsing.
18056 */
18057 contentBase = type->contentTypeDef;
18058 type->contentTypeDef = NULL;
18059 } else {
18060 /*
18061 * (1.2) "...otherwise (<restriction> has no <simpleType>
18062 * among its [children]), the simple type definition which
18063 * is the {content type} of the ... base type."
18064 */
18065 contentBase = baseType->contentTypeDef;
18066 }
18067 /*
18068 * SPEC
18069 * "... a simple type definition which restricts the simple
18070 * type definition identified in clause 1.1 or clause 1.2
18071 * with a set of facet components"
18072 *
18073 * Create the anonymous simple type, which will be the content
18074 * type of the complex type.
18075 */
18076#ifdef ENABLE_NAMED_LOCALS
18077 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18078 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018079 content = xmlSchemaAddType(pctxt, pctxt->schema,
18080 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018081 type->node, 0);
18082#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018083 content = xmlSchemaAddType(pctxt, pctxt->schema,
18084 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018085 type->node, 0);
18086#endif
18087 if (content == NULL)
18088 goto exit_failure;
18089 /*
18090 * We will use the same node as for the <complexType>
18091 * to have it somehow anchored in the schema doc.
18092 */
18093 content->type = XML_SCHEMA_TYPE_SIMPLE;
18094 content->baseType = contentBase;
18095 /*
18096 * Move the facets, previously anchored on the
18097 * complexType during parsing.
18098 */
18099 content->facets = type->facets;
18100 type->facets = NULL;
18101 content->facetSet = type->facetSet;
18102 type->facetSet = NULL;
18103
18104 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018105 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018106 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018107 /*
18108 * Fixup the newly created type. We don't need to check
18109 * for circularity here.
18110 */
18111 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18112 HFAILURE HERROR
18113 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18114 HFAILURE HERROR
18115
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018116 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018117 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18118 (WXS_IS_RESTRICTION(type))) {
18119 /*
18120 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18121 * an emptiable particle, then a simple type definition which
18122 * restricts the <restriction>'s <simpleType> child.
18123 */
18124 if ((type->contentTypeDef == NULL) ||
18125 (type->contentTypeDef->baseType == NULL)) {
18126 /*
18127 * TODO: Check if this ever happens.
18128 */
18129 xmlSchemaPCustomErr(pctxt,
18130 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018131 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018132 "Internal error: xmlSchemaTypeFixup, "
18133 "complex type '%s': the <simpleContent><restriction> "
18134 "is missing a <simpleType> child, but was not catched "
18135 "by xmlSchemaCheckSRCCT()", type->name);
18136 goto exit_failure;
18137 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018138 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018139 /*
18140 * SPEC (3) If <extension> + base is <complexType> with
18141 * <simpleType> content, "...then the {content type} of that
18142 * complex type definition"
18143 */
18144 if (baseType->contentTypeDef == NULL) {
18145 /*
18146 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18147 * should have catched this already.
18148 */
18149 xmlSchemaPCustomErr(pctxt,
18150 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018151 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018152 "Internal error: xmlSchemaTypeFixup, "
18153 "complex type '%s': the <extension>ed base type is "
18154 "a complex type with no simple content type",
18155 type->name);
18156 goto exit_failure;
18157 }
18158 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018159 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018160 /*
18161 * SPEC (4) <extension> + base is <simpleType>
18162 * "... then that simple type definition"
18163 */
18164 type->contentTypeDef = baseType;
18165 } else {
18166 /*
18167 * TODO: Check if this ever happens.
18168 */
18169 xmlSchemaPCustomErr(pctxt,
18170 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018171 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018172 "Internal error: xmlSchemaTypeFixup, "
18173 "complex type '%s' with <simpleContent>: unhandled "
18174 "derivation case", type->name);
18175 goto exit_failure;
18176 }
18177 } else {
18178 int dummySequence = 0;
18179 xmlSchemaParticlePtr particle =
18180 (xmlSchemaParticlePtr) type->subtypes;
18181 /*
18182 * Corresponds to <complexType><complexContent>...
18183 *
18184 * NOTE that the effective mixed was already set during parsing of
18185 * <complexType> and <complexContent>; its flag value is
18186 * XML_SCHEMAS_TYPE_MIXED.
18187 *
18188 * Compute the "effective content":
18189 * (2.1.1) + (2.1.2) + (2.1.3)
18190 */
18191 if ((particle == NULL) ||
18192 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18193 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18194 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18195 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18196 (particle->minOccurs == 0))) &&
18197 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18198 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18199 /*
18200 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18201 * a particle whose properties are as follows:..."
18202 *
18203 * Empty sequence model group with
18204 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18205 * NOTE that we sill assign it the <complexType> node to
18206 * somehow anchor it in the doc.
18207 */
18208 if ((particle == NULL) ||
18209 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18210 /*
18211 * Create the particle.
18212 */
18213 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18214 type->node, 1, 1);
18215 if (particle == NULL)
18216 goto exit_failure;
18217 /*
18218 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018219 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018220 particle->children = (xmlSchemaTreeItemPtr)
18221 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18222 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18223 if (particle->children == NULL)
18224 goto exit_failure;
18225
18226 type->subtypes = (xmlSchemaTypePtr) particle;
18227 }
18228 dummySequence = 1;
18229 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18230 } else {
18231 /*
18232 * SPEC (2.1.5) "otherwise empty"
18233 */
18234 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18235 }
18236 } else {
18237 /*
18238 * SPEC (2.2) "otherwise the particle corresponding to the
18239 * <all>, <choice>, <group> or <sequence> among the
18240 * [children]."
18241 */
18242 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18243 }
18244 /*
18245 * Compute the "content type".
18246 */
18247 if (WXS_IS_RESTRICTION(type)) {
18248 /*
18249 * SPEC (3.1) "If <restriction>..."
18250 * (3.1.1) + (3.1.2) */
18251 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18252 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18253 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18254 }
18255 } else {
18256 /*
18257 * SPEC (3.2) "If <extension>..."
18258 */
18259 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18260 /*
18261 * SPEC (3.2.1)
18262 */
18263 type->contentType = baseType->contentType;
18264 type->subtypes = baseType->subtypes;
18265 /*
18266 * NOTE that the effective mixed is ignored here.
18267 */
18268 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18269 /*
18270 * SPEC (3.2.2)
18271 */
18272 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18273 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18274 } else {
18275 /*
18276 * SPEC (3.2.3)
18277 */
18278 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18279 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18280 /*
18281 * "A model group whose {compositor} is sequence and whose
18282 * {particles} are..."
18283 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018284 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18285 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18286 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18287 XML_SCHEMA_TYPE_ALL))
18288 {
18289 /*
18290 * SPEC cos-all-limited (1)
18291 */
18292 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18293 /* TODO: error code */
18294 XML_SCHEMAP_COS_ALL_LIMITED,
18295 WXS_ITEM_NODE(type), NULL,
18296 "The type has an 'all' model group in its "
18297 "{content type} and thus cannot be derived from "
18298 "a non-empty type, since this would produce a "
18299 "'sequence' model group containing the 'all' "
18300 "model group; 'all' model groups are not "
18301 "allowed to appear inside other model groups",
18302 NULL, NULL);
18303
18304 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18305 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18306 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18307 XML_SCHEMA_TYPE_ALL))
18308 {
18309 /*
18310 * SPEC cos-all-limited (1)
18311 */
18312 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18313 /* TODO: error code */
18314 XML_SCHEMAP_COS_ALL_LIMITED,
18315 WXS_ITEM_NODE(type), NULL,
18316 "A type cannot be derived by extension from a type "
18317 "which has an 'all' model group in its "
18318 "{content type}, since this would produce a "
18319 "'sequence' model group containing the 'all' "
18320 "model group; 'all' model groups are not "
18321 "allowed to appear inside other model groups",
18322 NULL, NULL);
18323
18324 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018325 xmlSchemaTreeItemPtr effectiveContent =
18326 (xmlSchemaTreeItemPtr) type->subtypes;
18327 /*
18328 * Create the particle.
18329 */
18330 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18331 type->node, 1, 1);
18332 if (particle == NULL)
18333 goto exit_failure;
18334 /*
18335 * Create the "sequence" model group.
18336 */
18337 particle->children = (xmlSchemaTreeItemPtr)
18338 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18339 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18340 if (particle->children == NULL)
18341 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018342 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018343 /*
18344 * SPEC "the particle of the {content type} of
18345 * the ... base ..."
18346 * Create a duplicate of the base type's particle
18347 * and assign its "term" to it.
18348 */
18349 particle->children->children =
18350 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18351 pctxt->schema, type->node,
18352 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18353 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18354 if (particle->children->children == NULL)
18355 goto exit_failure;
18356 particle = (xmlSchemaParticlePtr)
18357 particle->children->children;
18358 particle->children =
18359 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18360 /*
18361 * SPEC "followed by the ·effective content·."
18362 */
18363 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018364 /*
18365 * This all will result in:
18366 * new-particle
18367 * --> new-sequence(
18368 * new-particle
18369 * --> base-model,
18370 * this-particle
18371 * --> this-model
18372 * )
18373 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018374 } else {
18375 /*
18376 * This is the case when there is already an empty
18377 * <sequence> with minOccurs==maxOccurs==1.
18378 * Just add the base types's content type.
18379 * NOTE that, although we miss to add an intermediate
18380 * <sequence>, this should produce no difference to
18381 * neither the regex compilation of the content model,
18382 * nor to the complex type contraints.
18383 */
18384 particle->children->children =
18385 (xmlSchemaTreeItemPtr) baseType->subtypes;
18386 }
18387 }
18388 }
18389 }
18390 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018391 * Now fixup attribute uses:
18392 * - expand attr. group references
18393 * - intersect attribute wildcards
18394 * - inherit attribute uses of the base type
18395 * - inherit or union attr. wildcards if extending
18396 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018397 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018398 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018399 HFAILURE HERROR
18400 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018401 * Apply the complex type component constraints; this will not
18402 * check attributes, since this is done in
18403 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018404 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018405 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018406 HFAILURE HERROR
18407
18408#ifdef DEBUG_TYPE
18409 xmlSchemaDebugFixedType(pctxt, type);
18410#endif
18411 if (olderrs != pctxt->nberrors)
18412 return(pctxt->err);
18413 else
18414 return(0);
18415
18416exit_error:
18417 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18418#ifdef DEBUG_TYPE
18419 xmlSchemaDebugFixedType(pctxt, type);
18420#endif
18421 return(pctxt->err);
18422
18423exit_failure:
18424 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18425#ifdef DEBUG_TYPE
18426 xmlSchemaDebugFixedType(pctxt, type);
18427#endif
18428 return(-1);
18429}
18430
18431
18432/**
18433 * xmlSchemaTypeFixup:
18434 * @typeDecl: the schema type definition
18435 * @ctxt: the schema parser context
18436 *
18437 * Fixes the content model of the type.
18438 * URGENT TODO: We need an int result!
18439 */
18440static int
18441xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018442 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018443{
18444 if (type == NULL)
18445 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018446 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18447 AERROR_INT("xmlSchemaTypeFixup",
18448 "this function needs a parser context");
18449 return(-1);
18450 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018451 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018452 return(0);
18453 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018454 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018455 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018456 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018457 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018458}
18459
18460/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018461 * xmlSchemaCheckFacet:
18462 * @facet: the facet
18463 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018464 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018465 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018466 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018467 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018468 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018469 * Returns 0 if valid, a positive error code if not valid and
18470 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018471 */
18472int
18473xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018474 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018475 xmlSchemaParserCtxtPtr pctxt,
18476 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018477{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018478 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018479
Daniel Veillardce682bc2004-11-05 17:22:25 +000018480 if ((facet == NULL) || (typeDecl == NULL))
18481 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018482 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018483 * TODO: will the parser context be given if used from
18484 * the relaxNG module?
18485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018486 if (pctxt == NULL)
18487 ctxtGiven = 0;
18488 else
18489 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018490
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018491 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018492 case XML_SCHEMA_FACET_MININCLUSIVE:
18493 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18494 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018495 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18496 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018497 /*
18498 * Okay we need to validate the value
18499 * at that point.
18500 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018501 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018502
18503 /* 4.3.5.5 Constraints on enumeration Schema Components
18504 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018505 * It is an ·error· if any member of {value} is not in the
18506 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018507 *
18508 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018509 * The value ·must· be in the
18510 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018511 */
18512 /*
18513 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018514 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018516 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018517 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018518 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018520 */
18521 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18522 base = typeDecl->baseType;
18523 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018524 PERROR_INT("xmlSchemaCheckFacet",
18525 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018526 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018527 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018528 } else
18529 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018530
18531 if (! ctxtGiven) {
18532 /*
18533 * A context is needed if called from RelaxNG.
18534 */
18535 pctxt = xmlSchemaNewParserCtxt("*");
18536 if (pctxt == NULL)
18537 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018539 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018540 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018541 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018542 * facet->node is just the node holding the facet
18543 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018544 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018545 */
18546 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018547 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 facet->value, &(facet->val), 1, 1, 0);
18549 if (ret != 0) {
18550 if (ret < 0) {
18551 /* No error message for RelaxNG. */
18552 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018553 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018554 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18555 "Internal error: xmlSchemaCheckFacet, "
18556 "failed to validate the value '%s' of the "
18557 "facet '%s' against the base type",
18558 facet->value, xmlSchemaFacetTypeToString(facet->type));
18559 }
18560 goto internal_error;
18561 }
18562 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18563 /* No error message for RelaxNG. */
18564 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018565 xmlChar *str = NULL;
18566
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018567 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018568 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018569 "The value '%s' of the facet does not validate "
18570 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 facet->value,
18572 xmlSchemaFormatQName(&str,
18573 base->targetNamespace, base->name));
18574 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018575 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018576 goto exit;
18577 } else if (facet->val == NULL) {
18578 if (ctxtGiven) {
18579 PERROR_INT("xmlSchemaCheckFacet",
18580 "value was not computed");
18581 }
18582 TODO
18583 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018584 break;
18585 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018586 case XML_SCHEMA_FACET_PATTERN:
18587 facet->regexp = xmlRegexpCompile(facet->value);
18588 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018589 ret = XML_SCHEMAP_REGEXP_INVALID;
18590 /* No error message for RelaxNG. */
18591 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018592 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018593 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018594 "The value '%s' of the facet 'pattern' is not a "
18595 "valid regular expression",
18596 facet->value, NULL);
18597 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018598 }
18599 break;
18600 case XML_SCHEMA_FACET_TOTALDIGITS:
18601 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18602 case XML_SCHEMA_FACET_LENGTH:
18603 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018604 case XML_SCHEMA_FACET_MINLENGTH:
18605
18606 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18607 ret = xmlSchemaValidatePredefinedType(
18608 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18609 facet->value, &(facet->val));
18610 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 ret = xmlSchemaValidatePredefinedType(
18612 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18613 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018614 }
18615 if (ret != 0) {
18616 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018617 /* No error message for RelaxNG. */
18618 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018619 PERROR_INT("xmlSchemaCheckFacet",
18620 "validating facet value");
18621 }
18622 goto internal_error;
18623 }
18624 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18625 /* No error message for RelaxNG. */
18626 if (ctxtGiven) {
18627 /* error code */
18628 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18629 ret, facet->node, WXS_BASIC_CAST typeDecl,
18630 "The value '%s' of the facet '%s' is not a valid '%s'",
18631 facet->value,
18632 xmlSchemaFacetTypeToString(facet->type),
18633 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18634 BAD_CAST "nonNegativeInteger" :
18635 BAD_CAST "positiveInteger",
18636 NULL);
18637 }
18638 }
18639 break;
18640
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018641 case XML_SCHEMA_FACET_WHITESPACE:{
18642 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18643 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18644 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18645 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18646 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18647 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18648 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018649 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18650 /* No error message for RelaxNG. */
18651 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018652 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018653 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018654 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018655 "The value '%s' of the facet 'whitespace' is not "
18656 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018657 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018658 }
18659 }
18660 default:
18661 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018662 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018663exit:
18664 if ((! ctxtGiven) && (pctxt != NULL))
18665 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018666 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018667internal_error:
18668 if ((! ctxtGiven) && (pctxt != NULL))
18669 xmlSchemaFreeParserCtxt(pctxt);
18670 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018671}
18672
18673/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018674 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018675 * @typeDecl: the schema type definition
18676 * @ctxt: the schema parser context
18677 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018678 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018679 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018680static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018681xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018682 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018683{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018684 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018685 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018686 /*
18687 * NOTE: It is intended to use the facets list, instead
18688 * of facetSet.
18689 */
18690 if (typeDecl->facets != NULL) {
18691 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018693 /*
18694 * Temporarily assign the "schema" to the validation context
18695 * of the parser context. This is needed for NOTATION validation.
18696 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018697 if (pctxt->vctxt == NULL) {
18698 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18699 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018700 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018701 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018702 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018703 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18704 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018705 facet = facet->next;
18706 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018707 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018708 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018709 if (olderrs != pctxt->nberrors)
18710 return(pctxt->err);
18711 return(0);
18712exit_failure:
18713 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018714}
18715
18716/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018717 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018718 * @ctxtMGroup: the searched model group
18719 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018720 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018721 *
18722 * This one is intended to be used by
18723 * xmlSchemaCheckGroupDefCircular only.
18724 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018725 * Returns the particle with the circular model group definition reference,
18726 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018728static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018729xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018730 xmlSchemaTreeItemPtr particle)
18731{
18732 xmlSchemaTreeItemPtr circ = NULL;
18733 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018734 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018735
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018736 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018737 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018738 if (term == NULL)
18739 continue;
18740 switch (term->type) {
18741 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018742 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018743 if (gdef == groupDef)
18744 return (particle);
18745 /*
18746 * Mark this model group definition to avoid infinite
18747 * recursion on circular references not yet examined.
18748 */
18749 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18750 continue;
18751 if (gdef->children != NULL) {
18752 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18753 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18754 gdef->children->children);
18755 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18756 if (circ != NULL)
18757 return (circ);
18758 }
18759 break;
18760 case XML_SCHEMA_TYPE_SEQUENCE:
18761 case XML_SCHEMA_TYPE_CHOICE:
18762 case XML_SCHEMA_TYPE_ALL:
18763 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18764 if (circ != NULL)
18765 return (circ);
18766 break;
18767 default:
18768 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018769 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018770 }
18771 return (NULL);
18772}
18773
18774/**
18775 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018776 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018777 * @ctxt: the parser context
18778 * @name: the name
18779 *
18780 * Checks for circular references to model group definitions.
18781 */
18782static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018783xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018784 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018785{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018786 /*
18787 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018788 * 2 Circular groups are disallowed. That is, within the {particles}
18789 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018790 * is the group itself.
18791 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018792 if ((item == NULL) ||
18793 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18794 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018795 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018796 {
18797 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018798
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018799 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018800 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018801 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018802 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018803 * TODO: The error report is not adequate: this constraint
18804 * is defined for model groups but not definitions, but since
18805 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018806 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018807 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018808 */
18809 xmlSchemaPCustomErr(ctxt,
18810 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018811 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018812 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018813 "defined", xmlSchemaFormatQName(&str,
18814 item->targetNamespace, item->name));
18815 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018816 /*
18817 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018818 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018819 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018820 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018821 }
18822 }
18823}
18824
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018825/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018826 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018827 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018828 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018829 *
18830 * Assigns the model group of model group definitions to the "term"
18831 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018832 * In xmlSchemaResolveModelGroupParticleReferences the model group
18833 * definitions were assigned to the "term", since needed for the
18834 * circularity check.
18835 *
18836 * Schema Component Constraint:
18837 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018838 */
18839static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018840xmlSchemaModelGroupToModelGroupDefFixup(
18841 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18842 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018843{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018844 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18845
18846 while (particle != NULL) {
18847 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18848 ((WXS_PARTICLE_TERM(particle))->type !=
18849 XML_SCHEMA_TYPE_GROUP))
18850 {
18851 particle = WXS_PTC_CAST particle->next;
18852 continue;
18853 }
18854 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18855 /*
18856 * TODO: Remove the particle.
18857 */
18858 WXS_PARTICLE_TERM(particle) = NULL;
18859 particle = WXS_PTC_CAST particle->next;
18860 continue;
18861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018862 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018863 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018864 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018865 WXS_PARTICLE_TERM(particle) =
18866 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18867
18868 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018869 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018870}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018871
18872/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018873 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018874 * @ctxtGr: the searched attribute group
18875 * @attr: the current attribute list to be processed
18876 *
18877 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018878 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018879 *
18880 * Returns the circular attribute grou reference, otherwise NULL.
18881 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018882static xmlSchemaQNameRefPtr
18883xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18884 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018885{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018886 xmlSchemaAttributeGroupPtr gr;
18887 xmlSchemaQNameRefPtr ref, circ;
18888 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018889 /*
18890 * We will search for an attribute group reference which
18891 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018892 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018893 for (i = 0; i < list->nbItems; i++) {
18894 ref = list->items[i];
18895 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18896 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18897 (ref->item != NULL))
18898 {
18899 gr = WXS_ATTR_GROUP_CAST ref->item;
18900 if (gr == ctxtGr)
18901 return(ref);
18902 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18903 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018904 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018905 * Mark as visited to avoid infinite recursion on
18906 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018907 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018908 if ((gr->attrUses) &&
18909 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18910 {
18911 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18912 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18913 (xmlSchemaItemListPtr) gr->attrUses);
18914 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18915 if (circ != NULL)
18916 return (circ);
18917 }
18918
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018919 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018920 }
18921 return (NULL);
18922}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018923
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018924/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018925 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018926 * attrGr: the attribute group definition
18927 * @ctxt: the parser context
18928 * @name: the name
18929 *
18930 * Checks for circular references of attribute groups.
18931 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018932static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018933xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018934 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018935{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018936 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018937 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018938 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018939 * 3 Circular group reference is disallowed outside <redefine>.
18940 * That is, unless this element information item's parent is
18941 * <redefine>, then among the [children], if any, there must
18942 * not be an <attributeGroup> with ref [attribute] which resolves
18943 * to the component corresponding to this <attributeGroup>. Indirect
18944 * circularity is also ruled out. That is, when QName resolution
18945 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18946 * any <attributeGroup>s with a ref [attribute] among the [children],
18947 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018948 * which resolves to the component corresponding to this <attributeGroup>.
18949 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018950 if (attrGr->attrUses == NULL)
18951 return(0);
18952 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18953 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018954 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018955 xmlSchemaQNameRefPtr circ;
18956
18957 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18958 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018959 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018960 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018961 /*
18962 * TODO: Report the referenced attr group as QName.
18963 */
18964 xmlSchemaPCustomErr(ctxt,
18965 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018966 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018967 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018968 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18969 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018970 /*
18971 * NOTE: We will cut the reference to avoid further
18972 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018973 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018974 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018975 circ->item = NULL;
18976 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018977 }
18978 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018979 return(0);
18980}
18981
18982static int
18983xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18984 xmlSchemaAttributeGroupPtr attrGr);
18985
18986/**
18987 * xmlSchemaExpandAttributeGroupRefs:
18988 * @pctxt: the parser context
18989 * @node: the node of the component holding the attribute uses
18990 * @completeWild: the intersected wildcard to be returned
18991 * @list: the attribute uses
18992 *
18993 * Substitutes contained attribute group references
18994 * for their attribute uses. Wilcards are intersected.
18995 * Attribute use prohibitions are removed from the list
18996 * and returned via the @prohibs list.
18997 * Pointlessness of attr. prohibs, if a matching attr. decl
18998 * is existent a well, are checked.
18999 */
19000static int
19001xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19002 xmlSchemaBasicItemPtr item,
19003 xmlSchemaWildcardPtr *completeWild,
19004 xmlSchemaItemListPtr list,
19005 xmlSchemaItemListPtr prohibs)
19006{
19007 xmlSchemaAttributeGroupPtr gr;
19008 xmlSchemaAttributeUsePtr use;
19009 xmlSchemaItemListPtr sublist;
19010 int i, j;
19011 int created = (*completeWild == NULL) ? 0 : 1;
19012
19013 if (prohibs)
19014 prohibs->nbItems = 0;
19015
19016 for (i = 0; i < list->nbItems; i++) {
19017 use = list->items[i];
19018
19019 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19020 if (prohibs == NULL) {
19021 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19022 "unexpected attr prohibition found");
19023 return(-1);
19024 }
19025 /*
19026 * Remove from attribute uses.
19027 */
19028 if (xmlSchemaItemListRemove(list, i) == -1)
19029 return(-1);
19030 i--;
19031 /*
19032 * Note that duplicate prohibitions were already
19033 * handled at parsing time.
19034 */
19035 /*
19036 * Add to list of prohibitions.
19037 */
19038 xmlSchemaItemListAddSize(prohibs, 2, use);
19039 continue;
19040 }
19041 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19042 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19043 {
19044 if ((WXS_QNAME_CAST use)->item == NULL)
19045 return(-1);
19046 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19047 /*
19048 * Expand the referenced attr. group.
19049 * TODO: remove this, this is done in a previous step, so
19050 * already done here.
19051 */
19052 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19053 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19054 return(-1);
19055 }
19056 /*
19057 * Build the 'complete' wildcard; i.e. intersect multiple
19058 * wildcards.
19059 */
19060 if (gr->attributeWildcard != NULL) {
19061 if (*completeWild == NULL) {
19062 *completeWild = gr->attributeWildcard;
19063 } else {
19064 if (! created) {
19065 xmlSchemaWildcardPtr tmpWild;
19066
19067 /*
19068 * Copy the first encountered wildcard as context,
19069 * except for the annotation.
19070 *
19071 * Although the complete wildcard might not correspond
19072 * to any node in the schema, we will anchor it on
19073 * the node of the owner component.
19074 */
19075 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19076 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19077 WXS_ITEM_NODE(item));
19078 if (tmpWild == NULL)
19079 return(-1);
19080 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19081 tmpWild, *completeWild) == -1)
19082 return (-1);
19083 tmpWild->processContents = (*completeWild)->processContents;
19084 *completeWild = tmpWild;
19085 created = 1;
19086 }
19087
19088 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19089 gr->attributeWildcard) == -1)
19090 return(-1);
19091 }
19092 }
19093 /*
19094 * Just remove the reference if the referenced group does not
19095 * contain any attribute uses.
19096 */
19097 if (gr->attrUses == NULL) {
19098 if (xmlSchemaItemListRemove(list, i) == -1)
19099 return(-1);
19100 i--;
19101 continue;
19102 }
19103 /*
19104 * Add the attribute uses.
19105 */
19106 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19107 if (sublist->nbItems != 0) {
19108 list->items[i] = sublist->items[0];
19109 if (sublist->nbItems != 1) {
19110 for (j = 1; j < sublist->nbItems; j++) {
19111 i++;
19112 if (xmlSchemaItemListInsert(list,
19113 sublist->items[j], i) == -1)
19114 return(-1);
19115 }
19116 }
19117 }
19118 }
19119
19120 }
19121 /*
19122 * Handle pointless prohibitions of declared attributes.
19123 */
19124 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19125 xmlSchemaAttributeUseProhibPtr prohib;
19126
19127 for (i = prohibs->nbItems -1; i >= 0; i--) {
19128 prohib = prohibs->items[i];
19129 for (j = 0; j < list->nbItems; j++) {
19130 use = list->items[j];
19131
19132 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19133 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19134 {
19135 xmlChar *str = NULL;
19136
19137 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19138 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19139 prohib->node, NULL,
19140 "Skipping pointless attribute use prohibition "
19141 "'%s', since a corresponding attribute use "
19142 "exists already in the type definition",
19143 xmlSchemaFormatQName(&str,
19144 prohib->targetNamespace, prohib->name),
19145 NULL, NULL);
19146 FREE_AND_NULL(str);
19147 /*
19148 * Remove the prohibition.
19149 */
19150 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19151 return(-1);
19152 break;
19153 }
19154 }
19155 }
19156 }
19157 return(0);
19158}
19159
19160/**
19161 * xmlSchemaAttributeGroupExpandRefs:
19162 * @pctxt: the parser context
19163 * @attrGr: the attribute group definition
19164 *
19165 * Computation of:
19166 * {attribute uses} property
19167 * {attribute wildcard} property
19168 *
19169 * Substitutes contained attribute group references
19170 * for their attribute uses. Wilcards are intersected.
19171 */
19172static int
19173xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19174 xmlSchemaAttributeGroupPtr attrGr)
19175{
19176 if ((attrGr->attrUses == NULL) ||
19177 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19178 return(0);
19179
19180 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19181 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19182 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19183 return(-1);
19184 return(0);
19185}
19186
19187/**
19188 * xmlSchemaAttributeGroupExpandRefs:
19189 * @pctxt: the parser context
19190 * @attrGr: the attribute group definition
19191 *
19192 * Substitutes contained attribute group references
19193 * for their attribute uses. Wilcards are intersected.
19194 *
19195 * Schema Component Constraint:
19196 * Attribute Group Definition Properties Correct (ag-props-correct)
19197 */
19198static int
19199xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19200 xmlSchemaAttributeGroupPtr attrGr)
19201{
19202 /*
19203 * SPEC ag-props-correct
19204 * (1) "The values of the properties of an attribute group definition
19205 * must be as described in the property tableau in The Attribute
19206 * Group Definition Schema Component (§3.6.1), modulo the impact of
19207 * Missing Sub-components (§5.3);"
19208 */
19209
19210 if ((attrGr->attrUses != NULL) &&
19211 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19212 {
19213 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19214 xmlSchemaAttributeUsePtr use, tmp;
19215 int i, j, hasId = 0;
19216
19217 for (i = uses->nbItems -1; i >= 0; i--) {
19218 use = uses->items[i];
19219 /*
19220 * SPEC ag-props-correct
19221 * (2) "Two distinct members of the {attribute uses} must not have
19222 * {attribute declaration}s both of whose {name}s match and whose
19223 * {target namespace}s are identical."
19224 */
19225 if (i > 0) {
19226 for (j = i -1; j >= 0; j--) {
19227 tmp = uses->items[j];
19228 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19229 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19230 (WXS_ATTRUSE_DECL_TNS(use) ==
19231 WXS_ATTRUSE_DECL_TNS(tmp)))
19232 {
19233 xmlChar *str = NULL;
19234
19235 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19236 XML_SCHEMAP_AG_PROPS_CORRECT,
19237 attrGr->node, WXS_BASIC_CAST attrGr,
19238 "Duplicate %s",
19239 xmlSchemaGetComponentDesignation(&str, use),
19240 NULL);
19241 FREE_AND_NULL(str);
19242 /*
19243 * Remove the duplicate.
19244 */
19245 if (xmlSchemaItemListRemove(uses, i) == -1)
19246 return(-1);
19247 goto next_use;
19248 }
19249 }
19250 }
19251 /*
19252 * SPEC ag-props-correct
19253 * (3) "Two distinct members of the {attribute uses} must not have
19254 * {attribute declaration}s both of whose {type definition}s are or
19255 * are derived from ID."
19256 * TODO: Does 'derived' include member-types of unions?
19257 */
19258 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19259 if (xmlSchemaIsDerivedFromBuiltInType(
19260 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19261 {
19262 if (hasId) {
19263 xmlChar *str = NULL;
19264
19265 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19266 XML_SCHEMAP_AG_PROPS_CORRECT,
19267 attrGr->node, WXS_BASIC_CAST attrGr,
19268 "There must not exist more than one attribute "
19269 "declaration of type 'xs:ID' "
19270 "(or derived from 'xs:ID'). The %s violates this "
19271 "constraint",
19272 xmlSchemaGetComponentDesignation(&str, use),
19273 NULL);
19274 FREE_AND_NULL(str);
19275 if (xmlSchemaItemListRemove(uses, i) == -1)
19276 return(-1);
19277 }
19278 hasId = 1;
19279 }
19280 }
19281next_use: {}
19282 }
19283 }
19284 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019285}
19286
19287/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019288 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019289 * @attrgrpDecl: the schema attribute definition
19290 * @ctxt: the schema parser context
19291 * @name: the attribute name
19292 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019293 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019294 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019295static int
19296xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19297 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019298{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019299 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019300
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019301 if (ref->item != NULL)
19302 return(0);
19303 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19304 ref->name,
19305 ref->targetNamespace);
19306 if (group == NULL) {
19307 xmlSchemaPResCompAttrErr(ctxt,
19308 XML_SCHEMAP_SRC_RESOLVE,
19309 NULL, ref->node,
19310 "ref", ref->name, ref->targetNamespace,
19311 ref->itemType, NULL);
19312 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019313 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019314 ref->item = WXS_BASIC_CAST group;
19315 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019316}
19317
19318/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019319 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019320 * @item: an schema attribute declaration/use
19321 * @ctxt: a schema parser context
19322 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019323 *
19324 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019325 * Schema Component Constraint:
19326 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019327 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019328 * Validates the value constraints of an attribute declaration/use.
19329 * NOTE that this needs the simle type definitions to be already
19330 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019331 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019332static int
19333xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19334 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019335{
19336
19337 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019338 * SPEC a-props-correct (1)
19339 * "The values of the properties of an attribute declaration must
19340 * be as described in the property tableau in The Attribute
19341 * Declaration Schema Component (§3.2.1), modulo the impact of
19342 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019343 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019344
19345 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19346 return(0);
19347
19348 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019349 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019350
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019351 /*
19352 * SPEC a-props-correct (3)
19353 * "If the {type definition} is or is derived from ID then there
19354 * must not be a {value constraint}."
19355 */
19356 if (xmlSchemaIsDerivedFromBuiltInType(
19357 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19358 {
19359 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360 XML_SCHEMAP_A_PROPS_CORRECT_3,
19361 NULL, WXS_BASIC_CAST attr,
19362 "Value constraints are not allowed if the type definition "
19363 "is or is derived from xs:ID",
19364 NULL, NULL);
19365 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019366 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019367 /*
19368 * SPEC a-props-correct (2)
19369 * "if there is a {value constraint}, the canonical lexical
19370 * representation of its value must be ·valid· with respect
19371 * to the {type definition} as defined in String Valid (§3.14.4)."
19372 * TODO: Don't care about the *cononical* stuff here, this requirement
19373 * will be removed in WXS 1.1 anyway.
19374 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019375 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019376 attr->node, WXS_ATTR_TYPEDEF(attr),
19377 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019378 1, 1, 0);
19379 if (ret != 0) {
19380 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019381 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019382 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019383 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019384 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019385 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019386 XML_SCHEMAP_A_PROPS_CORRECT_2,
19387 NULL, WXS_BASIC_CAST attr,
19388 "The value of the value constraint is not valid",
19389 NULL, NULL);
19390 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019391 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019392 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019393
19394 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019395}
19396
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019397static xmlSchemaElementPtr
19398xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19399 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019400{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019401 xmlSchemaElementPtr ret;
19402
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019403 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019404 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019405 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019406 return (ancestor);
19407
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019408 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019409 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019410 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019411 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019412 WXS_SUBST_HEAD(ancestor));
19413 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019414
19415 return (ret);
19416}
19417
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019418/**
19419 * xmlSchemaCheckElemPropsCorrect:
19420 * @ctxt: a schema parser context
19421 * @decl: the element declaration
19422 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019423 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019424 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019425 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019426 *
19427 * STATUS:
19428 * missing: (6)
19429 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019430static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019431xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19432 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019433{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019434 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019435 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019436 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019437 * SPEC (1) "The values of the properties of an element declaration
19438 * must be as described in the property tableau in The Element
19439 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19440 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019441 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019442 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19443 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019444
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019445 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019446 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019447 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019448 * affiliation}, then {scope} must be global."
19449 */
19450 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19451 xmlSchemaPCustomErr(pctxt,
19452 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019453 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019454 "Only global element declarations can have a "
19455 "substitution group affiliation", NULL);
19456 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019457 }
19458 /*
19459 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19460 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019461 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019462 * property."
19463 */
19464 if (head == elemDecl)
19465 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019466 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019467 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19468 else
19469 circ = NULL;
19470 if (circ != NULL) {
19471 xmlChar *strA = NULL, *strB = NULL;
19472
19473 xmlSchemaPCustomErrExt(pctxt,
19474 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019475 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019476 "The element declaration '%s' defines a circular "
19477 "substitution group to element declaration '%s'",
19478 xmlSchemaGetComponentQName(&strA, circ),
19479 xmlSchemaGetComponentQName(&strB, head),
19480 NULL);
19481 FREE_AND_NULL(strA)
19482 FREE_AND_NULL(strB)
19483 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19484 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019485 /*
19486 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019487 * the {type definition}
19488 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019489 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019490 * of the {substitution group exclusions} of the {substitution group
19491 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19492 * (if the {type definition} is complex) or as defined in
19493 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019494 * simple)."
19495 *
19496 * NOTE: {substitution group exclusions} means the values of the
19497 * attribute "final".
19498 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019499
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019500 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019501 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019502
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019503 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19504 set |= SUBSET_EXTENSION;
19505 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19506 set |= SUBSET_RESTRICTION;
19507
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019508 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019509 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19511
19512 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019513 xmlSchemaPCustomErrExt(pctxt,
19514 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019515 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019516 "The type definition '%s' was "
19517 "either rejected by the substitution group "
19518 "affiliation '%s', or not validly derived from its type "
19519 "definition '%s'",
19520 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019521 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019522 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019523 FREE_AND_NULL(strA)
19524 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019525 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019526 }
19527 }
19528 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019529 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019530 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019531 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019532 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019533 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019534 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019535 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019536 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019537 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019538 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019539 (WXS_IS_COMPLEX(typeDef) &&
19540 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019541 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19542 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019543
19544 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19545 xmlSchemaPCustomErr(pctxt,
19546 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019547 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019548 "The type definition (or type definition's content type) is or "
19549 "is derived from ID; value constraints are not allowed in "
19550 "conjunction with such a type definition", NULL);
19551 } else if (elemDecl->value != NULL) {
19552 int vcret;
19553 xmlNodePtr node = NULL;
19554
19555 /*
19556 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19557 * representation of its value must be ·valid· with respect to the
19558 * {type definition} as defined in Element Default Valid (Immediate)
19559 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019560 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019561 if (typeDef == NULL) {
19562 xmlSchemaPErr(pctxt, elemDecl->node,
19563 XML_SCHEMAP_INTERNAL,
19564 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19565 "type is missing... skipping validation of "
19566 "the value constraint", NULL, NULL);
19567 return (-1);
19568 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019569 if (elemDecl->node != NULL) {
19570 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19571 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19572 BAD_CAST "fixed");
19573 else
19574 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19575 BAD_CAST "default");
19576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019577 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19578 typeDef, elemDecl->value, &(elemDecl->defVal));
19579 if (vcret != 0) {
19580 if (vcret < 0) {
19581 PERROR_INT("xmlSchemaElemCheckValConstr",
19582 "failed to validate the value constraint of an "
19583 "element declaration");
19584 return (-1);
19585 }
19586 return (vcret);
19587 }
19588 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019589
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019590 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019591}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019592
19593/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019594 * xmlSchemaCheckElemSubstGroup:
19595 * @ctxt: a schema parser context
19596 * @decl: the element declaration
19597 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019598 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019599 * Schema Component Constraint:
19600 * Substitution Group (cos-equiv-class)
19601 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019602 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019603 * a list will be built for each subst. group head, holding all direct
19604 * referents to this head.
19605 * NOTE that this function needs:
19606 * 1. circular subst. groups to be checked beforehand
19607 * 2. the declaration's type to be derived from the head's type
19608 *
19609 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019610 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019611 */
19612static void
19613xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19614 xmlSchemaElementPtr elemDecl)
19615{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019616 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019617 /* SPEC (1) "Its {abstract} is false." */
19618 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19619 return;
19620 {
19621 xmlSchemaElementPtr head;
19622 xmlSchemaTypePtr headType, type;
19623 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019624 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019625 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19626 * {disallowed substitutions} as the blocking constraint, as defined in
19627 * Substitution Group OK (Transitive) (§3.3.6)."
19628 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019629 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19630 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019631 set = 0;
19632 methSet = 0;
19633 /*
19634 * The blocking constraints.
19635 */
19636 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19637 continue;
19638 headType = head->subtypes;
19639 type = elemDecl->subtypes;
19640 if (headType == type)
19641 goto add_member;
19642 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19643 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19644 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19645 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19646 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019647 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019648 * "The set of all {derivation method}s involved in the
19649 * derivation of D's {type definition} from C's {type definition}
19650 * does not intersect with the union of the blocking constraint,
19651 * C's {prohibited substitutions} (if C is complex, otherwise the
19652 * empty set) and the {prohibited substitutions} (respectively the
19653 * empty set) of any intermediate {type definition}s in the
19654 * derivation of D's {type definition} from C's {type definition}."
19655 */
19656 /*
19657 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19658 * subst.head axis, the methSet does not need to be computed for
19659 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019660 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019661 /*
19662 * The set of all {derivation method}s involved in the derivation
19663 */
19664 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019665 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019666 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19667 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019668
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019669 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019670 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19671 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19672
19673 type = type->baseType;
19674 }
19675 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019676 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019677 * the head's type.
19678 */
19679 type = elemDecl->subtypes->baseType;
19680 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019681 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019682 if ((type->flags &
19683 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19684 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19685 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19686 if ((type->flags &
19687 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19688 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19689 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19690 } else
19691 break;
19692 if (type == headType)
19693 break;
19694 type = type->baseType;
19695 }
19696 if ((set != 0) &&
19697 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19698 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19699 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19700 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19701 continue;
19702 }
19703add_member:
19704 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19705 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19706 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19707 }
19708 }
19709}
19710
19711/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019712 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019713 * @item: an schema element declaration/particle
19714 * @ctxt: a schema parser context
19715 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019716 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019717 * Validates the value constraints of an element declaration.
19718 *
19719 * Fixes finish doing the computations on the element declarations.
19720 */
19721static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019722xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019723 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019724{
19725 if (elemDecl == NULL)
19726 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019727 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19728 return;
19729 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019730 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19731 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019732}
19733
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019734/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019735 * xmlSchemaResolveModelGroupParticleReferences:
19736 * @particle: a particle component
19737 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019738 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019739 * Resolves references of a model group's {particles} to
19740 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019741 */
19742static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019743xmlSchemaResolveModelGroupParticleReferences(
19744 xmlSchemaParserCtxtPtr ctxt,
19745 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019746{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019747 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19748 xmlSchemaQNameRefPtr ref;
19749 xmlSchemaBasicItemPtr refItem;
19750
19751 /*
19752 * URGENT TODO: Test this.
19753 */
19754 while (particle != NULL) {
19755 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19756 ((WXS_PARTICLE_TERM(particle))->type !=
19757 XML_SCHEMA_EXTRA_QNAMEREF))
19758 {
19759 goto next_particle;
19760 }
19761 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019762 /*
19763 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019764 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019765 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019766 particle->children = NULL;
19767
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019768 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19769 ref->itemType, ref->name, ref->targetNamespace);
19770 if (refItem == NULL) {
19771 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019772 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019773 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019774 /* TODO: remove the particle. */
19775 goto next_particle;
19776 }
19777 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19778 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19779 /* TODO: remove the particle. */
19780 goto next_particle;
19781 /*
19782 * NOTE that we will assign the model group definition
19783 * itself to the "term" of the particle. This will ease
19784 * the check for circular model group definitions. After
19785 * that the "term" will be assigned the model group of the
19786 * model group definition.
19787 */
19788 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19789 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019790 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019791 * SPEC cos-all-limited (1)
19792 * SPEC cos-all-limited (1.2)
19793 * "It appears only as the value of one or both of the
19794 * following properties:"
19795 * (1.1) "the {model group} property of a model group
19796 * definition."
19797 * (1.2) "the {term} property of a particle [... of] the "
19798 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019799 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019800 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19801 /* TODO: error code */
19802 XML_SCHEMAP_COS_ALL_LIMITED,
19803 WXS_ITEM_NODE(particle), NULL,
19804 "A model group definition is referenced, but "
19805 "it contains an 'all' model group, which "
19806 "cannot be contained by model groups",
19807 NULL, NULL);
19808 /* TODO: remove the particle. */
19809 goto next_particle;
19810 }
19811 particle->children = (xmlSchemaTreeItemPtr) refItem;
19812 } else {
19813 /*
19814 * TODO: Are referenced element declarations the only
19815 * other components we expect here?
19816 */
19817 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019818 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019819next_particle:
19820 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019821 }
19822}
19823
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019824static int
19825xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19826 xmlSchemaValPtr y)
19827{
19828 xmlSchemaTypePtr tx, ty, ptx, pty;
19829 int ret;
19830
19831 while (x != NULL) {
19832 /* Same types. */
19833 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19834 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19835 ptx = xmlSchemaGetPrimitiveType(tx);
19836 pty = xmlSchemaGetPrimitiveType(ty);
19837 /*
19838 * (1) if a datatype T' is ·derived· by ·restriction· from an
19839 * atomic datatype T then the ·value space· of T' is a subset of
19840 * the ·value space· of T. */
19841 /*
19842 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19843 * from a common atomic ancestor T then the ·value space·s of T'
19844 * and T'' may overlap.
19845 */
19846 if (ptx != pty)
19847 return(0);
19848 /*
19849 * We assume computed values to be normalized, so do a fast
19850 * string comparison for string based types.
19851 */
19852 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019853 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019854 if (! xmlStrEqual(
19855 xmlSchemaValueGetAsString(x),
19856 xmlSchemaValueGetAsString(y)))
19857 return (0);
19858 } else {
19859 ret = xmlSchemaCompareValuesWhtsp(
19860 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19861 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19862 if (ret == -2)
19863 return(-1);
19864 if (ret != 0)
19865 return(0);
19866 }
19867 /*
19868 * Lists.
19869 */
19870 x = xmlSchemaValueGetNext(x);
19871 if (x != NULL) {
19872 y = xmlSchemaValueGetNext(y);
19873 if (y == NULL)
19874 return (0);
19875 } else if (xmlSchemaValueGetNext(y) != NULL)
19876 return (0);
19877 else
19878 return (1);
19879 }
19880 return (0);
19881}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019882
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019883/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019884 * xmlSchemaResolveAttrUseReferences:
19885 * @item: an attribute use
19886 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019887 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019888 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019889 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019890static int
19891xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19892 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019893{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019894 if ((ctxt == NULL) || (ause == NULL))
19895 return(-1);
19896 if ((ause->attrDecl == NULL) ||
19897 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19898 return(0);
19899
19900 {
19901 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19902
19903 /*
19904 * TODO: Evaluate, what errors could occur if the declaration is not
19905 * found.
19906 */
19907 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19908 ref->name, ref->targetNamespace);
19909 if (ause->attrDecl == NULL) {
19910 xmlSchemaPResCompAttrErr(ctxt,
19911 XML_SCHEMAP_SRC_RESOLVE,
19912 WXS_BASIC_CAST ause, ause->node,
19913 "ref", ref->name, ref->targetNamespace,
19914 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19915 return(ctxt->err);;
19916 }
19917 }
19918 return(0);
19919}
19920
19921/**
19922 * xmlSchemaCheckAttrUsePropsCorrect:
19923 * @ctxt: a parser context
19924 * @use: an attribute use
19925 *
19926 * Schema Component Constraint:
19927 * Attribute Use Correct (au-props-correct)
19928 *
19929 */
19930static int
19931xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19932 xmlSchemaAttributeUsePtr use)
19933{
19934 if ((ctxt == NULL) || (use == NULL))
19935 return(-1);
19936 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19937 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19938 return(0);
19939
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019940 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019941 * SPEC au-props-correct (1)
19942 * "The values of the properties of an attribute use must be as
19943 * described in the property tableau in The Attribute Use Schema
19944 * Component (§3.5.1), modulo the impact of Missing
19945 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019946 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019947
19948 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19949 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19950 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19951 {
19952 xmlSchemaPCustomErr(ctxt,
19953 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19954 WXS_BASIC_CAST use, NULL,
19955 "The attribute declaration has a 'fixed' value constraint "
19956 ", thus the attribute use must also have a 'fixed' value "
19957 "constraint",
19958 NULL);
19959 return(ctxt->err);
19960 }
19961 /*
19962 * Compute and check the value constraint's value.
19963 */
19964 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19965 int ret;
19966 /*
19967 * TODO: The spec seems to be missing a check of the
19968 * value constraint of the attribute use. We will do it here.
19969 */
19970 /*
19971 * SPEC a-props-correct (3)
19972 */
19973 if (xmlSchemaIsDerivedFromBuiltInType(
19974 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19975 {
19976 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19977 XML_SCHEMAP_AU_PROPS_CORRECT,
19978 NULL, WXS_BASIC_CAST use,
19979 "Value constraints are not allowed if the type definition "
19980 "is or is derived from xs:ID",
19981 NULL, NULL);
19982 return(ctxt->err);
19983 }
19984
19985 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19986 use->node, WXS_ATTRUSE_TYPEDEF(use),
19987 use->defValue, &(use->defVal),
19988 1, 1, 0);
19989 if (ret != 0) {
19990 if (ret < 0) {
19991 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19992 "calling xmlSchemaVCheckCVCSimpleType()");
19993 return(-1);
19994 }
19995 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19996 XML_SCHEMAP_AU_PROPS_CORRECT,
19997 NULL, WXS_BASIC_CAST use,
19998 "The value of the value constraint is not valid",
19999 NULL, NULL);
20000 return(ctxt->err);
20001 }
20002 }
20003 /*
20004 * SPEC au-props-correct (2)
20005 * "If the {attribute declaration} has a fixed
20006 * {value constraint}, then if the attribute use itself has a
20007 * {value constraint}, it must also be fixed and its value must match
20008 * that of the {attribute declaration}'s {value constraint}."
20009 */
20010 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20011 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20012 {
20013 if (! xmlSchemaAreValuesEqual(use->defVal,
20014 (WXS_ATTRUSE_DECL(use))->defVal))
20015 {
20016 xmlSchemaPCustomErr(ctxt,
20017 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20018 WXS_BASIC_CAST use, NULL,
20019 "The 'fixed' value constraint of the attribute use "
20020 "must match the attribute declaration's value "
20021 "constraint '%s'",
20022 (WXS_ATTRUSE_DECL(use))->defValue);
20023 }
20024 return(ctxt->err);
20025 }
20026 return(0);
20027}
20028
20029
20030
20031
20032/**
20033 * xmlSchemaResolveAttrTypeReferences:
20034 * @item: an attribute declaration
20035 * @ctxt: a parser context
20036 *
20037 * Resolves the referenced type definition component.
20038 */
20039static int
20040xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20041 xmlSchemaParserCtxtPtr ctxt)
20042{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020043 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020044 * The simple type definition corresponding to the <simpleType> element
20045 * information item in the [children], if present, otherwise the simple
20046 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020047 * [attribute], if present, otherwise the ·simple ur-type definition·.
20048 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020049 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020050 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020051 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20052 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020053 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020054 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020055 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020056
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020057 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20058 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020059 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020060 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020061 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020062 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020063 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020064 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020065 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020066 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020067 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020068
Daniel Veillard3646d642004-06-02 19:19:14 +000020069 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020070 /*
20071 * The type defaults to the xs:anySimpleType.
20072 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020073 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20074 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020075 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020076}
20077
20078/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020079 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020080 * @idc: the identity-constraint definition
20081 * @ctxt: the schema parser context
20082 * @name: the attribute name
20083 *
20084 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020085 * Schema Component Constraint:
20086 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020087 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020088static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020089xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020090 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020091{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020092 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020093 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020094 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020095 idc->ref->item = (xmlSchemaBasicItemPtr)
20096 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20097 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020098 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020099 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020100 * TODO: It is actually not an error to fail to resolve
20101 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020102 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020103 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020104 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020105 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020106 "refer", idc->ref->name,
20107 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020108 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020109 return(pctxt->err);
20110 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20111 /*
20112 * SPEC c-props-correct (1)
20113 */
20114 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20115 XML_SCHEMAP_C_PROPS_CORRECT,
20116 NULL, WXS_BASIC_CAST idc,
20117 "The keyref references a keyref",
20118 NULL, NULL);
20119 idc->ref->item = NULL;
20120 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020121 } else {
20122 if (idc->nbFields !=
20123 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20124 xmlChar *str = NULL;
20125 xmlSchemaIDCPtr refer;
20126
20127 refer = (xmlSchemaIDCPtr) idc->ref->item;
20128 /*
20129 * SPEC c-props-correct(2)
20130 * "If the {identity-constraint category} is keyref,
20131 * the cardinality of the {fields} must equal that of
20132 * the {fields} of the {referenced key}.
20133 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020134 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020135 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020136 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020137 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020138 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020139 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020140 refer->name),
20141 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020142 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020143 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020144 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020145 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020146 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020147 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020148}
20149
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020150static int
20151xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20152 xmlSchemaParserCtxtPtr pctxt)
20153{
20154 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20155 prohib->targetNamespace) == NULL) {
20156
20157 xmlSchemaPResCompAttrErr(pctxt,
20158 XML_SCHEMAP_SRC_RESOLVE,
20159 NULL, prohib->node,
20160 "ref", prohib->name, prohib->targetNamespace,
20161 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20162 return(XML_SCHEMAP_SRC_RESOLVE);
20163 }
20164 return(0);
20165}
20166
20167#define WXS_REDEFINED_TYPE(c) \
20168(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20169
20170#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20171(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20172
20173#define WXS_REDEFINED_ATTR_GROUP(c) \
20174(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20175
20176static int
20177xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20178{
20179 int err = 0;
20180 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20181 xmlSchemaBasicItemPtr prev, item;
20182 int wasRedefined;
20183
20184 if (redef == NULL)
20185 return(0);
20186
20187 do {
20188 item = redef->item;
20189 /*
20190 * First try to locate the redefined component in the
20191 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020192 * NOTE: According to this schema bug entry:
20193 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20194 * it's not clear if the referenced component needs to originate
20195 * from the <redefine>d schema _document_ or the schema; the latter
20196 * would include all imported and included sub-schemas of the
20197 * <redefine>d schema. Currenlty we latter approach is used.
20198 * SUPPLEMENT: It seems that the WG moves towards the latter
20199 * approach, so we are doing it right.
20200 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020201 */
20202 prev = xmlSchemaFindRedefCompInGraph(
20203 redef->targetBucket, item->type,
20204 redef->refName, redef->refTargetNs);
20205 if (prev == NULL) {
20206 xmlChar *str = NULL;
20207 xmlNodePtr node;
20208
20209 /*
20210 * SPEC src-redefine:
20211 * (6.2.1) "The ·actual value· of its own name attribute plus
20212 * target namespace must successfully ·resolve· to a model
20213 * group definition in I."
20214 * (7.2.1) "The ·actual value· of its own name attribute plus
20215 * target namespace must successfully ·resolve· to an attribute
20216 * group definition in I."
20217
20218 *
20219 * Note that, if we are redefining with the use of references
20220 * to components, the spec assumes the src-resolve to be used;
20221 * but this won't assure that we search only *inside* the
20222 * redefined schema.
20223 */
20224 if (redef->reference)
20225 node = WXS_ITEM_NODE(redef->reference);
20226 else
20227 node = WXS_ITEM_NODE(item);
20228 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20229 /*
20230 * TODO: error code.
20231 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20232 * reference kind.
20233 */
20234 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20235 "The %s to be redefined could not be found in "
20236 "the redefined schema",
20237 WXS_ITEM_TYPE_NAME(item),
20238 xmlSchemaFormatQName(&str, redef->refTargetNs,
20239 redef->refName));
20240 FREE_AND_NULL(str);
20241 err = pctxt->err;
20242 redef = redef->next;
20243 continue;
20244 }
20245 /*
20246 * TODO: Obtaining and setting the redefinition state is really
20247 * clumsy.
20248 */
20249 wasRedefined = 0;
20250 switch (item->type) {
20251 case XML_SCHEMA_TYPE_COMPLEX:
20252 case XML_SCHEMA_TYPE_SIMPLE:
20253 if ((WXS_TYPE_CAST prev)->flags &
20254 XML_SCHEMAS_TYPE_REDEFINED)
20255 {
20256 wasRedefined = 1;
20257 break;
20258 }
20259 /* Mark it as redefined. */
20260 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20261 /*
20262 * Assign the redefined type to the
20263 * base type of the redefining type.
20264 * TODO: How
20265 */
20266 ((xmlSchemaTypePtr) item)->baseType =
20267 (xmlSchemaTypePtr) prev;
20268 break;
20269 case XML_SCHEMA_TYPE_GROUP:
20270 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20271 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20272 {
20273 wasRedefined = 1;
20274 break;
20275 }
20276 /* Mark it as redefined. */
20277 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20278 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20279 if (redef->reference != NULL) {
20280 /*
20281 * Overwrite the QName-reference with the
20282 * referenced model group def.
20283 */
20284 (WXS_PTC_CAST redef->reference)->children =
20285 WXS_TREE_CAST prev;
20286 }
20287 redef->target = prev;
20288 break;
20289 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20290 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20291 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20292 {
20293 wasRedefined = 1;
20294 break;
20295 }
20296 (WXS_ATTR_GROUP_CAST prev)->flags |=
20297 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20298 if (redef->reference != NULL) {
20299 /*
20300 * Assign the redefined attribute group to the
20301 * QName-reference component.
20302 * This is the easy case, since we will just
20303 * expand the redefined group.
20304 */
20305 (WXS_QNAME_CAST redef->reference)->item = prev;
20306 redef->target = NULL;
20307 } else {
20308 /*
20309 * This is the complicated case: we need
20310 * to apply src-redefine (7.2.2) at a later
20311 * stage, i.e. when attribute group references
20312 * have beed expanded and simple types have
20313 * beed fixed.
20314 */
20315 redef->target = prev;
20316 }
20317 break;
20318 default:
20319 PERROR_INT("xmlSchemaResolveRedefReferences",
20320 "Unexpected redefined component type");
20321 return(-1);
20322 }
20323 if (wasRedefined) {
20324 xmlChar *str = NULL;
20325 xmlNodePtr node;
20326
20327 if (redef->reference)
20328 node = WXS_ITEM_NODE(redef->reference);
20329 else
20330 node = WXS_ITEM_NODE(redef->item);
20331
20332 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20333 /* TODO: error code. */
20334 XML_SCHEMAP_SRC_REDEFINE,
20335 node, NULL,
20336 "The referenced %s was already redefined. Multiple "
20337 "redefinition of the same component is not supported",
20338 xmlSchemaGetComponentDesignation(&str, prev),
20339 NULL);
20340 FREE_AND_NULL(str)
20341 err = pctxt->err;
20342 redef = redef->next;
20343 continue;
20344 }
20345 redef = redef->next;
20346 } while (redef != NULL);
20347
20348 return(err);
20349}
20350
20351static int
20352xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20353{
20354 int err = 0;
20355 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20356 xmlSchemaBasicItemPtr item;
20357
20358 if (redef == NULL)
20359 return(0);
20360
20361 do {
20362 if (redef->target == NULL) {
20363 redef = redef->next;
20364 continue;
20365 }
20366 item = redef->item;
20367
20368 switch (item->type) {
20369 case XML_SCHEMA_TYPE_SIMPLE:
20370 case XML_SCHEMA_TYPE_COMPLEX:
20371 /*
20372 * Since the spec wants the {name} of the redefined
20373 * type to be 'absent', we'll NULL it.
20374 */
20375 (WXS_TYPE_CAST redef->target)->name = NULL;
20376
20377 /*
20378 * TODO: Seems like there's nothing more to do. The normal
20379 * inheritance mechanism is used. But not 100% sure.
20380 */
20381 break;
20382 case XML_SCHEMA_TYPE_GROUP:
20383 /*
20384 * URGENT TODO:
20385 * SPEC src-redefine:
20386 * (6.2.2) "The {model group} of the model group definition
20387 * which corresponds to it per XML Representation of Model
20388 * Group Definition Schema Components (§3.7.2) must be a
20389 * ·valid restriction· of the {model group} of that model
20390 * group definition in I, as defined in Particle Valid
20391 * (Restriction) (§3.9.6)."
20392 */
20393 break;
20394 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20395 /*
20396 * SPEC src-redefine:
20397 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20398 * the attribute group definition which corresponds to it
20399 * per XML Representation of Attribute Group Definition Schema
20400 * Components (§3.6.2) must be ·valid restrictions· of the
20401 * {attribute uses} and {attribute wildcard} of that attribute
20402 * group definition in I, as defined in clause 2, clause 3 and
20403 * clause 4 of Derivation Valid (Restriction, Complex)
20404 * (§3.4.6) (where references to the base type definition are
20405 * understood as references to the attribute group definition
20406 * in I)."
20407 */
20408 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20409 XML_SCHEMA_ACTION_REDEFINE,
20410 item, redef->target,
20411 (WXS_ATTR_GROUP_CAST item)->attrUses,
20412 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20413 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20414 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20415 if (err == -1)
20416 return(-1);
20417 break;
20418 default:
20419 break;
20420 }
20421 redef = redef->next;
20422 } while (redef != NULL);
20423 return(0);
20424}
20425
20426
20427static int
20428xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20429 xmlSchemaBucketPtr bucket)
20430{
20431 xmlSchemaBasicItemPtr item;
20432 int err;
20433 xmlHashTablePtr *table;
20434 const xmlChar *name;
20435 int i;
20436
20437#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20438 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20439 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20440 else \
20441 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20442
20443 /*
20444 * Add global components to the schema's hash tables.
20445 * This is the place where duplicate components will be
20446 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020447 * TODO: I think normally we should support imports of the
20448 * same namespace from multiple locations. We don't do currently,
20449 * but if we do then according to:
20450 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20451 * we would need, if imported directly, to import redefined
20452 * components as well to be able to catch clashing components.
20453 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020454 */
20455 if (bucket == NULL)
20456 return(-1);
20457 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20458 return(0);
20459 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20460
20461 for (i = 0; i < bucket->globals->nbItems; i++) {
20462 item = bucket->globals->items[i];
20463 table = NULL;
20464 switch (item->type) {
20465 case XML_SCHEMA_TYPE_COMPLEX:
20466 case XML_SCHEMA_TYPE_SIMPLE:
20467 if (WXS_REDEFINED_TYPE(item))
20468 continue;
20469 name = (WXS_TYPE_CAST item)->name;
20470 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20471 break;
20472 case XML_SCHEMA_TYPE_ELEMENT:
20473 name = (WXS_ELEM_CAST item)->name;
20474 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20475 break;
20476 case XML_SCHEMA_TYPE_ATTRIBUTE:
20477 name = (WXS_ATTR_CAST item)->name;
20478 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20479 break;
20480 case XML_SCHEMA_TYPE_GROUP:
20481 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20482 continue;
20483 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20484 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20485 break;
20486 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20487 if (WXS_REDEFINED_ATTR_GROUP(item))
20488 continue;
20489 name = (WXS_ATTR_GROUP_CAST item)->name;
20490 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20491 break;
20492 case XML_SCHEMA_TYPE_IDC_KEY:
20493 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20494 case XML_SCHEMA_TYPE_IDC_KEYREF:
20495 name = (WXS_IDC_CAST item)->name;
20496 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20497 break;
20498 case XML_SCHEMA_TYPE_NOTATION:
20499 name = ((xmlSchemaNotationPtr) item)->name;
20500 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20501 break;
20502 default:
20503 PERROR_INT("xmlSchemaAddComponents",
20504 "Unexpected global component type");
20505 continue;
20506 }
20507 if (*table == NULL) {
20508 *table = xmlHashCreateDict(10, pctxt->dict);
20509 if (*table == NULL) {
20510 PERROR_INT("xmlSchemaAddComponents",
20511 "failed to create a component hash table");
20512 return(-1);
20513 }
20514 }
20515 err = xmlHashAddEntry(*table, name, item);
20516 if (err != 0) {
20517 xmlChar *str = NULL;
20518
20519 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20520 XML_SCHEMAP_REDEFINED_TYPE,
20521 WXS_ITEM_NODE(item),
20522 WXS_BASIC_CAST item,
20523 "A global %s '%s' does already exist",
20524 WXS_ITEM_TYPE_NAME(item),
20525 xmlSchemaGetComponentQName(&str, item));
20526 FREE_AND_NULL(str);
20527 }
20528 }
20529 /*
20530 * Process imported/included schemas.
20531 */
20532 if (bucket->relations != NULL) {
20533 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20534 do {
20535 if ((rel->bucket != NULL) &&
20536 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20537 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20538 return(-1);
20539 }
20540 rel = rel->next;
20541 } while (rel != NULL);
20542 }
20543 return(0);
20544}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020545
20546static int
20547xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20548{
20549 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20550 xmlSchemaTreeItemPtr item, *items;
20551 int nbItems, i;
20552
20553#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20554
20555 if ((con->pending == NULL) ||
20556 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020557 return(0);
20558
20559 /* TODO:
20560 * SPEC (src-redefine):
20561 * (6.2) "If it has no such self-reference, then all of the
20562 * following must be true:"
20563
20564 * (6.2.2) The {model group} of the model group definition which
20565 * corresponds to it per XML Representation of Model Group
20566 * Definition Schema Components (§3.7.2) must be a ·valid
20567 * restriction· of the {model group} of that model group definition
20568 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20569 */
20570 xmlSchemaCheckSRCRedefineFirst(pctxt);
20571
20572 /*
20573 * Add global components to the schemata's hash tables.
20574 */
20575 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020576
20577 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020578 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20579 nbItems = con->pending->nbItems;
20580 /*
20581 * Now that we have parsed *all* the schema document(s) and converted
20582 * them to schema components, we can resolve references, apply component
20583 * constraints, create the FSA from the content model, etc.
20584 */
20585 /*
20586 * Resolve references of..
20587 *
20588 * 1. element declarations:
20589 * - the type definition
20590 * - the substitution group affiliation
20591 * 2. simple/complex types:
20592 * - the base type definition
20593 * - the memberTypes of union types
20594 * - the itemType of list types
20595 * 3. attributes declarations and attribute uses:
20596 * - the type definition
20597 * - if an attribute use, then the attribute declaration
20598 * 4. attribute group references:
20599 * - the attribute group definition
20600 * 5. particles:
20601 * - the term of the particle (e.g. a model group)
20602 * 6. IDC key-references:
20603 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020604 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020605 */
20606 for (i = 0; i < nbItems; i++) {
20607 item = items[i];
20608 switch (item->type) {
20609 case XML_SCHEMA_TYPE_ELEMENT:
20610 xmlSchemaResolveElementReferences(
20611 (xmlSchemaElementPtr) item, pctxt);
20612 FIXHFAILURE;
20613 break;
20614 case XML_SCHEMA_TYPE_COMPLEX:
20615 case XML_SCHEMA_TYPE_SIMPLE:
20616 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020617 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020618 FIXHFAILURE;
20619 break;
20620 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020621 xmlSchemaResolveAttrTypeReferences(
20622 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020623 FIXHFAILURE;
20624 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020625 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20626 xmlSchemaResolveAttrUseReferences(
20627 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020628 FIXHFAILURE;
20629 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020630 case XML_SCHEMA_EXTRA_QNAMEREF:
20631 if ((WXS_QNAME_CAST item)->itemType ==
20632 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20633 {
20634 xmlSchemaResolveAttrGroupReferences(
20635 WXS_QNAME_CAST item, pctxt);
20636 }
20637 FIXHFAILURE;
20638 break;
20639 case XML_SCHEMA_TYPE_SEQUENCE:
20640 case XML_SCHEMA_TYPE_CHOICE:
20641 case XML_SCHEMA_TYPE_ALL:
20642 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20643 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020644 FIXHFAILURE;
20645 break;
20646 case XML_SCHEMA_TYPE_IDC_KEY:
20647 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20648 case XML_SCHEMA_TYPE_IDC_KEYREF:
20649 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020650 (xmlSchemaIDCPtr) item, pctxt);
20651 FIXHFAILURE;
20652 break;
20653 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20654 /*
20655 * Handle attribue prohibition which had a
20656 * "ref" attribute.
20657 */
20658 xmlSchemaResolveAttrUseProhibReferences(
20659 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020660 FIXHFAILURE;
20661 break;
20662 default:
20663 break;
20664 }
20665 }
20666 if (pctxt->nberrors != 0)
20667 goto exit_error;
20668
20669 /*
20670 * Now that all references are resolved we
20671 * can check for circularity of...
20672 * 1. the base axis of type definitions
20673 * 2. nested model group definitions
20674 * 3. nested attribute group definitions
20675 * TODO: check for circual substitution groups.
20676 */
20677 for (i = 0; i < nbItems; i++) {
20678 item = items[i];
20679 /*
20680 * Let's better stop on the first error here.
20681 */
20682 switch (item->type) {
20683 case XML_SCHEMA_TYPE_COMPLEX:
20684 case XML_SCHEMA_TYPE_SIMPLE:
20685 xmlSchemaCheckTypeDefCircular(
20686 (xmlSchemaTypePtr) item, pctxt);
20687 FIXHFAILURE;
20688 if (pctxt->nberrors != 0)
20689 goto exit_error;
20690 break;
20691 case XML_SCHEMA_TYPE_GROUP:
20692 xmlSchemaCheckGroupDefCircular(
20693 (xmlSchemaModelGroupDefPtr) item, pctxt);
20694 FIXHFAILURE;
20695 if (pctxt->nberrors != 0)
20696 goto exit_error;
20697 break;
20698 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20699 xmlSchemaCheckAttrGroupCircular(
20700 (xmlSchemaAttributeGroupPtr) item, pctxt);
20701 FIXHFAILURE;
20702 if (pctxt->nberrors != 0)
20703 goto exit_error;
20704 break;
20705 default:
20706 break;
20707 }
20708 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020709 if (pctxt->nberrors != 0)
20710 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020711 /*
20712 * Model group definition references:
20713 * Such a reference is reflected by a particle at the component
20714 * level. Until now the 'term' of such particles pointed
20715 * to the model group definition; this was done, in order to
20716 * ease circularity checks. Now we need to set the 'term' of
20717 * such particles to the model group of the model group definition.
20718 */
20719 for (i = 0; i < nbItems; i++) {
20720 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020721 switch (item->type) {
20722 case XML_SCHEMA_TYPE_SEQUENCE:
20723 case XML_SCHEMA_TYPE_CHOICE:
20724 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20725 WXS_MODEL_GROUP_CAST item);
20726 break;
20727 default:
20728 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020729 }
20730 }
20731 if (pctxt->nberrors != 0)
20732 goto exit_error;
20733 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020734 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020735 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020736 for (i = 0; i < nbItems; i++) {
20737 item = items[i];
20738 switch (item->type) {
20739 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20740 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20741 WXS_ATTR_GROUP_HAS_REFS(item))
20742 {
20743 xmlSchemaAttributeGroupExpandRefs(pctxt,
20744 WXS_ATTR_GROUP_CAST item);
20745 FIXHFAILURE;
20746 }
20747 break;
20748 default:
20749 break;
20750 }
20751 }
20752 if (pctxt->nberrors != 0)
20753 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020754 /*
20755 * First compute the variety of simple types. This is needed as
20756 * a seperate step, since otherwise we won't be able to detect
20757 * circular union types in all cases.
20758 */
20759 for (i = 0; i < nbItems; i++) {
20760 item = items[i];
20761 switch (item->type) {
20762 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020763 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020764 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20765 (xmlSchemaTypePtr) item);
20766 FIXHFAILURE;
20767 }
20768 break;
20769 default:
20770 break;
20771 }
20772 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020773 if (pctxt->nberrors != 0)
20774 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020775 /*
20776 * Detect circular union types. Note that this needs the variety to
20777 * be already computed.
20778 */
20779 for (i = 0; i < nbItems; i++) {
20780 item = items[i];
20781 switch (item->type) {
20782 case XML_SCHEMA_TYPE_SIMPLE:
20783 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20784 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20785 (xmlSchemaTypePtr) item);
20786 FIXHFAILURE;
20787 }
20788 break;
20789 default:
20790 break;
20791 }
20792 }
20793 if (pctxt->nberrors != 0)
20794 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020795
20796 /*
20797 * Do the complete type fixup for simple types.
20798 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020799 for (i = 0; i < nbItems; i++) {
20800 item = items[i];
20801 switch (item->type) {
20802 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020803 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20804 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20805 FIXHFAILURE;
20806 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020807 break;
20808 default:
20809 break;
20810 }
20811 }
20812 if (pctxt->nberrors != 0)
20813 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020814 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020815 * At this point we need all simple types to be builded and checked.
20816 */
20817 /*
20818 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020819 */
20820 for (i = 0; i < nbItems; i++) {
20821 item = items[i];
20822 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020823 case XML_SCHEMA_TYPE_ATTRIBUTE:
20824 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20825 FIXHFAILURE;
20826 break;
20827 default:
20828 break;
20829 }
20830 }
20831 if (pctxt->nberrors != 0)
20832 goto exit_error;
20833 /*
20834 * Apply constraints for attribute uses.
20835 */
20836 for (i = 0; i < nbItems; i++) {
20837 item = items[i];
20838 switch (item->type) {
20839 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20840 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20841 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20842 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020843 FIXHFAILURE;
20844 }
20845 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020846 default:
20847 break;
20848 }
20849 }
20850 if (pctxt->nberrors != 0)
20851 goto exit_error;
20852
20853 /*
20854 * Apply constraints for attribute group definitions.
20855 */
20856 for (i = 0; i < nbItems; i++) {
20857 item = items[i];
20858 switch (item->type) {
20859 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20860 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20861 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20862 {
20863 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20864 FIXHFAILURE;
20865 }
20866 break;
20867 default:
20868 break;
20869 }
20870 }
20871 if (pctxt->nberrors != 0)
20872 goto exit_error;
20873
20874 /*
20875 * Apply constraints for redefinitions.
20876 */
20877 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20878 xmlSchemaCheckSRCRedefineSecond(pctxt);
20879 if (pctxt->nberrors != 0)
20880 goto exit_error;
20881
20882 /*
20883 * Fixup complex types.
20884 */
20885 for (i = 0; i < nbItems; i++) {
20886 item = con->pending->items[i];
20887 switch (item->type) {
20888 case XML_SCHEMA_TYPE_COMPLEX:
20889 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20890 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20891 FIXHFAILURE;
20892 }
20893 break;
20894 default:
20895 break;
20896 }
20897 }
20898 if (pctxt->nberrors != 0)
20899 goto exit_error;
20900
20901 /*
20902 * The list could have changed, since xmlSchemaFixupComplexType()
20903 * will create particles and model groups in some cases.
20904 */
20905 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20906 nbItems = con->pending->nbItems;
20907
20908 /*
20909 * At this point all complex types need to be builded and checked.
20910 */
20911 /*
20912 * Apply some constraints for element declarations.
20913 */
20914 for (i = 0; i < nbItems; i++) {
20915 item = items[i];
20916 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020917 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020918
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020919 if ((((xmlSchemaElementPtr) item)->flags &
20920 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20921 xmlSchemaCheckElementDeclComponent(
20922 (xmlSchemaElementPtr) item, pctxt);
20923 FIXHFAILURE;
20924 }
20925 break;
20926 default:
20927 break;
20928 }
20929 }
20930 if (pctxt->nberrors != 0)
20931 goto exit_error;
20932 /*
20933 * Finally we can build the automaton from the content model of
20934 * complex types.
20935 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020936
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020937 for (i = 0; i < nbItems; i++) {
20938 item = items[i];
20939 switch (item->type) {
20940 case XML_SCHEMA_TYPE_COMPLEX:
20941 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020942 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020943 break;
20944 default:
20945 break;
20946 }
20947 }
20948 if (pctxt->nberrors != 0)
20949 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020950 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020951 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020952 */
20953 con->pending->nbItems = 0;
20954 return(0);
20955exit_error:
20956 con->pending->nbItems = 0;
20957 return(pctxt->err);
20958exit_failure:
20959 con->pending->nbItems = 0;
20960 return(-1);
20961}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020962/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020963 * xmlSchemaParse:
20964 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020965 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020966 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020967 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020968 *
20969 * Returns the internal XML Schema structure built from the resource or
20970 * NULL in case of error
20971 */
20972xmlSchemaPtr
20973xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20974{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020975 xmlSchemaPtr schema = NULL;
20976 xmlSchemaBucketPtr bucket = NULL;
20977 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020978
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020979 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020980 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020981 * the API; i.e. not automatically by the validated instance document.
20982 */
20983
Daniel Veillard4255d502002-04-16 15:50:10 +000020984 xmlSchemaInitTypes();
20985
Daniel Veillard6045c902002-10-09 21:13:59 +000020986 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020987 return (NULL);
20988
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020989 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020990 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020991 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020992 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020993
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020994 /* Create the *main* schema. */
20995 schema = xmlSchemaNewSchema(ctxt);
20996 if (schema == NULL)
20997 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020998 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020999 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021000 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021001 if (ctxt->constructor == NULL) {
21002 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21003 if (ctxt->constructor == NULL)
21004 return(NULL);
21005 /* Take ownership of the constructor to be able to free it. */
21006 ctxt->ownsConstructor = 1;
21007 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021008 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021009 /*
21010 * Locate and add the schema document.
21011 */
21012 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21013 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21014 NULL, NULL, &bucket);
21015 if (res == -1)
21016 goto exit_failure;
21017 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021018 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021019
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021020 if (bucket == NULL) {
21021 /* TODO: Error code, actually we failed to *locate* the schema. */
21022 if (ctxt->URL)
21023 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21024 NULL, NULL,
21025 "Failed to locate the main schema resource at '%s'",
21026 ctxt->URL, NULL);
21027 else
21028 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21029 NULL, NULL,
21030 "Failed to locate the main schema resource",
21031 NULL, NULL);
21032 goto exit;
21033 }
21034 /* Set the main schema bucket. */
21035 ctxt->constructor->bucket = bucket;
21036 ctxt->targetNamespace = bucket->targetNamespace;
21037 schema->targetNamespace = bucket->targetNamespace;
21038
21039 /* Then do the parsing for good. */
21040 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21041 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021042 if (ctxt->nberrors != 0)
21043 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021044
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021045 schema->doc = bucket->doc;
21046 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021047
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021048 ctxt->schema = schema;
21049
21050 if (xmlSchemaFixupComponents(ctxt) == -1)
21051 goto exit_failure;
21052
21053 /*
21054 * TODO: This is not nice, since we cannot distinguish from the
21055 * result if there was an internal error or not.
21056 */
21057exit:
21058 if (ctxt->nberrors != 0) {
21059 if (schema) {
21060 xmlSchemaFree(schema);
21061 schema = NULL;
21062 }
21063 if (ctxt->constructor) {
21064 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21065 ctxt->constructor = NULL;
21066 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021068 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021069 ctxt->schema = NULL;
21070 return(schema);
21071exit_failure:
21072 /*
21073 * Quite verbose, but should catch internal errors, which were
21074 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021075 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021076 if (schema) {
21077 xmlSchemaFree(schema);
21078 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021079 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021080 if (ctxt->constructor) {
21081 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21082 ctxt->constructor = NULL;
21083 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021084 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021085 PERROR_INT2("xmlSchemaParse",
21086 "An internal error occured");
21087 ctxt->schema = NULL;
21088 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021089}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021090
Daniel Veillard4255d502002-04-16 15:50:10 +000021091/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021092 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021093 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021094 * @err: the error callback
21095 * @warn: the warning callback
21096 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021097 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021098 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021099 */
21100void
21101xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021102 xmlSchemaValidityErrorFunc err,
21103 xmlSchemaValidityWarningFunc warn, void *ctx)
21104{
Daniel Veillard4255d502002-04-16 15:50:10 +000021105 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021106 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021107 ctxt->error = err;
21108 ctxt->warning = warn;
21109 ctxt->userData = ctx;
21110}
21111
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021112/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021113 * xmlSchemaGetParserErrors:
21114 * @ctxt: a XMl-Schema parser context
21115 * @err: the error callback result
21116 * @warn: the warning callback result
21117 * @ctx: contextual data for the callbacks result
21118 *
21119 * Get the callback information used to handle errors for a parser context
21120 *
21121 * Returns -1 in case of failure, 0 otherwise
21122 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021123int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021124xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21125 xmlSchemaValidityErrorFunc * err,
21126 xmlSchemaValidityWarningFunc * warn, void **ctx)
21127{
21128 if (ctxt == NULL)
21129 return(-1);
21130 if (err != NULL)
21131 *err = ctxt->error;
21132 if (warn != NULL)
21133 *warn = ctxt->warning;
21134 if (ctx != NULL)
21135 *ctx = ctxt->userData;
21136 return(0);
21137}
21138
21139/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021140 * xmlSchemaFacetTypeToString:
21141 * @type: the facet type
21142 *
21143 * Convert the xmlSchemaTypeType to a char string.
21144 *
21145 * Returns the char string representation of the facet type if the
21146 * type is a facet and an "Internal Error" string otherwise.
21147 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021148static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021149xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21150{
21151 switch (type) {
21152 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021153 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021154 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021155 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021156 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021157 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021158 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021159 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021160 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021161 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021162 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021163 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021164 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021165 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021166 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021167 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021168 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021169 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021170 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021171 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021172 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021173 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021174 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021175 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021176 default:
21177 break;
21178 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021179 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021180}
21181
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021182static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021183xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21184{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021185 /*
21186 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021187 * from xsd:string.
21188 */
21189 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021190 /*
21191 * Note that we assume a whitespace of preserve for anySimpleType.
21192 */
21193 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21194 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21195 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021196 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021197 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021198 else {
21199 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021200 * For all ·atomic· datatypes other than string (and types ·derived·
21201 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021202 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021203 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021204 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021205 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021206 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021207 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021208 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021209 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021210 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021211 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021212 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021213 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021214 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021215 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21216 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21217 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21218 return (XML_SCHEMA_WHITESPACE_REPLACE);
21219 else
21220 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021222 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021223}
21224
Daniel Veillard4255d502002-04-16 15:50:10 +000021225/************************************************************************
21226 * *
21227 * Simple type validation *
21228 * *
21229 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021230
Daniel Veillard4255d502002-04-16 15:50:10 +000021231
21232/************************************************************************
21233 * *
21234 * DOM Validation code *
21235 * *
21236 ************************************************************************/
21237
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021238/**
21239 * xmlSchemaAssembleByLocation:
21240 * @pctxt: a schema parser context
21241 * @vctxt: a schema validation context
21242 * @schema: the existing schema
21243 * @node: the node that fired the assembling
21244 * @nsName: the namespace name of the new schema
21245 * @location: the location of the schema
21246 *
21247 * Expands an existing schema by an additional schema.
21248 *
21249 * Returns 0 if the new schema is correct, a positive error code
21250 * number otherwise and -1 in case of an internal or API error.
21251 */
21252static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021253xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021254 xmlSchemaPtr schema,
21255 xmlNodePtr node,
21256 const xmlChar *nsName,
21257 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021258{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021259 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021260 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021261 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021262
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021263 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021264 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021265
21266 if (vctxt->pctxt == NULL) {
21267 VERROR_INT("xmlSchemaAssembleByLocation",
21268 "no parser context available");
21269 return(-1);
21270 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021271 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021272 if (pctxt->constructor == NULL) {
21273 PERROR_INT("xmlSchemaAssembleByLocation",
21274 "no constructor");
21275 return(-1);
21276 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021277 /*
21278 * Acquire the schema document.
21279 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021280 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21281 location, node);
21282 /*
21283 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21284 * the process will automatically change this to
21285 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21286 */
21287 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21288 location, NULL, NULL, 0, node, NULL, nsName,
21289 &bucket);
21290 if (ret != 0)
21291 return(ret);
21292 if (bucket == NULL) {
21293 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021294 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021295 return(-1);
21296 }
21297 /*
21298 * The first located schema will be handled as if all other
21299 * schemas imported by XSI were imported by this first schema.
21300 */
21301 if ((bucket != NULL) &&
21302 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21303 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21304 /*
21305 * TODO: Is this handled like an import? I.e. is it not an error
21306 * if the schema cannot be located?
21307 */
21308 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21309 return(0);
21310 /*
21311 * We will reuse the parser context for every schema imported
21312 * directly via XSI. So reset the context.
21313 */
21314 pctxt->nberrors = 0;
21315 pctxt->err = 0;
21316 pctxt->doc = bucket->doc;
21317
21318 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21319 if (ret == -1) {
21320 pctxt->doc = NULL;
21321 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021322 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021323 /* Paranoid error channelling. */
21324 if ((ret == 0) && (pctxt->nberrors != 0))
21325 ret = pctxt->err;
21326 if (pctxt->nberrors == 0) {
21327 /*
21328 * Only bother to fixup pending components, if there was
21329 * no error yet.
21330 */
21331 xmlSchemaFixupComponents(pctxt);
21332 vctxt->nberrors += pctxt->nberrors;
21333 } else {
21334 /* Add to validation error sum. */
21335 vctxt->nberrors += pctxt->nberrors;
21336 }
21337 pctxt->doc = NULL;
21338 return(ret);
21339exit_failure:
21340 pctxt->doc = NULL;
21341 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021342}
21343
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021344static xmlSchemaAttrInfoPtr
21345xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21346 int metaType)
21347{
21348 if (vctxt->nbAttrInfos == 0)
21349 return (NULL);
21350 {
21351 int i;
21352 xmlSchemaAttrInfoPtr iattr;
21353
21354 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21355 iattr = vctxt->attrInfos[i];
21356 if (iattr->metaType == metaType)
21357 return (iattr);
21358 }
21359
21360 }
21361 return (NULL);
21362}
21363
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021364/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021365 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021366 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021367 *
21368 * Expands an existing schema by an additional schema using
21369 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21370 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21371 * must be set to 1.
21372 *
21373 * Returns 0 if the new schema is correct, a positive error code
21374 * number otherwise and -1 in case of an internal or API error.
21375 */
21376static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021377xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021378{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021379 const xmlChar *cur, *end;
21380 const xmlChar *nsname = NULL, *location;
21381 int count = 0;
21382 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021383 xmlSchemaAttrInfoPtr iattr;
21384
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021385 /*
21386 * Parse the value; we will assume an even number of values
21387 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021388 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021389 * URGENT TODO: !! This needs to work for both
21390 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21391 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021392 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021393 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21394 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21395 if (iattr == NULL)
21396 xmlSchemaGetMetaAttrInfo(vctxt,
21397 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21398 if (iattr == NULL)
21399 return (0);
21400 cur = iattr->value;
21401 do {
21402 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021403 /*
21404 * Get the namespace name.
21405 */
21406 while (IS_BLANK_CH(*cur))
21407 cur++;
21408 end = cur;
21409 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21410 end++;
21411 if (end == cur)
21412 break;
21413 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021414 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021415 cur = end;
21416 }
21417 /*
21418 * Get the URI.
21419 */
21420 while (IS_BLANK_CH(*cur))
21421 cur++;
21422 end = cur;
21423 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21424 end++;
21425 if (end == cur)
21426 break;
21427 count++;
21428 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021429 cur = end;
21430 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21431 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021432 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021433 VERROR_INT("xmlSchemaAssembleByXSI",
21434 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021435 return (-1);
21436 }
21437 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021438 return (ret);
21439}
21440
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021441static const xmlChar *
21442xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21443 const xmlChar *prefix)
21444{
21445 if (vctxt->sax != NULL) {
21446 int i, j;
21447 xmlSchemaNodeInfoPtr inode;
21448
21449 for (i = vctxt->depth; i >= 0; i--) {
21450 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21451 inode = vctxt->elemInfos[i];
21452 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21453 if (((prefix == NULL) &&
21454 (inode->nsBindings[j] == NULL)) ||
21455 ((prefix != NULL) && xmlStrEqual(prefix,
21456 inode->nsBindings[j]))) {
21457
21458 /*
21459 * Note that the namespace bindings are already
21460 * in a string dict.
21461 */
21462 return (inode->nsBindings[j+1]);
21463 }
21464 }
21465 }
21466 }
21467 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021468#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021469 } else if (vctxt->reader != NULL) {
21470 xmlChar *nsName;
21471
21472 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21473 if (nsName != NULL) {
21474 const xmlChar *ret;
21475
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021476 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21477 xmlFree(nsName);
21478 return (ret);
21479 } else
21480 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021481#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021482 } else {
21483 xmlNsPtr ns;
21484
21485 if ((vctxt->inode->node == NULL) ||
21486 (vctxt->inode->node->doc == NULL)) {
21487 VERROR_INT("xmlSchemaLookupNamespace",
21488 "no node or node's doc avaliable");
21489 return (NULL);
21490 }
21491 ns = xmlSearchNs(vctxt->inode->node->doc,
21492 vctxt->inode->node, prefix);
21493 if (ns != NULL)
21494 return (ns->href);
21495 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021496 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021497}
21498
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021499/*
21500* This one works on the schema of the validation context.
21501*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021502static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021503xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21504 xmlSchemaPtr schema,
21505 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021506 const xmlChar *value,
21507 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021508 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021509{
21510 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021511
21512 if (vctxt && (vctxt->schema == NULL)) {
21513 VERROR_INT("xmlSchemaValidateNotation",
21514 "a schema is needed on the validation context");
21515 return (-1);
21516 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021517 ret = xmlValidateQName(value, 1);
21518 if (ret != 0)
21519 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021520 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021521 xmlChar *localName = NULL;
21522 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021523
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021524 localName = xmlSplitQName2(value, &prefix);
21525 if (prefix != NULL) {
21526 const xmlChar *nsName = NULL;
21527
21528 if (vctxt != NULL)
21529 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21530 else if (node != NULL) {
21531 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21532 if (ns != NULL)
21533 nsName = ns->href;
21534 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021535 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021536 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021537 return (1);
21538 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021539 if (nsName == NULL) {
21540 xmlFree(prefix);
21541 xmlFree(localName);
21542 return (1);
21543 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021544 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021545 if (valNeeded && (val != NULL)) {
21546 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21547 BAD_CAST xmlStrdup(nsName));
21548 if (*val == NULL)
21549 ret = -1;
21550 }
21551 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021552 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021553 xmlFree(prefix);
21554 xmlFree(localName);
21555 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021556 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021557 if (valNeeded && (val != NULL)) {
21558 (*val) = xmlSchemaNewNOTATIONValue(
21559 BAD_CAST xmlStrdup(value), NULL);
21560 if (*val == NULL)
21561 ret = -1;
21562 }
21563 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021564 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021565 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021566 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021567 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021568}
21569
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021570static int
21571xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21572 const xmlChar* lname,
21573 const xmlChar* nsname)
21574{
21575 int i;
21576
21577 lname = xmlDictLookup(vctxt->dict, lname, -1);
21578 if (lname == NULL)
21579 return(-1);
21580 if (nsname != NULL) {
21581 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21582 if (nsname == NULL)
21583 return(-1);
21584 }
21585 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21586 if ((vctxt->nodeQNames->items [i] == lname) &&
21587 (vctxt->nodeQNames->items[i +1] == nsname))
21588 /* Already there */
21589 return(i);
21590 }
21591 /* Add new entry. */
21592 i = vctxt->nodeQNames->nbItems;
21593 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21594 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21595 return(i);
21596}
21597
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021598/************************************************************************
21599 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021600 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021601 * *
21602 ************************************************************************/
21603
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021604/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021605 * xmlSchemaAugmentIDC:
21606 * @idcDef: the IDC definition
21607 *
21608 * Creates an augmented IDC definition item.
21609 *
21610 * Returns the item, or NULL on internal errors.
21611 */
21612static void
21613xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21614 xmlSchemaValidCtxtPtr vctxt)
21615{
21616 xmlSchemaIDCAugPtr aidc;
21617
21618 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21619 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021620 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021621 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21622 NULL);
21623 return;
21624 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021625 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021626 aidc->def = idcDef;
21627 aidc->next = NULL;
21628 if (vctxt->aidcs == NULL)
21629 vctxt->aidcs = aidc;
21630 else {
21631 aidc->next = vctxt->aidcs;
21632 vctxt->aidcs = aidc;
21633 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021634 /*
21635 * Save if we have keyrefs at all.
21636 */
21637 if ((vctxt->hasKeyrefs == 0) &&
21638 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21639 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021640}
21641
21642/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021643 * xmlSchemaIDCNewBinding:
21644 * @idcDef: the IDC definition of this binding
21645 *
21646 * Creates a new IDC binding.
21647 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021648 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021649 */
21650static xmlSchemaPSVIIDCBindingPtr
21651xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21652{
21653 xmlSchemaPSVIIDCBindingPtr ret;
21654
21655 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21656 sizeof(xmlSchemaPSVIIDCBinding));
21657 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021658 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021659 "allocating a PSVI IDC binding item", NULL);
21660 return (NULL);
21661 }
21662 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21663 ret->definition = idcDef;
21664 return (ret);
21665}
21666
21667/**
21668 * xmlSchemaIDCStoreNodeTableItem:
21669 * @vctxt: the WXS validation context
21670 * @item: the IDC node table item
21671 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021672 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021673 * They are stored to avoid copying them if IDC node-tables are merged
21674 * with corresponding parent IDC node-tables (bubbling).
21675 *
21676 * Returns 0 if succeeded, -1 on internal errors.
21677 */
21678static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021679xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021680 xmlSchemaPSVIIDCNodePtr item)
21681{
21682 /*
21683 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021684 */
21685 if (vctxt->idcNodes == NULL) {
21686 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021687 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21688 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021689 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021690 "allocating the IDC node table item list", NULL);
21691 return (-1);
21692 }
21693 vctxt->sizeIdcNodes = 20;
21694 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21695 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021696 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21697 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021698 sizeof(xmlSchemaPSVIIDCNodePtr));
21699 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021700 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021701 "re-allocating the IDC node table item list", NULL);
21702 return (-1);
21703 }
21704 }
21705 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021706
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021707 return (0);
21708}
21709
21710/**
21711 * xmlSchemaIDCStoreKey:
21712 * @vctxt: the WXS validation context
21713 * @item: the IDC key
21714 *
21715 * The validation context is used to store an IDC key.
21716 *
21717 * Returns 0 if succeeded, -1 on internal errors.
21718 */
21719static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021720xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021721 xmlSchemaPSVIIDCKeyPtr key)
21722{
21723 /*
21724 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021725 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021726 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021727 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021728 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21729 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021730 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021731 "allocating the IDC key storage list", NULL);
21732 return (-1);
21733 }
21734 vctxt->sizeIdcKeys = 40;
21735 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21736 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021737 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21738 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021739 sizeof(xmlSchemaPSVIIDCKeyPtr));
21740 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021741 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021742 "re-allocating the IDC key storage list", NULL);
21743 return (-1);
21744 }
21745 }
21746 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021747
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021748 return (0);
21749}
21750
21751/**
21752 * xmlSchemaIDCAppendNodeTableItem:
21753 * @bind: the IDC binding
21754 * @ntItem: the node-table item
21755 *
21756 * Appends the IDC node-table item to the binding.
21757 *
21758 * Returns 0 on success and -1 on internal errors.
21759 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021760static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021761xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21762 xmlSchemaPSVIIDCNodePtr ntItem)
21763{
21764 if (bind->nodeTable == NULL) {
21765 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021766 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021767 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21768 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021769 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021770 "allocating an array of IDC node-table items", NULL);
21771 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021772 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021773 } else if (bind->sizeNodes <= bind->nbNodes) {
21774 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021775 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21776 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021777 sizeof(xmlSchemaPSVIIDCNodePtr));
21778 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021779 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021780 "re-allocating an array of IDC node-table items", NULL);
21781 return(-1);
21782 }
21783 }
21784 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021785 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021786}
21787
21788/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021789 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021790 * @vctxt: the WXS validation context
21791 * @matcher: the IDC matcher
21792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021793 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021794 * of the given matcher. If none found, a new one is created
21795 * and added to the IDC table.
21796 *
21797 * Returns an IDC binding or NULL on internal errors.
21798 */
21799static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021800xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021801 xmlSchemaIDCMatcherPtr matcher)
21802{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021803 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021804
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021805 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021806
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021807 if (ielem->idcTable == NULL) {
21808 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21809 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021810 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021811 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021812 } else {
21813 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021814
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021815 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021816 do {
21817 if (bind->definition == matcher->aidc->def)
21818 return(bind);
21819 if (bind->next == NULL) {
21820 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21821 if (bind->next == NULL)
21822 return (NULL);
21823 return(bind->next);
21824 }
21825 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021826 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021827 }
21828 return (NULL);
21829}
21830
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021831static xmlSchemaItemListPtr
21832xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21833 xmlSchemaIDCMatcherPtr matcher)
21834{
21835 if (matcher->targets == NULL)
21836 matcher->targets = xmlSchemaItemListCreate();
21837 return(matcher->targets);
21838}
21839
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021840/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021841 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021842 * @key: the IDC key
21843 *
21844 * Frees an IDC key together with its compiled value.
21845 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021846static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021847xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21848{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021849 if (key->val != NULL)
21850 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021851 xmlFree(key);
21852}
21853
21854/**
21855 * xmlSchemaIDCFreeBinding:
21856 *
21857 * Frees an IDC binding. Note that the node table-items
21858 * are not freed.
21859 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021860static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021861xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21862{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021863 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021864 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021865 if (bind->dupls != NULL)
21866 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021867 xmlFree(bind);
21868}
21869
21870/**
21871 * xmlSchemaIDCFreeIDCTable:
21872 * @bind: the first IDC binding in the list
21873 *
21874 * Frees an IDC table, i.e. all the IDC bindings in the list.
21875 */
21876static void
21877xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21878{
21879 xmlSchemaPSVIIDCBindingPtr prev;
21880
21881 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021882 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021883 bind = bind->next;
21884 xmlSchemaIDCFreeBinding(prev);
21885 }
21886}
21887
21888/**
21889 * xmlSchemaIDCFreeMatcherList:
21890 * @matcher: the first IDC matcher in the list
21891 *
21892 * Frees a list of IDC matchers.
21893 */
21894static void
21895xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21896{
21897 xmlSchemaIDCMatcherPtr next;
21898
21899 while (matcher != NULL) {
21900 next = matcher->next;
21901 if (matcher->keySeqs != NULL) {
21902 int i;
21903 for (i = 0; i < matcher->sizeKeySeqs; i++)
21904 if (matcher->keySeqs[i] != NULL)
21905 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021906 xmlFree(matcher->keySeqs);
21907 }
21908 if (matcher->targets != NULL) {
21909 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21910 int i;
21911 xmlSchemaPSVIIDCNodePtr idcNode;
21912 /*
21913 * Node-table items for keyrefs are not stored globally
21914 * to the validation context, since they are not bubbled.
21915 * We need to free them here.
21916 */
21917 for (i = 0; i < matcher->targets->nbItems; i++) {
21918 idcNode =
21919 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21920 xmlFree(idcNode->keys);
21921 xmlFree(idcNode);
21922 }
21923 }
21924 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021925 }
21926 xmlFree(matcher);
21927 matcher = next;
21928 }
21929}
21930
21931/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021932 * xmlSchemaIDCAddStateObject:
21933 * @vctxt: the WXS validation context
21934 * @matcher: the IDC matcher
21935 * @sel: the XPath information
21936 * @parent: the parent "selector" state object if any
21937 * @type: "selector" or "field"
21938 *
21939 * Creates/reuses and activates state objects for the given
21940 * XPath information; if the XPath expression consists of unions,
21941 * multiple state objects are created for every unioned expression.
21942 *
21943 * Returns 0 on success and -1 on internal errors.
21944 */
21945static int
21946xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21947 xmlSchemaIDCMatcherPtr matcher,
21948 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021949 int type)
21950{
21951 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021952
21953 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021954 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021955 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021956 if (vctxt->xpathStatePool != NULL) {
21957 sto = vctxt->xpathStatePool;
21958 vctxt->xpathStatePool = sto->next;
21959 sto->next = NULL;
21960 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021961 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021962 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021963 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021964 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21965 if (sto == NULL) {
21966 xmlSchemaVErrMemory(NULL,
21967 "allocating an IDC state object", NULL);
21968 return (-1);
21969 }
21970 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21971 }
21972 /*
21973 * Add to global list.
21974 */
21975 if (vctxt->xpathStates != NULL)
21976 sto->next = vctxt->xpathStates;
21977 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021978
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021979 /*
21980 * Free the old xpath validation context.
21981 */
21982 if (sto->xpathCtxt != NULL)
21983 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
21984
21985 /*
21986 * Create a new XPath (pattern) validation context.
21987 */
21988 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
21989 (xmlPatternPtr) sel->xpathComp);
21990 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021991 VERROR_INT("xmlSchemaIDCAddStateObject",
21992 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021993 return (-1);
21994 }
21995 sto->type = type;
21996 sto->depth = vctxt->depth;
21997 sto->matcher = matcher;
21998 sto->sel = sel;
21999 sto->nbHistory = 0;
22000
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022001#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022002 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22003 sto->sel->xpath);
22004#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022005 return (0);
22006}
22007
22008/**
22009 * xmlSchemaXPathEvaluate:
22010 * @vctxt: the WXS validation context
22011 * @nodeType: the nodeType of the current node
22012 *
22013 * Evaluates all active XPath state objects.
22014 *
22015 * Returns the number of IC "field" state objects which resolved to
22016 * this node, 0 if none resolved and -1 on internal errors.
22017 */
22018static int
22019xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022020 xmlElementType nodeType)
22021{
22022 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022023 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022024
22025 if (vctxt->xpathStates == NULL)
22026 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022027
22028 if (nodeType == XML_ATTRIBUTE_NODE)
22029 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022030#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022031 {
22032 xmlChar *str = NULL;
22033 xmlGenericError(xmlGenericErrorContext,
22034 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022035 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22036 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022037 FREE_AND_NULL(str)
22038 }
22039#endif
22040 /*
22041 * Process all active XPath state objects.
22042 */
22043 first = vctxt->xpathStates;
22044 sto = first;
22045 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022046#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022047 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022048 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22049 sto->matcher->aidc->def->name, sto->sel->xpath);
22050 else
22051 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22052 sto->matcher->aidc->def->name, sto->sel->xpath);
22053#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022054 if (nodeType == XML_ELEMENT_NODE)
22055 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022056 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022057 else
22058 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022059 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022060
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022061 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022062 VERROR_INT("xmlSchemaXPathEvaluate",
22063 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022064 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022065 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022066 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022067 goto next_sto;
22068 /*
22069 * Full match.
22070 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022071#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022072 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022073 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022074#endif
22075 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022076 * Register a match in the state object history.
22077 */
22078 if (sto->history == NULL) {
22079 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22080 if (sto->history == NULL) {
22081 xmlSchemaVErrMemory(NULL,
22082 "allocating the state object history", NULL);
22083 return(-1);
22084 }
22085 sto->sizeHistory = 10;
22086 } else if (sto->sizeHistory <= sto->nbHistory) {
22087 sto->sizeHistory *= 2;
22088 sto->history = (int *) xmlRealloc(sto->history,
22089 sto->sizeHistory * sizeof(int));
22090 if (sto->history == NULL) {
22091 xmlSchemaVErrMemory(NULL,
22092 "re-allocating the state object history", NULL);
22093 return(-1);
22094 }
22095 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022096 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022097
22098#ifdef DEBUG_IDC
22099 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22100 vctxt->depth);
22101#endif
22102
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022103 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22104 xmlSchemaIDCSelectPtr sel;
22105 /*
22106 * Activate state objects for the IDC fields of
22107 * the IDC selector.
22108 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022109#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022110 xmlGenericError(xmlGenericErrorContext, "IDC: "
22111 "activating field states\n");
22112#endif
22113 sel = sto->matcher->aidc->def->fields;
22114 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022115 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22116 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22117 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022118 sel = sel->next;
22119 }
22120 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22121 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022122 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022123 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022124#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022125 xmlGenericError(xmlGenericErrorContext,
22126 "IDC: key found\n");
22127#endif
22128 /*
22129 * Notify that the character value of this node is
22130 * needed.
22131 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022132 if (resolved == 0) {
22133 if ((vctxt->inode->flags &
22134 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22135 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22136 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022137 resolved++;
22138 }
22139next_sto:
22140 if (sto->next == NULL) {
22141 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022142 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022143 */
22144 head = first;
22145 sto = vctxt->xpathStates;
22146 } else
22147 sto = sto->next;
22148 }
22149 return (resolved);
22150}
22151
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022152static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022153xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022154 xmlChar **buf,
22155 xmlSchemaPSVIIDCKeyPtr *seq,
22156 int count)
22157{
22158 int i, res;
22159 const xmlChar *value = NULL;
22160
22161 *buf = xmlStrdup(BAD_CAST "[");
22162 for (i = 0; i < count; i++) {
22163 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022164 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
22165 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022166 if (res == 0)
22167 *buf = xmlStrcat(*buf, value);
22168 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022169 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22170 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022171 *buf = xmlStrcat(*buf, BAD_CAST "???");
22172 }
22173 if (i < count -1)
22174 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22175 else
22176 *buf = xmlStrcat(*buf, BAD_CAST "'");
22177 if (value != NULL) {
22178 xmlFree((xmlChar *) value);
22179 value = NULL;
22180 }
22181 }
22182 *buf = xmlStrcat(*buf, BAD_CAST "]");
22183
22184 return (BAD_CAST *buf);
22185}
22186
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022187/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022188 * xmlSchemaXPathPop:
22189 * @vctxt: the WXS validation context
22190 *
22191 * Pops all XPath states.
22192 *
22193 * Returns 0 on success and -1 on internal errors.
22194 */
22195static int
22196xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22197{
22198 xmlSchemaIDCStateObjPtr sto;
22199 int res;
22200
22201 if (vctxt->xpathStates == NULL)
22202 return(0);
22203 sto = vctxt->xpathStates;
22204 do {
22205 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22206 if (res == -1)
22207 return (-1);
22208 sto = sto->next;
22209 } while (sto != NULL);
22210 return(0);
22211}
22212
22213/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022214 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022215 * @vctxt: the WXS validation context
22216 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022217 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022218 *
22219 * Processes and pops the history items of the IDC state objects.
22220 * IDC key-sequences are validated/created on IDC bindings.
22221 *
22222 * Returns 0 on success and -1 on internal errors.
22223 */
22224static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022225xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022226 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022227{
22228 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022229 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022230 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022231 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022232
22233 if (vctxt->xpathStates == NULL)
22234 return (0);
22235 sto = vctxt->xpathStates;
22236
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022237#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022238 {
22239 xmlChar *str = NULL;
22240 xmlGenericError(xmlGenericErrorContext,
22241 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022242 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22243 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022244 FREE_AND_NULL(str)
22245 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022246#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022247 /*
22248 * Evaluate the state objects.
22249 */
22250 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022251 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22252 if (res == -1) {
22253 VERROR_INT("xmlSchemaXPathProcessHistory",
22254 "calling xmlStreamPop()");
22255 return (-1);
22256 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022257#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022258 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22259 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022260#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022261 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022262 goto deregister_check;
22263
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022264 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022265
22266 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022267 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022268 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022269 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022270 sto = sto->next;
22271 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022272 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022273 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022274 /*
22275 * NOTE: According to
22276 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22277 * ... the simple-content of complex types is also allowed.
22278 */
22279
22280 if (WXS_IS_COMPLEX(type)) {
22281 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22282 /*
22283 * Sanity check for complex types with simple content.
22284 */
22285 simpleType = type->contentTypeDef;
22286 if (simpleType == NULL) {
22287 VERROR_INT("xmlSchemaXPathProcessHistory",
22288 "field resolves to a CT with simple content "
22289 "but the CT is missing the ST definition");
22290 return (-1);
22291 }
22292 } else
22293 simpleType = NULL;
22294 } else
22295 simpleType = type;
22296 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022297 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022298
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022299 /*
22300 * Not qualified if the field resolves to a node of non
22301 * simple type.
22302 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022303 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022304 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022305 WXS_BASIC_CAST sto->matcher->aidc->def,
22306 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022307 "non-simple type",
22308 sto->sel->xpath,
22309 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22310 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022311 sto->nbHistory--;
22312 goto deregister_check;
22313 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022314
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022315 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022316 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022317 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022318 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022319 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022320 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022321 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022322 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022323 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022324 sto->nbHistory--;
22325 goto deregister_check;
22326 } else {
22327 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22328 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022329 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022330
22331 /*
22332 * The key will be anchored on the matcher's list of
22333 * key-sequences. The position in this list is determined
22334 * by the target node's depth relative to the matcher's
22335 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022336 *
22337 * Element Depth Pos List-entries
22338 * <scope> 0 NULL
22339 * <bar> 1 NULL
22340 * <target/> 2 2 target
22341 * <bar>
22342 * </scope>
22343 *
22344 * The size of the list is only dependant on the depth of
22345 * the tree.
22346 * An entry will be NULLed in selector_leave, i.e. when
22347 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022348 */
22349 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022350 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022351
22352 /*
22353 * Create/grow the array of key-sequences.
22354 */
22355 if (matcher->keySeqs == NULL) {
22356 if (pos > 9)
22357 matcher->sizeKeySeqs = pos * 2;
22358 else
22359 matcher->sizeKeySeqs = 10;
22360 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22361 xmlMalloc(matcher->sizeKeySeqs *
22362 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22363 if (matcher->keySeqs == NULL) {
22364 xmlSchemaVErrMemory(NULL,
22365 "allocating an array of key-sequences",
22366 NULL);
22367 return(-1);
22368 }
22369 memset(matcher->keySeqs, 0,
22370 matcher->sizeKeySeqs *
22371 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22372 } else if (pos >= matcher->sizeKeySeqs) {
22373 int i = matcher->sizeKeySeqs;
22374
22375 matcher->sizeKeySeqs *= 2;
22376 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22377 xmlRealloc(matcher->keySeqs,
22378 matcher->sizeKeySeqs *
22379 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022380 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022381 xmlSchemaVErrMemory(NULL,
22382 "reallocating an array of key-sequences",
22383 NULL);
22384 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022385 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022386 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022387 * The array needs to be NULLed.
22388 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022389 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022390 for (; i < matcher->sizeKeySeqs; i++)
22391 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022392 }
22393
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022394 /*
22395 * Get/create the key-sequence.
22396 */
22397 keySeq = matcher->keySeqs[pos];
22398 if (keySeq == NULL) {
22399 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022400 } else if (keySeq[idx] != NULL) {
22401 xmlChar *str = NULL;
22402 /*
22403 * cvc-identity-constraint:
22404 * 3 For each node in the ·target node set· all
22405 * of the {fields}, with that node as the context
22406 * node, evaluate to either an empty node-set or
22407 * a node-set with exactly one member, which must
22408 * have a simple type.
22409 *
22410 * The key was already set; report an error.
22411 */
22412 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22413 XML_SCHEMAV_CVC_IDC, NULL,
22414 WXS_BASIC_CAST matcher->aidc->def,
22415 "The XPath '%s' of a field of %s evaluates to a "
22416 "node-set with more than one member",
22417 sto->sel->xpath,
22418 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22419 FREE_AND_NULL(str);
22420 sto->nbHistory--;
22421 goto deregister_check;
22422 } else
22423 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022424
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022425create_sequence:
22426 /*
22427 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022428 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022429 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22430 matcher->aidc->def->nbFields *
22431 sizeof(xmlSchemaPSVIIDCKeyPtr));
22432 if (keySeq == NULL) {
22433 xmlSchemaVErrMemory(NULL,
22434 "allocating an IDC key-sequence", NULL);
22435 return(-1);
22436 }
22437 memset(keySeq, 0, matcher->aidc->def->nbFields *
22438 sizeof(xmlSchemaPSVIIDCKeyPtr));
22439 matcher->keySeqs[pos] = keySeq;
22440create_key:
22441 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022442 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022443 */
22444 if (key == NULL) {
22445 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22446 sizeof(xmlSchemaPSVIIDCKey));
22447 if (key == NULL) {
22448 xmlSchemaVErrMemory(NULL,
22449 "allocating a IDC key", NULL);
22450 xmlFree(keySeq);
22451 matcher->keySeqs[pos] = NULL;
22452 return(-1);
22453 }
22454 /*
22455 * Consume the compiled value.
22456 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022457 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022458 key->val = vctxt->inode->val;
22459 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022460 /*
22461 * Store the key in a global list.
22462 */
22463 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22464 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022465 return (-1);
22466 }
22467 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022468 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022469 }
22470 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022471
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022472 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022473 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022474 xmlSchemaPSVIIDCNodePtr ntItem;
22475 xmlSchemaIDCMatcherPtr matcher;
22476 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022477 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022478 int pos, i, j, nbKeys;
22479 /*
22480 * Here we have the following scenario:
22481 * An IDC 'selector' state object resolved to a target node,
22482 * during the time this target node was in the
22483 * ancestor-or-self axis, the 'field' state object(s) looked
22484 * out for matching nodes to create a key-sequence for this
22485 * target node. Now we are back to this target node and need
22486 * to put the key-sequence, together with the target node
22487 * itself, into the node-table of the corresponding IDC
22488 * binding.
22489 */
22490 matcher = sto->matcher;
22491 idc = matcher->aidc->def;
22492 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022493 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022494 /*
22495 * Check if the matcher has any key-sequences at all, plus
22496 * if it has a key-sequence for the current target node.
22497 */
22498 if ((matcher->keySeqs == NULL) ||
22499 (matcher->sizeKeySeqs <= pos)) {
22500 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22501 goto selector_key_error;
22502 else
22503 goto selector_leave;
22504 }
22505
22506 keySeq = &(matcher->keySeqs[pos]);
22507 if (*keySeq == NULL) {
22508 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22509 goto selector_key_error;
22510 else
22511 goto selector_leave;
22512 }
22513
22514 for (i = 0; i < nbKeys; i++) {
22515 if ((*keySeq)[i] == NULL) {
22516 /*
22517 * Not qualified, if not all fields did resolve.
22518 */
22519 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22520 /*
22521 * All fields of a "key" IDC must resolve.
22522 */
22523 goto selector_key_error;
22524 }
22525 goto selector_leave;
22526 }
22527 }
22528 /*
22529 * All fields did resolve.
22530 */
22531
22532 /*
22533 * 4.1 If the {identity-constraint category} is unique(/key),
22534 * then no two members of the ·qualified node set· have
22535 * ·key-sequences· whose members are pairwise equal, as
22536 * defined by Equal in [XML Schemas: Datatypes].
22537 *
22538 * Get the IDC binding from the matcher and check for
22539 * duplicate key-sequences.
22540 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022541#if 0
22542 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22543#endif
22544 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022545 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022546 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022547 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022548
22549 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022550 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022551 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022552 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022553 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022554 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022555 bkeySeq =
22556 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022557 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022558 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022559 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022560 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022561 if (res == -1) {
22562 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022563 } else if (res == 0) {
22564 /*
22565 * One of the keys differs, so the key-sequence
22566 * won't be equal; get out.
22567 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022568 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022569 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022570 }
22571 if (res == 1) {
22572 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022573 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022574 */
22575 break;
22576 }
22577 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022578 } while (i < targets->nbItems);
22579 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022580 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022581 /*
22582 * TODO: Try to report the key-sequence.
22583 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022584 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022585 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022586 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022587 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022588 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022589 (*keySeq), nbKeys),
22590 xmlSchemaGetIDCDesignation(&strB, idc));
22591 FREE_AND_NULL(str);
22592 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022593 goto selector_leave;
22594 }
22595 }
22596 /*
22597 * Add a node-table item to the IDC binding.
22598 */
22599 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22600 sizeof(xmlSchemaPSVIIDCNode));
22601 if (ntItem == NULL) {
22602 xmlSchemaVErrMemory(NULL,
22603 "allocating an IDC node-table item", NULL);
22604 xmlFree(*keySeq);
22605 *keySeq = NULL;
22606 return(-1);
22607 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022608 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022609
22610 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022611 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022612 */
22613 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22614 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22615 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022616 xmlFree(*keySeq);
22617 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022618 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022619 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022620 ntItem->nodeQNameID = -1;
22621 } else {
22622 /*
22623 * Save a cached QName for this node on the IDC node, to be
22624 * able to report it, even if the node is not saved.
22625 */
22626 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22627 vctxt->inode->localName, vctxt->inode->nsName);
22628 if (ntItem->nodeQNameID == -1) {
22629 xmlFree(ntItem);
22630 xmlFree(*keySeq);
22631 *keySeq = NULL;
22632 return (-1);
22633 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022634 }
22635 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022636 * Init the node-table item: Save the node, position and
22637 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022638 */
22639 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022640 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022641 ntItem->keys = *keySeq;
22642 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022643#if 0
22644 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22645#endif
22646 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022647 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22648 /*
22649 * Free the item, since keyref items won't be
22650 * put on a global list.
22651 */
22652 xmlFree(ntItem->keys);
22653 xmlFree(ntItem);
22654 }
22655 return (-1);
22656 }
22657
22658 goto selector_leave;
22659selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022660 {
22661 xmlChar *str = NULL;
22662 /*
22663 * 4.2.1 (KEY) The ·target node set· and the
22664 * ·qualified node set· are equal, that is, every
22665 * member of the ·target node set· is also a member
22666 * of the ·qualified node set· and vice versa.
22667 */
22668 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22669 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022670 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022671 "Not all fields of %s evaluate to a node",
22672 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22673 FREE_AND_NULL(str);
22674 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022675selector_leave:
22676 /*
22677 * Free the key-sequence if not added to the IDC table.
22678 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022679 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022680 xmlFree(*keySeq);
22681 *keySeq = NULL;
22682 }
22683 } /* if selector */
22684
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022685 sto->nbHistory--;
22686
22687deregister_check:
22688 /*
22689 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022690 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022691 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022692#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022693 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22694 sto->sel->xpath);
22695#endif
22696 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022697 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022698 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022699 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022700 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022701 nextsto = sto->next;
22702 /*
22703 * Unlink from the list of active XPath state objects.
22704 */
22705 vctxt->xpathStates = sto->next;
22706 sto->next = vctxt->xpathStatePool;
22707 /*
22708 * Link it to the pool of reusable state objects.
22709 */
22710 vctxt->xpathStatePool = sto;
22711 sto = nextsto;
22712 } else
22713 sto = sto->next;
22714 } /* while (sto != NULL) */
22715 return (0);
22716}
22717
22718/**
22719 * xmlSchemaIDCRegisterMatchers:
22720 * @vctxt: the WXS validation context
22721 * @elemDecl: the element declaration
22722 *
22723 * Creates helper objects to evaluate IDC selectors/fields
22724 * successively.
22725 *
22726 * Returns 0 if OK and -1 on internal errors.
22727 */
22728static int
22729xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22730 xmlSchemaElementPtr elemDecl)
22731{
22732 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22733 xmlSchemaIDCPtr idc, refIdc;
22734 xmlSchemaIDCAugPtr aidc;
22735
22736 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22737 if (idc == NULL)
22738 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022739
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022740#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022741 {
22742 xmlChar *str = NULL;
22743 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022744 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022745 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22746 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022747 FREE_AND_NULL(str)
22748 }
22749#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022750 if (vctxt->inode->idcMatchers != NULL) {
22751 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22752 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022753 return (-1);
22754 }
22755 do {
22756 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22757 /*
22758 * Since IDCs bubbles are expensive we need to know the
22759 * depth at which the bubbles should stop; this will be
22760 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022761 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022762 * be -1, indicating that no bubbles are needed.
22763 */
22764 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22765 if (refIdc != NULL) {
22766 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022767 * Remember that we have keyrefs on this node.
22768 */
22769 vctxt->inode->hasKeyrefs = 1;
22770 /*
22771 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022772 */
22773 aidc = vctxt->aidcs;
22774 while (aidc != NULL) {
22775 if (aidc->def == refIdc)
22776 break;
22777 aidc = aidc->next;
22778 }
22779 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022780 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022781 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022782 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022783 return (-1);
22784 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022785 if ((aidc->keyrefDepth == -1) ||
22786 (vctxt->depth < aidc->keyrefDepth))
22787 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022788 }
22789 }
22790 /*
22791 * Lookup the augmented IDC item for the IDC definition.
22792 */
22793 aidc = vctxt->aidcs;
22794 while (aidc != NULL) {
22795 if (aidc->def == idc)
22796 break;
22797 aidc = aidc->next;
22798 }
22799 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022800 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22801 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022802 return (-1);
22803 }
22804 /*
22805 * Create an IDC matcher for every IDC definition.
22806 */
22807 matcher = (xmlSchemaIDCMatcherPtr)
22808 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22809 if (matcher == NULL) {
22810 xmlSchemaVErrMemory(vctxt,
22811 "allocating an IDC matcher", NULL);
22812 return (-1);
22813 }
22814 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22815 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022816 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022817 else
22818 last->next = matcher;
22819 last = matcher;
22820
22821 matcher->type = IDC_MATCHER;
22822 matcher->depth = vctxt->depth;
22823 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022824 matcher->idcType = aidc->def->type;
22825#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022826 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22827#endif
22828 /*
22829 * Init the automaton state object.
22830 */
22831 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022832 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022833 return (-1);
22834
22835 idc = idc->next;
22836 } while (idc != NULL);
22837 return (0);
22838}
22839
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022840static int
22841xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22842 xmlSchemaNodeInfoPtr ielem)
22843{
22844 xmlSchemaPSVIIDCBindingPtr bind;
22845 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22846 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22847 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22848
22849 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22850 /* vctxt->createIDCNodeTables */
22851 while (matcher != NULL) {
22852 /*
22853 * Skip keyref IDCs and empty IDC target-lists.
22854 */
22855 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22856 WXS_ILIST_IS_EMPTY(matcher->targets))
22857 {
22858 matcher = matcher->next;
22859 continue;
22860 }
22861 /*
22862 * If we _want_ the IDC node-table to be created in any case
22863 * then do so. Otherwise create them only if keyrefs need them.
22864 */
22865 if ((! vctxt->createIDCNodeTables) &&
22866 ((matcher->aidc->keyrefDepth == -1) ||
22867 (matcher->aidc->keyrefDepth > vctxt->depth)))
22868 {
22869 matcher = matcher->next;
22870 continue;
22871 }
22872 /*
22873 * Get/create the IDC binding on this element for the IDC definition.
22874 */
22875 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22876
22877 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22878 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22879 nbDupls = bind->dupls->nbItems;
22880 } else {
22881 dupls = NULL;
22882 nbDupls = 0;
22883 }
22884 if (bind->nodeTable != NULL) {
22885 nbNodeTable = bind->nbNodes;
22886 } else {
22887 nbNodeTable = 0;
22888 }
22889
22890 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22891 /*
22892 * Transfer all IDC target-nodes to the IDC node-table.
22893 */
22894 bind->nodeTable =
22895 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22896 bind->sizeNodes = matcher->targets->sizeItems;
22897 bind->nbNodes = matcher->targets->nbItems;
22898
22899 matcher->targets->items = NULL;
22900 matcher->targets->sizeItems = 0;
22901 matcher->targets->nbItems = 0;
22902 } else {
22903 /*
22904 * Compare the key-sequences and add to the IDC node-table.
22905 */
22906 nbTargets = matcher->targets->nbItems;
22907 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22908 nbFields = matcher->aidc->def->nbFields;
22909 i = 0;
22910 do {
22911 keys = targets[i]->keys;
22912 if (nbDupls) {
22913 /*
22914 * Search in already found duplicates first.
22915 */
22916 j = 0;
22917 do {
22918 if (nbFields == 1) {
22919 res = xmlSchemaAreValuesEqual(keys[0]->val,
22920 dupls[j]->keys[0]->val);
22921 if (res == -1)
22922 goto internal_error;
22923 if (res == 1) {
22924 /*
22925 * Equal key-sequence.
22926 */
22927 goto next_target;
22928 }
22929 } else {
22930 res = 0;
22931 ntkeys = dupls[j]->keys;
22932 for (k = 0; k < nbFields; k++) {
22933 res = xmlSchemaAreValuesEqual(keys[k]->val,
22934 ntkeys[k]->val);
22935 if (res == -1)
22936 goto internal_error;
22937 if (res == 0) {
22938 /*
22939 * One of the keys differs.
22940 */
22941 break;
22942 }
22943 }
22944 if (res == 1) {
22945 /*
22946 * Equal key-sequence found.
22947 */
22948 goto next_target;
22949 }
22950 }
22951 j++;
22952 } while (j < nbDupls);
22953 }
22954 if (nbNodeTable) {
22955 j = 0;
22956 do {
22957 if (nbFields == 1) {
22958 res = xmlSchemaAreValuesEqual(keys[0]->val,
22959 bind->nodeTable[j]->keys[0]->val);
22960 if (res == -1)
22961 goto internal_error;
22962 if (res == 0) {
22963 /*
22964 * The key-sequence differs.
22965 */
22966 goto next_node_table_entry;
22967 }
22968 } else {
22969 res = 0;
22970 ntkeys = bind->nodeTable[j]->keys;
22971 for (k = 0; k < nbFields; k++) {
22972 res = xmlSchemaAreValuesEqual(keys[k]->val,
22973 ntkeys[k]->val);
22974 if (res == -1)
22975 goto internal_error;
22976 if (res == 0) {
22977 /*
22978 * One of the keys differs.
22979 */
22980 goto next_node_table_entry;
22981 }
22982 }
22983 }
22984 /*
22985 * Add the duplicate to the list of duplicates.
22986 */
22987 if (bind->dupls == NULL) {
22988 bind->dupls = xmlSchemaItemListCreate();
22989 if (bind->dupls == NULL)
22990 goto internal_error;
22991 }
22992 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
22993 goto internal_error;
22994 /*
22995 * Remove the duplicate entry from the IDC node-table.
22996 */
22997 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
22998 bind->nbNodes--;
22999
23000 goto next_target;
23001
23002next_node_table_entry:
23003 j++;
23004 } while (j < nbNodeTable);
23005 }
23006 /*
23007 * If everything is fine, then add the IDC target-node to
23008 * the IDC node-table.
23009 */
23010 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23011 goto internal_error;
23012
23013next_target:
23014 i++;
23015 } while (i < nbTargets);
23016 }
23017 matcher = matcher->next;
23018 }
23019 return(0);
23020
23021internal_error:
23022 return(-1);
23023}
23024
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023025/**
23026 * xmlSchemaBubbleIDCNodeTables:
23027 * @depth: the current tree depth
23028 *
23029 * Merges IDC bindings of an element at @depth into the corresponding IDC
23030 * bindings of its parent element. If a duplicate note-table entry is found,
23031 * both, the parent node-table entry and child entry are discarded from the
23032 * node-table of the parent.
23033 *
23034 * Returns 0 if OK and -1 on internal errors.
23035 */
23036static int
23037xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23038{
23039 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023040 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23041 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023042 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023043 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023045 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023046 if (bind == NULL) {
23047 /* Fine, no table, no bubbles. */
23048 return (0);
23049 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023050
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023051 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23052 /*
23053 * Walk all bindings; create new or add to existing bindings.
23054 * Remove duplicate key-sequences.
23055 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023056 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023057
23058 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23059 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023060 /*
23061 * Check if the key/unique IDC table needs to be bubbled.
23062 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023063 if (! vctxt->createIDCNodeTables) {
23064 aidc = vctxt->aidcs;
23065 do {
23066 if (aidc->def == bind->definition) {
23067 if ((aidc->keyrefDepth == -1) ||
23068 (aidc->keyrefDepth >= vctxt->depth)) {
23069 goto next_binding;
23070 }
23071 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023072 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023073 aidc = aidc->next;
23074 } while (aidc != NULL);
23075 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023076
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023077 if (parTable != NULL)
23078 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023079 /*
23080 * Search a matching parent binding for the
23081 * IDC definition.
23082 */
23083 while (parBind != NULL) {
23084 if (parBind->definition == bind->definition)
23085 break;
23086 parBind = parBind->next;
23087 }
23088
23089 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023090 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023091 * Compare every node-table entry of the child node,
23092 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023093 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023094 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023095
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023096 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23097 oldDupls = parBind->dupls->nbItems;
23098 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23099 } else {
23100 dupls = NULL;
23101 oldDupls = 0;
23102 }
23103
23104 parNodes = parBind->nodeTable;
23105 nbFields = bind->definition->nbFields;
23106
23107 for (i = 0; i < bind->nbNodes; i++) {
23108 node = bind->nodeTable[i];
23109 if (node == NULL)
23110 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023111 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023112 * ...with every key-sequence of the parent node, already
23113 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023114 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023115 if (oldDupls) {
23116 j = 0;
23117 while (j < oldDupls) {
23118 if (nbFields == 1) {
23119 ret = xmlSchemaAreValuesEqual(
23120 node->keys[0]->val,
23121 dupls[j]->keys[0]->val);
23122 if (ret == -1)
23123 goto internal_error;
23124 if (ret == 0) {
23125 j++;
23126 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023127 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023128 } else {
23129 parNode = dupls[j];
23130 for (k = 0; k < nbFields; k++) {
23131 ret = xmlSchemaAreValuesEqual(
23132 node->keys[k]->val,
23133 parNode->keys[k]->val);
23134 if (ret == -1)
23135 goto internal_error;
23136 if (ret == 0)
23137 break;
23138 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023139 }
23140 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023141 /* Duplicate found. */
23142 break;
23143 j++;
23144 }
23145 if (j != oldDupls) {
23146 /* Duplicate found. Skip this entry. */
23147 continue;
23148 }
23149 }
23150 /*
23151 * ... and with every key-sequence of the parent node.
23152 */
23153 if (oldNum) {
23154 j = 0;
23155 while (j < oldNum) {
23156 if (nbFields == 1) {
23157 ret = xmlSchemaAreValuesEqual(
23158 node->keys[0]->val,
23159 parNodes[j]->keys[0]->val);
23160 if (ret == -1)
23161 goto internal_error;
23162 if (ret == 0) {
23163 j++;
23164 continue;
23165 }
23166 } else {
23167 parNode = parNodes[j];
23168 for (k = 0; k < nbFields; k++) {
23169 ret = xmlSchemaAreValuesEqual(
23170 node->keys[k]->val,
23171 parNode->keys[k]->val);
23172 if (ret == -1)
23173 goto internal_error;
23174 if (ret == 0)
23175 break;
23176 }
23177 }
23178 if (ret == 1)
23179 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023180 break;
23181 j++;
23182 }
23183 if (j != oldNum) {
23184 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023185 * Handle duplicates. Move the duplicate in
23186 * the parent's node-table to the list of
23187 * duplicates.
23188 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023189 oldNum--;
23190 parBind->nbNodes--;
23191 /*
23192 * Move last old item to pos of duplicate.
23193 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023194 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023195
23196 if (parBind->nbNodes != oldNum) {
23197 /*
23198 * If new items exist, move last new item to
23199 * last of old items.
23200 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023201 parNodes[oldNum] =
23202 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023203 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023204 if (parBind->dupls == NULL) {
23205 parBind->dupls = xmlSchemaItemListCreate();
23206 if (parBind->dupls == NULL)
23207 goto internal_error;
23208 }
23209 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023210 } else {
23211 /*
23212 * Add the node-table entry (node and key-sequence) of
23213 * the child node to the node table of the parent node.
23214 */
23215 if (parBind->nodeTable == NULL) {
23216 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023217 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023218 if (parBind->nodeTable == NULL) {
23219 xmlSchemaVErrMemory(NULL,
23220 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023221 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023222 }
23223 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023224 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023225 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023226 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23227 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23228 sizeof(xmlSchemaPSVIIDCNodePtr));
23229 if (parBind->nodeTable == NULL) {
23230 xmlSchemaVErrMemory(NULL,
23231 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023232 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023233 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023234 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023235 /*
23236 * Append the new node-table entry to the 'new node-table
23237 * entries' section.
23238 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023239 parBind->nodeTable[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023240 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023241
23242 }
23243
23244 }
23245 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023246 /*
23247 * No binding for the IDC was found: create a new one and
23248 * copy all node-tables.
23249 */
23250 parBind = xmlSchemaIDCNewBinding(bind->definition);
23251 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023252 goto internal_error;
23253
23254 /*
23255 * TODO: Hmm, how to optimize the initial number of
23256 * allocated entries?
23257 */
23258 if (bind->nbNodes != 0) {
23259 /*
23260 * Add all IDC node-table entries.
23261 */
23262 if (! vctxt->psviExposeIDCNodeTables) {
23263 /*
23264 * Just move the entries.
23265 * NOTE: this is quite save here, since
23266 * all the keyref lookups have already been
23267 * performed.
23268 */
23269 parBind->nodeTable = bind->nodeTable;
23270 bind->nodeTable = NULL;
23271 parBind->sizeNodes = bind->sizeNodes;
23272 bind->sizeNodes = 0;
23273 parBind->nbNodes = bind->nbNodes;
23274 bind->nbNodes = 0;
23275 } else {
23276 /*
23277 * Copy the entries.
23278 */
23279 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23280 xmlMalloc(bind->nbNodes *
23281 sizeof(xmlSchemaPSVIIDCNodePtr));
23282 if (parBind->nodeTable == NULL) {
23283 xmlSchemaVErrMemory(NULL,
23284 "allocating an array of IDC node-table "
23285 "items", NULL);
23286 xmlSchemaIDCFreeBinding(parBind);
23287 goto internal_error;
23288 }
23289 parBind->sizeNodes = bind->nbNodes;
23290 parBind->nbNodes = bind->nbNodes;
23291 memcpy(parBind->nodeTable, bind->nodeTable,
23292 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23293 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023294 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023295 if (bind->dupls) {
23296 /*
23297 * Move the duplicates.
23298 */
23299 if (parBind->dupls != NULL)
23300 xmlSchemaItemListFree(parBind->dupls);
23301 parBind->dupls = bind->dupls;
23302 bind->dupls = NULL;
23303 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023304 if (*parTable == NULL)
23305 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023306 else {
23307 parBind->next = *parTable;
23308 *parTable = parBind;
23309 }
23310 }
23311
23312next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023313 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023314 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023315 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023316
23317internal_error:
23318 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023319}
23320
23321/**
23322 * xmlSchemaCheckCVCIDCKeyRef:
23323 * @vctxt: the WXS validation context
23324 * @elemDecl: the element declaration
23325 *
23326 * Check the cvc-idc-keyref constraints.
23327 */
23328static int
23329xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23330{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023331 xmlSchemaIDCMatcherPtr matcher;
23332 xmlSchemaPSVIIDCBindingPtr bind;
23333
23334 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023335 /*
23336 * Find a keyref.
23337 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023338 while (matcher != NULL) {
23339 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23340 matcher->targets &&
23341 matcher->targets->nbItems)
23342 {
23343 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023344 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023345 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023346
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023347 nbFields = matcher->aidc->def->nbFields;
23348
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023349 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023350 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023351 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023352 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023353 while (bind != NULL) {
23354 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023355 bind->definition)
23356 break;
23357 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023358 }
23359 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023360 /*
23361 * Search for a matching key-sequences.
23362 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023363 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023364 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023365 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023366 if (bind != NULL) {
23367 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023368 for (j = 0; j < bind->nbNodes; j++) {
23369 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023370 for (k = 0; k < nbFields; k++) {
23371 res = xmlSchemaAreValuesEqual(keys[k]->val,
23372 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023373 if (res == 0)
23374 break;
23375 else if (res == -1) {
23376 return (-1);
23377 }
23378 }
23379 if (res == 1) {
23380 /*
23381 * Match found.
23382 */
23383 break;
23384 }
23385 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023386 if ((res == 0) && hasDupls) {
23387 /*
23388 * Search in duplicates
23389 */
23390 for (j = 0; j < bind->dupls->nbItems; j++) {
23391 keys = ((xmlSchemaPSVIIDCNodePtr)
23392 bind->dupls->items[j])->keys;
23393 for (k = 0; k < nbFields; k++) {
23394 res = xmlSchemaAreValuesEqual(keys[k]->val,
23395 refKeys[k]->val);
23396 if (res == 0)
23397 break;
23398 else if (res == -1) {
23399 return (-1);
23400 }
23401 }
23402 if (res == 1) {
23403 /*
23404 * Match in duplicates found.
23405 */
23406 xmlChar *str = NULL, *strB = NULL;
23407 xmlSchemaKeyrefErr(vctxt,
23408 XML_SCHEMAV_CVC_IDC, refNode,
23409 (xmlSchemaTypePtr) matcher->aidc->def,
23410 "More than one match found for "
23411 "key-sequence %s of keyref '%s'",
23412 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23413 refNode->keys, nbFields),
23414 xmlSchemaGetComponentQName(&strB,
23415 matcher->aidc->def));
23416 FREE_AND_NULL(str);
23417 FREE_AND_NULL(strB);
23418 break;
23419 }
23420 }
23421 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023422 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023423
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023424 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023425 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023426 xmlSchemaKeyrefErr(vctxt,
23427 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023428 (xmlSchemaTypePtr) matcher->aidc->def,
23429 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023430 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023431 refNode->keys, nbFields),
23432 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023433 FREE_AND_NULL(str);
23434 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023435 }
23436 }
23437 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023438 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023439 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023440 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023441 return (0);
23442}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023443
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023444/************************************************************************
23445 * *
23446 * XML Reader validation code *
23447 * *
23448 ************************************************************************/
23449
23450static xmlSchemaAttrInfoPtr
23451xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023452{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023453 xmlSchemaAttrInfoPtr iattr;
23454 /*
23455 * Grow/create list of attribute infos.
23456 */
23457 if (vctxt->attrInfos == NULL) {
23458 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23459 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23460 vctxt->sizeAttrInfos = 1;
23461 if (vctxt->attrInfos == NULL) {
23462 xmlSchemaVErrMemory(vctxt,
23463 "allocating attribute info list", NULL);
23464 return (NULL);
23465 }
23466 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23467 vctxt->sizeAttrInfos++;
23468 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23469 xmlRealloc(vctxt->attrInfos,
23470 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23471 if (vctxt->attrInfos == NULL) {
23472 xmlSchemaVErrMemory(vctxt,
23473 "re-allocating attribute info list", NULL);
23474 return (NULL);
23475 }
23476 } else {
23477 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23478 if (iattr->localName != NULL) {
23479 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23480 "attr info not cleared");
23481 return (NULL);
23482 }
23483 iattr->nodeType = XML_ATTRIBUTE_NODE;
23484 return (iattr);
23485 }
23486 /*
23487 * Create an attribute info.
23488 */
23489 iattr = (xmlSchemaAttrInfoPtr)
23490 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23491 if (iattr == NULL) {
23492 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23493 return (NULL);
23494 }
23495 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23496 iattr->nodeType = XML_ATTRIBUTE_NODE;
23497 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23498
23499 return (iattr);
23500}
23501
23502static int
23503xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23504 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023505 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023506 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023507 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023508 int ownedNames,
23509 xmlChar *value,
23510 int ownedValue)
23511{
23512 xmlSchemaAttrInfoPtr attr;
23513
23514 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23515 if (attr == NULL) {
23516 VERROR_INT("xmlSchemaPushAttribute",
23517 "calling xmlSchemaGetFreshAttrInfo()");
23518 return (-1);
23519 }
23520 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023521 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023522 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23523 attr->localName = localName;
23524 attr->nsName = nsName;
23525 if (ownedNames)
23526 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23527 /*
23528 * Evaluate if it's an XSI attribute.
23529 */
23530 if (nsName != NULL) {
23531 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23532 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23533 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23534 }
23535 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23536 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23537 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23538 }
23539 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23540 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23541 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23542 }
23543 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23544 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23545 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23546 }
23547 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23548 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23549 }
23550 }
23551 attr->value = value;
23552 if (ownedValue)
23553 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23554 if (attr->metaType != 0)
23555 attr->state = XML_SCHEMAS_ATTR_META;
23556 return (0);
23557}
23558
23559static void
23560xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23561{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023562 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023563 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023564 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23565 FREE_AND_NULL(ielem->localName);
23566 FREE_AND_NULL(ielem->nsName);
23567 } else {
23568 ielem->localName = NULL;
23569 ielem->nsName = NULL;
23570 }
23571 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23572 FREE_AND_NULL(ielem->value);
23573 } else {
23574 ielem->value = NULL;
23575 }
23576 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023577 /*
23578 * PSVI TODO: Be careful not to free it when the value is
23579 * exposed via PSVI.
23580 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023581 xmlSchemaFreeValue(ielem->val);
23582 ielem->val = NULL;
23583 }
23584 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023585 /*
23586 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023588 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23589 ielem->idcMatchers = NULL;
23590 }
23591 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023592 /*
23593 * OPTIMIZE TODO: Use a pool of IDC tables??.
23594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23596 ielem->idcTable = NULL;
23597 }
23598 if (ielem->regexCtxt != NULL) {
23599 xmlRegFreeExecCtxt(ielem->regexCtxt);
23600 ielem->regexCtxt = NULL;
23601 }
23602 if (ielem->nsBindings != NULL) {
23603 xmlFree((xmlChar **)ielem->nsBindings);
23604 ielem->nsBindings = NULL;
23605 ielem->nbNsBindings = 0;
23606 ielem->sizeNsBindings = 0;
23607 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023608}
23609
23610/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023611 * xmlSchemaGetFreshElemInfo:
23612 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023613 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023614 * Creates/reuses and initializes the element info item for
23615 * the currect tree depth.
23616 *
23617 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023618 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023619static xmlSchemaNodeInfoPtr
23620xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023621{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023622 xmlSchemaNodeInfoPtr info = NULL;
23623
23624 if (vctxt->depth > vctxt->sizeElemInfos) {
23625 VERROR_INT("xmlSchemaGetFreshElemInfo",
23626 "inconsistent depth encountered");
23627 return (NULL);
23628 }
23629 if (vctxt->elemInfos == NULL) {
23630 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23631 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23632 if (vctxt->elemInfos == NULL) {
23633 xmlSchemaVErrMemory(vctxt,
23634 "allocating the element info array", NULL);
23635 return (NULL);
23636 }
23637 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23638 vctxt->sizeElemInfos = 10;
23639 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23640 int i = vctxt->sizeElemInfos;
23641
23642 vctxt->sizeElemInfos *= 2;
23643 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23644 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23645 sizeof(xmlSchemaNodeInfoPtr));
23646 if (vctxt->elemInfos == NULL) {
23647 xmlSchemaVErrMemory(vctxt,
23648 "re-allocating the element info array", NULL);
23649 return (NULL);
23650 }
23651 /*
23652 * We need the new memory to be NULLed.
23653 * TODO: Use memset instead?
23654 */
23655 for (; i < vctxt->sizeElemInfos; i++)
23656 vctxt->elemInfos[i] = NULL;
23657 } else
23658 info = vctxt->elemInfos[vctxt->depth];
23659
23660 if (info == NULL) {
23661 info = (xmlSchemaNodeInfoPtr)
23662 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23663 if (info == NULL) {
23664 xmlSchemaVErrMemory(vctxt,
23665 "allocating an element info", NULL);
23666 return (NULL);
23667 }
23668 vctxt->elemInfos[vctxt->depth] = info;
23669 } else {
23670 if (info->localName != NULL) {
23671 VERROR_INT("xmlSchemaGetFreshElemInfo",
23672 "elem info has not been cleared");
23673 return (NULL);
23674 }
23675 }
23676 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23677 info->nodeType = XML_ELEMENT_NODE;
23678 info->depth = vctxt->depth;
23679
23680 return (info);
23681}
23682
23683#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23684#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23685#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23686
23687static int
23688xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23689 xmlNodePtr node,
23690 xmlSchemaTypePtr type,
23691 xmlSchemaValType valType,
23692 const xmlChar * value,
23693 xmlSchemaValPtr val,
23694 unsigned long length,
23695 int fireErrors)
23696{
23697 int ret, error = 0;
23698
23699 xmlSchemaTypePtr tmpType;
23700 xmlSchemaFacetLinkPtr facetLink;
23701 xmlSchemaFacetPtr facet;
23702 unsigned long len = 0;
23703 xmlSchemaWhitespaceValueType ws;
23704
23705 /*
23706 * In Libxml2, derived built-in types have currently no explicit facets.
23707 */
23708 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023709 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023710
23711 /*
23712 * NOTE: Do not jump away, if the facetSet of the given type is
23713 * empty: until now, "pattern" and "enumeration" facets of the
23714 * *base types* need to be checked as well.
23715 */
23716 if (type->facetSet == NULL)
23717 goto pattern_and_enum;
23718
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023719 if (! WXS_IS_ATOMIC(type)) {
23720 if (WXS_IS_LIST(type))
23721 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023722 else
23723 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023724 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023725 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023726 * Whitespace handling is only of importance for string-based
23727 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023728 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023729 tmpType = xmlSchemaGetPrimitiveType(type);
23730 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023731 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023732 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23733 } else
23734 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23735 /*
23736 * If the value was not computed (for string or
23737 * anySimpleType based types), then use the provided
23738 * type.
23739 */
23740 if (val == NULL)
23741 valType = valType;
23742 else
23743 valType = xmlSchemaGetValType(val);
23744
23745 ret = 0;
23746 for (facetLink = type->facetSet; facetLink != NULL;
23747 facetLink = facetLink->next) {
23748 /*
23749 * Skip the pattern "whiteSpace": it is used to
23750 * format the character content beforehand.
23751 */
23752 switch (facetLink->facet->type) {
23753 case XML_SCHEMA_FACET_WHITESPACE:
23754 case XML_SCHEMA_FACET_PATTERN:
23755 case XML_SCHEMA_FACET_ENUMERATION:
23756 continue;
23757 case XML_SCHEMA_FACET_LENGTH:
23758 case XML_SCHEMA_FACET_MINLENGTH:
23759 case XML_SCHEMA_FACET_MAXLENGTH:
23760 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23761 valType, value, val, &len, ws);
23762 break;
23763 default:
23764 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23765 valType, value, val, ws);
23766 break;
23767 }
23768 if (ret < 0) {
23769 AERROR_INT("xmlSchemaValidateFacets",
23770 "validating against a atomic type facet");
23771 return (-1);
23772 } else if (ret > 0) {
23773 if (fireErrors)
23774 xmlSchemaFacetErr(actxt, ret, node,
23775 value, len, type, facetLink->facet, NULL, NULL, NULL);
23776 else
23777 return (ret);
23778 if (error == 0)
23779 error = ret;
23780 }
23781 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023782 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023783
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023784WXS_IS_LIST:
23785 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023786 goto pattern_and_enum;
23787 /*
23788 * "length", "minLength" and "maxLength" of list types.
23789 */
23790 ret = 0;
23791 for (facetLink = type->facetSet; facetLink != NULL;
23792 facetLink = facetLink->next) {
23793
23794 switch (facetLink->facet->type) {
23795 case XML_SCHEMA_FACET_LENGTH:
23796 case XML_SCHEMA_FACET_MINLENGTH:
23797 case XML_SCHEMA_FACET_MAXLENGTH:
23798 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23799 value, length, NULL);
23800 break;
23801 default:
23802 continue;
23803 }
23804 if (ret < 0) {
23805 AERROR_INT("xmlSchemaValidateFacets",
23806 "validating against a list type facet");
23807 return (-1);
23808 } else if (ret > 0) {
23809 if (fireErrors)
23810 xmlSchemaFacetErr(actxt, ret, node,
23811 value, length, type, facetLink->facet, NULL, NULL, NULL);
23812 else
23813 return (ret);
23814 if (error == 0)
23815 error = ret;
23816 }
23817 ret = 0;
23818 }
23819
23820pattern_and_enum:
23821 if (error >= 0) {
23822 int found = 0;
23823 /*
23824 * Process enumerations. Facet values are in the value space
23825 * of the defining type's base type. This seems to be a bug in the
23826 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23827 * Only the first set of enumerations in the ancestor-or-self axis
23828 * is used for validation.
23829 */
23830 ret = 0;
23831 tmpType = type;
23832 do {
23833 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23834 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23835 continue;
23836 found = 1;
23837 ret = xmlSchemaAreValuesEqual(facet->val, val);
23838 if (ret == 1)
23839 break;
23840 else if (ret < 0) {
23841 AERROR_INT("xmlSchemaValidateFacets",
23842 "validating against an enumeration facet");
23843 return (-1);
23844 }
23845 }
23846 if (ret != 0)
23847 break;
23848 tmpType = tmpType->baseType;
23849 } while ((tmpType != NULL) &&
23850 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23851 if (found && (ret == 0)) {
23852 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23853 if (fireErrors) {
23854 xmlSchemaFacetErr(actxt, ret, node,
23855 value, 0, type, NULL, NULL, NULL, NULL);
23856 } else
23857 return (ret);
23858 if (error == 0)
23859 error = ret;
23860 }
23861 }
23862
23863 if (error >= 0) {
23864 int found;
23865 /*
23866 * Process patters. Pattern facets are ORed at type level
23867 * and ANDed if derived. Walk the base type axis.
23868 */
23869 tmpType = type;
23870 facet = NULL;
23871 do {
23872 found = 0;
23873 for (facetLink = tmpType->facetSet; facetLink != NULL;
23874 facetLink = facetLink->next) {
23875 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23876 continue;
23877 found = 1;
23878 /*
23879 * NOTE that for patterns, @value needs to be the
23880 * normalized vaule.
23881 */
23882 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23883 if (ret == 1)
23884 break;
23885 else if (ret < 0) {
23886 AERROR_INT("xmlSchemaValidateFacets",
23887 "validating against a pattern facet");
23888 return (-1);
23889 } else {
23890 /*
23891 * Save the last non-validating facet.
23892 */
23893 facet = facetLink->facet;
23894 }
23895 }
23896 if (found && (ret != 1)) {
23897 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23898 if (fireErrors) {
23899 xmlSchemaFacetErr(actxt, ret, node,
23900 value, 0, type, facet, NULL, NULL, NULL);
23901 } else
23902 return (ret);
23903 if (error == 0)
23904 error = ret;
23905 break;
23906 }
23907 tmpType = tmpType->baseType;
23908 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23909 }
23910
23911 return (error);
23912}
23913
23914static xmlChar *
23915xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23916 const xmlChar *value)
23917{
23918 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23919 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23920 return (xmlSchemaCollapseString(value));
23921 case XML_SCHEMA_WHITESPACE_REPLACE:
23922 return (xmlSchemaWhiteSpaceReplace(value));
23923 default:
23924 return (NULL);
23925 }
23926}
23927
23928static int
23929xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23930 const xmlChar *value,
23931 xmlSchemaValPtr *val,
23932 int valNeeded)
23933{
23934 int ret;
23935 const xmlChar *nsName;
23936 xmlChar *local, *prefix = NULL;
23937
23938 ret = xmlValidateQName(value, 1);
23939 if (ret != 0) {
23940 if (ret == -1) {
23941 VERROR_INT("xmlSchemaValidateQName",
23942 "calling xmlValidateQName()");
23943 return (-1);
23944 }
23945 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23946 }
23947 /*
23948 * NOTE: xmlSplitQName2 will always return a duplicated
23949 * strings.
23950 */
23951 local = xmlSplitQName2(value, &prefix);
23952 if (local == NULL)
23953 local = xmlStrdup(value);
23954 /*
23955 * OPTIMIZE TODO: Use flags for:
23956 * - is there any namespace binding?
23957 * - is there a default namespace?
23958 */
23959 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23960
23961 if (prefix != NULL) {
23962 xmlFree(prefix);
23963 /*
23964 * A namespace must be found if the prefix is
23965 * NOT NULL.
23966 */
23967 if (nsName == NULL) {
23968 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023969 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023970 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023971 "The QName value '%s' has no "
23972 "corresponding namespace declaration in "
23973 "scope", value, NULL);
23974 if (local != NULL)
23975 xmlFree(local);
23976 return (ret);
23977 }
23978 }
23979 if (valNeeded && val) {
23980 if (nsName != NULL)
23981 *val = xmlSchemaNewQNameValue(
23982 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
23983 else
23984 *val = xmlSchemaNewQNameValue(NULL,
23985 BAD_CAST local);
23986 } else
23987 xmlFree(local);
23988 return (0);
23989}
23990
23991/*
23992* cvc-simple-type
23993*/
23994static int
23995xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
23996 xmlNodePtr node,
23997 xmlSchemaTypePtr type,
23998 const xmlChar *value,
23999 xmlSchemaValPtr *retVal,
24000 int fireErrors,
24001 int normalize,
24002 int isNormalized)
24003{
24004 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24005 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024006 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024007 xmlChar *normValue = NULL;
24008
24009#define NORMALIZE(atype) \
24010 if ((! isNormalized) && \
24011 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24012 normValue = xmlSchemaNormalizeValue(atype, value); \
24013 if (normValue != NULL) \
24014 value = normValue; \
24015 isNormalized = 1; \
24016 }
24017
24018 if ((retVal != NULL) && (*retVal != NULL)) {
24019 xmlSchemaFreeValue(*retVal);
24020 *retVal = NULL;
24021 }
24022 /*
24023 * 3.14.4 Simple Type Definition Validation Rules
24024 * Validation Rule: String Valid
24025 */
24026 /*
24027 * 1 It is schema-valid with respect to that definition as defined
24028 * by Datatype Valid in [XML Schemas: Datatypes].
24029 */
24030 /*
24031 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24032 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24033 * the string must be a ·declared entity name·.
24034 */
24035 /*
24036 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24037 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24038 * then every whitespace-delimited substring of the string must be a ·declared
24039 * entity name·.
24040 */
24041 /*
24042 * 2.3 otherwise no further condition applies.
24043 */
24044 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24045 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024046 if (value == NULL)
24047 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024048 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024049 xmlSchemaTypePtr biType; /* The built-in type. */
24050 /*
24051 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24052 * a literal in the ·lexical space· of {base type definition}"
24053 */
24054 /*
24055 * Whitespace-normalize.
24056 */
24057 NORMALIZE(type);
24058 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24059 /*
24060 * Get the built-in type.
24061 */
24062 biType = type->baseType;
24063 while ((biType != NULL) &&
24064 (biType->type != XML_SCHEMA_TYPE_BASIC))
24065 biType = biType->baseType;
24066
24067 if (biType == NULL) {
24068 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24069 "could not get the built-in type");
24070 goto internal_error;
24071 }
24072 } else
24073 biType = type;
24074 /*
24075 * NOTATIONs need to be processed here, since they need
24076 * to lookup in the hashtable of NOTATION declarations of the schema.
24077 */
24078 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24079 switch (biType->builtInType) {
24080 case XML_SCHEMAS_NOTATION:
24081 ret = xmlSchemaValidateNotation(
24082 (xmlSchemaValidCtxtPtr) actxt,
24083 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24084 NULL, value, &val, valNeeded);
24085 break;
24086 case XML_SCHEMAS_QNAME:
24087 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24088 value, &val, valNeeded);
24089 break;
24090 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024091 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024092 if (valNeeded)
24093 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24094 value, &val, NULL);
24095 else
24096 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24097 value, NULL, NULL);
24098 break;
24099 }
24100 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24101 switch (biType->builtInType) {
24102 case XML_SCHEMAS_NOTATION:
24103 ret = xmlSchemaValidateNotation(NULL,
24104 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24105 value, &val, valNeeded);
24106 break;
24107 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024108 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024109 if (valNeeded)
24110 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24111 value, &val, node);
24112 else
24113 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24114 value, NULL, node);
24115 break;
24116 }
24117 } else {
24118 /*
24119 * Validation via a public API is not implemented yet.
24120 */
24121 TODO
24122 goto internal_error;
24123 }
24124 if (ret != 0) {
24125 if (ret < 0) {
24126 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24127 "validating against a built-in type");
24128 goto internal_error;
24129 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024130 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024131 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24132 else
24133 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24134 }
24135 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24136 /*
24137 * Check facets.
24138 */
24139 ret = xmlSchemaValidateFacets(actxt, node, type,
24140 (xmlSchemaValType) biType->builtInType, value, val,
24141 0, fireErrors);
24142 if (ret != 0) {
24143 if (ret < 0) {
24144 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24145 "validating facets of atomic simple type");
24146 goto internal_error;
24147 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024148 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024149 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24150 else
24151 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24152 }
24153 }
24154 if (fireErrors && (ret > 0))
24155 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024156 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024157
24158 xmlSchemaTypePtr itemType;
24159 const xmlChar *cur, *end;
24160 xmlChar *tmpValue = NULL;
24161 unsigned long len = 0;
24162 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24163 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24164 * of white space separated tokens, each of which ·match·es a literal
24165 * in the ·lexical space· of {item type definition}
24166 */
24167 /*
24168 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24169 * the list type has an enum or pattern facet.
24170 */
24171 NORMALIZE(type);
24172 /*
24173 * VAL TODO: Optimize validation of empty values.
24174 * VAL TODO: We do not have computed values for lists.
24175 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024176 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024177 cur = value;
24178 do {
24179 while (IS_BLANK_CH(*cur))
24180 cur++;
24181 end = cur;
24182 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24183 end++;
24184 if (end == cur)
24185 break;
24186 tmpValue = xmlStrndup(cur, end - cur);
24187 len++;
24188
24189 if (valNeeded)
24190 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24191 tmpValue, &curVal, fireErrors, 0, 1);
24192 else
24193 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24194 tmpValue, NULL, fireErrors, 0, 1);
24195 FREE_AND_NULL(tmpValue);
24196 if (curVal != NULL) {
24197 /*
24198 * Add to list of computed values.
24199 */
24200 if (val == NULL)
24201 val = curVal;
24202 else
24203 xmlSchemaValueAppend(prevVal, curVal);
24204 prevVal = curVal;
24205 curVal = NULL;
24206 }
24207 if (ret != 0) {
24208 if (ret < 0) {
24209 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24210 "validating an item of list simple type");
24211 goto internal_error;
24212 }
24213 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24214 break;
24215 }
24216 cur = end;
24217 } while (*cur != 0);
24218 FREE_AND_NULL(tmpValue);
24219 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24220 /*
24221 * Apply facets (pattern, enumeration).
24222 */
24223 ret = xmlSchemaValidateFacets(actxt, node, type,
24224 XML_SCHEMAS_UNKNOWN, value, val,
24225 len, fireErrors);
24226 if (ret != 0) {
24227 if (ret < 0) {
24228 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24229 "validating facets of list simple type");
24230 goto internal_error;
24231 }
24232 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24233 }
24234 }
24235 if (fireErrors && (ret > 0)) {
24236 /*
24237 * Report the normalized value.
24238 */
24239 normalize = 1;
24240 NORMALIZE(type);
24241 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24242 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024243 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024244 xmlSchemaTypeLinkPtr memberLink;
24245 /*
24246 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24247 * not apply directly; however, the normalization behavior of ·union·
24248 * types is controlled by the value of whiteSpace on that one of the
24249 * ·memberTypes· against which the ·union· is successfully validated.
24250 *
24251 * This means that the value is normalized by the first validating
24252 * member type, then the facets of the union type are applied. This
24253 * needs changing of the value!
24254 */
24255
24256 /*
24257 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24258 * literal in the ·lexical space· of at least one member of
24259 * {member type definitions}
24260 */
24261 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24262 if (memberLink == NULL) {
24263 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24264 "union simple type has no member types");
24265 goto internal_error;
24266 }
24267 /*
24268 * Always normalize union type values, since we currently
24269 * cannot store the whitespace information with the value
24270 * itself; otherwise a later value-comparison would be
24271 * not possible.
24272 */
24273 while (memberLink != NULL) {
24274 if (valNeeded)
24275 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24276 memberLink->type, value, &val, 0, 1, 0);
24277 else
24278 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24279 memberLink->type, value, NULL, 0, 1, 0);
24280 if (ret <= 0)
24281 break;
24282 memberLink = memberLink->next;
24283 }
24284 if (ret != 0) {
24285 if (ret < 0) {
24286 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24287 "validating members of union simple type");
24288 goto internal_error;
24289 }
24290 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24291 }
24292 /*
24293 * Apply facets (pattern, enumeration).
24294 */
24295 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24296 /*
24297 * The normalization behavior of ·union· types is controlled by
24298 * the value of whiteSpace on that one of the ·memberTypes·
24299 * against which the ·union· is successfully validated.
24300 */
24301 NORMALIZE(memberLink->type);
24302 ret = xmlSchemaValidateFacets(actxt, node, type,
24303 XML_SCHEMAS_UNKNOWN, value, val,
24304 0, fireErrors);
24305 if (ret != 0) {
24306 if (ret < 0) {
24307 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24308 "validating facets of union simple type");
24309 goto internal_error;
24310 }
24311 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24312 }
24313 }
24314 if (fireErrors && (ret > 0))
24315 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24316 }
24317
24318 if (normValue != NULL)
24319 xmlFree(normValue);
24320 if (ret == 0) {
24321 if (retVal != NULL)
24322 *retVal = val;
24323 else if (val != NULL)
24324 xmlSchemaFreeValue(val);
24325 } else if (val != NULL)
24326 xmlSchemaFreeValue(val);
24327 return (ret);
24328internal_error:
24329 if (normValue != NULL)
24330 xmlFree(normValue);
24331 if (val != NULL)
24332 xmlSchemaFreeValue(val);
24333 return (-1);
24334}
24335
24336static int
24337xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24338 const xmlChar *value,
24339 const xmlChar **nsName,
24340 const xmlChar **localName)
24341{
24342 int ret = 0;
24343
24344 if ((nsName == NULL) || (localName == NULL))
24345 return (-1);
24346 *nsName = NULL;
24347 *localName = NULL;
24348
24349 ret = xmlValidateQName(value, 1);
24350 if (ret == -1)
24351 return (-1);
24352 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024353 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024354 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24355 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24356 return (1);
24357 }
24358 {
24359 xmlChar *local = NULL;
24360 xmlChar *prefix;
24361
24362 /*
24363 * NOTE: xmlSplitQName2 will return a duplicated
24364 * string.
24365 */
24366 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024367 if (local == NULL)
24368 *localName = xmlDictLookup(vctxt->dict, value, -1);
24369 else {
24370 *localName = xmlDictLookup(vctxt->dict, local, -1);
24371 xmlFree(local);
24372 }
24373
24374 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24375
24376 if (prefix != NULL) {
24377 xmlFree(prefix);
24378 /*
24379 * A namespace must be found if the prefix is NOT NULL.
24380 */
24381 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024382 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024383 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024384 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024385 "The QName value '%s' has no "
24386 "corresponding namespace declaration in scope",
24387 value, NULL);
24388 return (2);
24389 }
24390 }
24391 }
24392 return (0);
24393}
24394
24395static int
24396xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24397 xmlSchemaAttrInfoPtr iattr,
24398 xmlSchemaTypePtr *localType,
24399 xmlSchemaElementPtr elemDecl)
24400{
24401 int ret = 0;
24402 /*
24403 * cvc-elt (3.3.4) : (4)
24404 * AND
24405 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24406 * (1.2.1.2.1) - (1.2.1.2.4)
24407 * Handle 'xsi:type'.
24408 */
24409 if (localType == NULL)
24410 return (-1);
24411 *localType = NULL;
24412 if (iattr == NULL)
24413 return (0);
24414 else {
24415 const xmlChar *nsName = NULL, *local = NULL;
24416 /*
24417 * TODO: We should report a *warning* that the type was overriden
24418 * by the instance.
24419 */
24420 ACTIVATE_ATTRIBUTE(iattr);
24421 /*
24422 * (cvc-elt) (3.3.4) : (4.1)
24423 * (cvc-assess-elt) (1.2.1.2.2)
24424 */
24425 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24426 &nsName, &local);
24427 if (ret != 0) {
24428 if (ret < 0) {
24429 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24430 "calling xmlSchemaQNameExpand() to validate the "
24431 "attribute 'xsi:type'");
24432 goto internal_error;
24433 }
24434 goto exit;
24435 }
24436 /*
24437 * (cvc-elt) (3.3.4) : (4.2)
24438 * (cvc-assess-elt) (1.2.1.2.3)
24439 */
24440 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24441 if (*localType == NULL) {
24442 xmlChar *str = NULL;
24443
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024444 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024445 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024446 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024447 "The QName value '%s' of the xsi:type attribute does not "
24448 "resolve to a type definition",
24449 xmlSchemaFormatQName(&str, nsName, local), NULL);
24450 FREE_AND_NULL(str);
24451 ret = vctxt->err;
24452 goto exit;
24453 }
24454 if (elemDecl != NULL) {
24455 int set = 0;
24456
24457 /*
24458 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24459 * "The ·local type definition· must be validly
24460 * derived from the {type definition} given the union of
24461 * the {disallowed substitutions} and the {type definition}'s
24462 * {prohibited substitutions}, as defined in
24463 * Type Derivation OK (Complex) (§3.4.6)
24464 * (if it is a complex type definition),
24465 * or given {disallowed substitutions} as defined in Type
24466 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24467 * definition)."
24468 *
24469 * {disallowed substitutions}: the "block" on the element decl.
24470 * {prohibited substitutions}: the "block" on the type def.
24471 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024472 /*
24473 * OPTIMIZE TODO: We could map types already evaluated
24474 * to be validly derived from other types to avoid checking
24475 * this over and over for the same types.
24476 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024477 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24478 (elemDecl->subtypes->flags &
24479 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24480 set |= SUBSET_EXTENSION;
24481
24482 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24483 (elemDecl->subtypes->flags &
24484 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24485 set |= SUBSET_RESTRICTION;
24486
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024487 /*
24488 * REMOVED and CHANGED since this produced a parser context
24489 * which adds to the string dict of the schema. So this would
24490 * change the schema and we don't want this. We don't need
24491 * the parser context anymore.
24492 *
24493 * if ((vctxt->pctxt == NULL) &&
24494 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24495 * return (-1);
24496 */
24497
24498 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024499 elemDecl->subtypes, set) != 0) {
24500 xmlChar *str = NULL;
24501
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024502 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024503 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24504 "The type definition '%s', specified by xsi:type, is "
24505 "blocked or not validly derived from the type definition "
24506 "of the element declaration",
24507 xmlSchemaFormatQName(&str,
24508 (*localType)->targetNamespace,
24509 (*localType)->name),
24510 NULL);
24511 FREE_AND_NULL(str);
24512 ret = vctxt->err;
24513 *localType = NULL;
24514 }
24515 }
24516 }
24517exit:
24518 ACTIVATE_ELEM;
24519 return (ret);
24520internal_error:
24521 ACTIVATE_ELEM;
24522 return (-1);
24523}
24524
24525static int
24526xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24527{
24528 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024529 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024530
24531 /*
24532 * cvc-elt (3.3.4) : 1
24533 */
24534 if (elemDecl == NULL) {
24535 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24536 "No matching declaration available");
24537 return (vctxt->err);
24538 }
24539 /*
24540 * cvc-elt (3.3.4) : 2
24541 */
24542 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24543 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24544 "The element declaration is abstract");
24545 return (vctxt->err);
24546 }
24547 if (actualType == NULL) {
24548 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24549 "The type definition is absent");
24550 return (XML_SCHEMAV_CVC_TYPE_1);
24551 }
24552 if (vctxt->nbAttrInfos != 0) {
24553 int ret;
24554 xmlSchemaAttrInfoPtr iattr;
24555 /*
24556 * cvc-elt (3.3.4) : 3
24557 * Handle 'xsi:nil'.
24558 */
24559 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24560 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24561 if (iattr) {
24562 ACTIVATE_ATTRIBUTE(iattr);
24563 /*
24564 * Validate the value.
24565 */
24566 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024567 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024568 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24569 iattr->value, &(iattr->val), 1, 0, 0);
24570 ACTIVATE_ELEM;
24571 if (ret < 0) {
24572 VERROR_INT("xmlSchemaValidateElemDecl",
24573 "calling xmlSchemaVCheckCVCSimpleType() to "
24574 "validate the attribute 'xsi:nil'");
24575 return (-1);
24576 }
24577 if (ret == 0) {
24578 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24579 /*
24580 * cvc-elt (3.3.4) : 3.1
24581 */
24582 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24583 "The element is not 'nillable'");
24584 /* Does not return an error on purpose. */
24585 } else {
24586 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24587 /*
24588 * cvc-elt (3.3.4) : 3.2.2
24589 */
24590 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24591 (elemDecl->value != NULL)) {
24592 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24593 "The element cannot be 'nilled' because "
24594 "there is a fixed value constraint defined "
24595 "for it");
24596 /* Does not return an error on purpose. */
24597 } else
24598 vctxt->inode->flags |=
24599 XML_SCHEMA_ELEM_INFO_NILLED;
24600 }
24601 }
24602 }
24603 }
24604 /*
24605 * cvc-elt (3.3.4) : 4
24606 * Handle 'xsi:type'.
24607 */
24608 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24609 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24610 if (iattr) {
24611 xmlSchemaTypePtr localType = NULL;
24612
24613 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24614 elemDecl);
24615 if (ret != 0) {
24616 if (ret == -1) {
24617 VERROR_INT("xmlSchemaValidateElemDecl",
24618 "calling xmlSchemaProcessXSIType() to "
24619 "process the attribute 'xsi:type'");
24620 return (-1);
24621 }
24622 /* Does not return an error on purpose. */
24623 }
24624 if (localType != NULL) {
24625 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24626 actualType = localType;
24627 }
24628 }
24629 }
24630 /*
24631 * IDC: Register identity-constraint XPath matchers.
24632 */
24633 if ((elemDecl->idcs != NULL) &&
24634 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24635 return (-1);
24636 /*
24637 * No actual type definition.
24638 */
24639 if (actualType == NULL) {
24640 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24641 "The type definition is absent");
24642 return (XML_SCHEMAV_CVC_TYPE_1);
24643 }
24644 /*
24645 * Remember the actual type definition.
24646 */
24647 vctxt->inode->typeDef = actualType;
24648
24649 return (0);
24650}
24651
24652static int
24653xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24654{
24655 xmlSchemaAttrInfoPtr iattr;
24656 int ret = 0, i;
24657
24658 /*
24659 * SPEC cvc-type (3.1.1)
24660 * "The attributes of must be empty, excepting those whose namespace
24661 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24662 * whose local name is one of type, nil, schemaLocation or
24663 * noNamespaceSchemaLocation."
24664 */
24665 if (vctxt->nbAttrInfos == 0)
24666 return (0);
24667 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24668 iattr = vctxt->attrInfos[i];
24669 if (! iattr->metaType) {
24670 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024671 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024672 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24673 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24674 }
24675 }
24676 ACTIVATE_ELEM
24677 return (ret);
24678}
24679
24680/*
24681* Cleanup currently used attribute infos.
24682*/
24683static void
24684xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24685{
24686 int i;
24687 xmlSchemaAttrInfoPtr attr;
24688
24689 if (vctxt->nbAttrInfos == 0)
24690 return;
24691 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24692 attr = vctxt->attrInfos[i];
24693 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24694 if (attr->localName != NULL)
24695 xmlFree((xmlChar *) attr->localName);
24696 if (attr->nsName != NULL)
24697 xmlFree((xmlChar *) attr->nsName);
24698 }
24699 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24700 if (attr->value != NULL)
24701 xmlFree((xmlChar *) attr->value);
24702 }
24703 if (attr->val != NULL) {
24704 xmlSchemaFreeValue(attr->val);
24705 attr->val = NULL;
24706 }
24707 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24708 }
24709 vctxt->nbAttrInfos = 0;
24710}
24711
24712/*
24713* 3.4.4 Complex Type Definition Validation Rules
24714* Element Locally Valid (Complex Type) (cvc-complex-type)
24715* 3.2.4 Attribute Declaration Validation Rules
24716* Validation Rule: Attribute Locally Valid (cvc-attribute)
24717* Attribute Locally Valid (Use) (cvc-au)
24718*
24719* Only "assessed" attribute information items will be visible to
24720* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24721*/
24722static int
24723xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24724{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024725 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24726 xmlSchemaItemListPtr attrUseList;
24727 xmlSchemaAttributeUsePtr attrUse = NULL;
24728 xmlSchemaAttributePtr attrDecl = NULL;
24729 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24730 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024731 int xpathRes = 0, res, wildIDs = 0, fixed;
24732
24733 /*
24734 * SPEC (cvc-attribute)
24735 * (1) "The declaration must not be ·absent· (see Missing
24736 * Sub-components (§5.3) for how this can fail to be
24737 * the case)."
24738 * (2) "Its {type definition} must not be absent."
24739 *
24740 * NOTE (1) + (2): This is not handled here, since we currently do not
24741 * allow validation against schemas which have missing sub-components.
24742 *
24743 * SPEC (cvc-complex-type)
24744 * (3) "For each attribute information item in the element information
24745 * item's [attributes] excepting those whose [namespace name] is
24746 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24747 * [local name] is one of type, nil, schemaLocation or
24748 * noNamespaceSchemaLocation, the appropriate case among the following
24749 * must be true:
24750 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024751 */
24752 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24753 /*
24754 * @nbAttrs is the number of attributes present in the instance.
24755 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024756 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024757 if (attrUseList != NULL)
24758 nbUses = attrUseList->nbItems;
24759 else
24760 nbUses = 0;
24761 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024762 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024763 attrUse = attrUseList->items[i];
24764 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24765 for (j = 0; j < nbAttrs; j++) {
24766 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024767 /*
24768 * SPEC (cvc-complex-type) (3)
24769 * Skip meta attributes.
24770 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024771 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024772 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024773 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024774 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024775 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024776 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024777 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024778 continue;
24779 found = 1;
24780 /*
24781 * SPEC (cvc-complex-type)
24782 * (3.1) "If there is among the {attribute uses} an attribute
24783 * use with an {attribute declaration} whose {name} matches
24784 * the attribute information item's [local name] and whose
24785 * {target namespace} is identical to the attribute information
24786 * item's [namespace name] (where an ·absent· {target namespace}
24787 * is taken to be identical to a [namespace name] with no value),
24788 * then the attribute information must be ·valid· with respect
24789 * to that attribute use as per Attribute Locally Valid (Use)
24790 * (§3.5.4). In this case the {attribute declaration} of that
24791 * attribute use is the ·context-determined declaration· for the
24792 * attribute information item with respect to Schema-Validity
24793 * Assessment (Attribute) (§3.2.4) and
24794 * Assessment Outcome (Attribute) (§3.2.5).
24795 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024796 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24797 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024798 /*
24799 * Context-determined declaration.
24800 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024801 iattr->decl = attrDecl;
24802 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024803 break;
24804 }
24805
24806 if (found)
24807 continue;
24808
24809 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24810 /*
24811 * Handle non-existent, required attributes.
24812 *
24813 * SPEC (cvc-complex-type)
24814 * (4) "The {attribute declaration} of each attribute use in
24815 * the {attribute uses} whose {required} is true matches one
24816 * of the attribute information items in the element information
24817 * item's [attributes] as per clause 3.1 above."
24818 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024819 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24820 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024821 VERROR_INT(
24822 "xmlSchemaVAttributesComplex",
24823 "calling xmlSchemaGetFreshAttrInfo()");
24824 return (-1);
24825 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024826 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24827 tmpiattr->use = attrUse;
24828 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024829 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24830 ((attrUse->defValue != NULL) ||
24831 (attrDecl->defValue != NULL))) {
24832 /*
24833 * Handle non-existent, optional, default/fixed attributes.
24834 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024835 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24836 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024837 VERROR_INT(
24838 "xmlSchemaVAttributesComplex",
24839 "calling xmlSchemaGetFreshAttrInfo()");
24840 return (-1);
24841 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024842 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24843 tmpiattr->use = attrUse;
24844 tmpiattr->decl = attrDecl;
24845 tmpiattr->typeDef = attrDecl->subtypes;
24846 tmpiattr->localName = attrDecl->name;
24847 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024848 }
24849 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024850
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024851 if (vctxt->nbAttrInfos == 0)
24852 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024853 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024854 /*
24855 * Validate against the wildcard.
24856 */
24857 if (type->attributeWildcard != NULL) {
24858 /*
24859 * SPEC (cvc-complex-type)
24860 * (3.2.1) "There must be an {attribute wildcard}."
24861 */
24862 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024863 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024864 /*
24865 * SPEC (cvc-complex-type) (3)
24866 * Skip meta attributes.
24867 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024868 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024869 continue;
24870 /*
24871 * SPEC (cvc-complex-type)
24872 * (3.2.2) "The attribute information item must be ·valid· with
24873 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24874 *
24875 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24876 * "... its [namespace name] must be ·valid· with respect to
24877 * the wildcard constraint, as defined in Wildcard allows
24878 * Namespace Name (§3.10.4)."
24879 */
24880 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024881 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024882 /*
24883 * Handle processContents.
24884 *
24885 * SPEC (cvc-wildcard):
24886 * processContents | context-determined declaration:
24887 * "strict" "mustFind"
24888 * "lax" "none"
24889 * "skip" "skip"
24890 */
24891 if (type->attributeWildcard->processContents ==
24892 XML_SCHEMAS_ANY_SKIP) {
24893 /*
24894 * context-determined declaration = "skip"
24895 *
24896 * SPEC PSVI Assessment Outcome (Attribute)
24897 * [validity] = "notKnown"
24898 * [validation attempted] = "none"
24899 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024900 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024901 continue;
24902 }
24903 /*
24904 * Find an attribute declaration.
24905 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024906 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24907 iattr->localName, iattr->nsName);
24908 if (iattr->decl != NULL) {
24909 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024910 /*
24911 * SPEC (cvc-complex-type)
24912 * (5) "Let [Definition:] the wild IDs be the set of
24913 * all attribute information item to which clause 3.2
24914 * applied and whose ·validation· resulted in a
24915 * ·context-determined declaration· of mustFind or no
24916 * ·context-determined declaration· at all, and whose
24917 * [local name] and [namespace name] resolve (as
24918 * defined by QName resolution (Instance) (§3.15.4)) to
24919 * an attribute declaration whose {type definition} is
24920 * or is derived from ID. Then all of the following
24921 * must be true:"
24922 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024923 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024924 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024925 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024926 /*
24927 * SPEC (5.1) "There must be no more than one
24928 * item in ·wild IDs·."
24929 */
24930 if (wildIDs != 0) {
24931 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024932 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024933 TODO
24934 continue;
24935 }
24936 wildIDs++;
24937 /*
24938 * SPEC (cvc-complex-type)
24939 * (5.2) "If ·wild IDs· is non-empty, there must not
24940 * be any attribute uses among the {attribute uses}
24941 * whose {attribute declaration}'s {type definition}
24942 * is or is derived from ID."
24943 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024944 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024945 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024946 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024947 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024948 /* URGENT VAL TODO: implement */
24949 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024950 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024951 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024952 }
24953 }
24954 }
24955 } else if (type->attributeWildcard->processContents ==
24956 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024957 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024958 /*
24959 * SPEC PSVI Assessment Outcome (Attribute)
24960 * [validity] = "notKnown"
24961 * [validation attempted] = "none"
24962 */
24963 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024964 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024965 }
24966 }
24967 }
24968 }
24969
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024970 if (vctxt->nbAttrInfos == 0)
24971 return (0);
24972
24973 /*
24974 * Validate values, create default attributes, evaluate IDCs.
24975 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024976 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024977 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024978 /*
24979 * VAL TODO: Note that we won't try to resolve IDCs to
24980 * "lax" and "skip" validated attributes. Check what to
24981 * do in this case.
24982 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024983 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
24984 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024985 continue;
24986 /*
24987 * VAL TODO: What to do if the type definition is missing?
24988 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024989 if (iattr->typeDef == NULL) {
24990 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024991 continue;
24992 }
24993
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024994 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000024995 fixed = 0;
24996 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024997
24998 if (vctxt->xpathStates != NULL) {
24999 /*
25000 * Evaluate IDCs.
25001 */
25002 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25003 XML_ATTRIBUTE_NODE);
25004 if (xpathRes == -1) {
25005 VERROR_INT("xmlSchemaVAttributesComplex",
25006 "calling xmlSchemaXPathEvaluate()");
25007 goto internal_error;
25008 }
25009 }
25010
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025011 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025012 /*
25013 * Default/fixed attributes.
25014 */
25015 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025016 if (iattr->use->defValue != NULL) {
25017 iattr->value = (xmlChar *) iattr->use->defValue;
25018 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025019 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025020 iattr->value = (xmlChar *) iattr->decl->defValue;
25021 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025022 }
25023 /*
25024 * IDCs will consume the precomputed default value,
25025 * so we need to clone it.
25026 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025027 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025028 VERROR_INT("xmlSchemaVAttributesComplex",
25029 "default/fixed value on an attribute use was "
25030 "not precomputed");
25031 goto internal_error;
25032 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025033 iattr->val = xmlSchemaCopyValue(iattr->val);
25034 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025035 VERROR_INT("xmlSchemaVAttributesComplex",
25036 "calling xmlSchemaCopyValue()");
25037 goto internal_error;
25038 }
25039 }
25040 /*
25041 * PSVI: Add the default attribute to the current element.
25042 * VAL TODO: Should we use the *normalized* value? This currently
25043 * uses the *initial* value.
25044 */
25045 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025046 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025047 xmlChar *normValue;
25048 const xmlChar *value;
25049
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025050 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025051 /*
25052 * Normalize the value.
25053 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025054 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25055 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025056 if (normValue != NULL)
25057 value = BAD_CAST normValue;
25058
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025059 if (iattr->nsName == NULL) {
25060 if (xmlNewProp(iattr->node->parent,
25061 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025062 VERROR_INT("xmlSchemaVAttributesComplex",
25063 "callling xmlNewProp()");
25064 if (normValue != NULL)
25065 xmlFree(normValue);
25066 goto internal_error;
25067 }
25068 } else {
25069 xmlNsPtr ns;
25070
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025071 ns = xmlSearchNsByHref(iattr->node->doc,
25072 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025073 if (ns == NULL) {
25074 xmlChar prefix[12];
25075 int counter = 0;
25076
25077 /*
25078 * Create a namespace declaration on the validation
25079 * root node if no namespace declaration is in scope.
25080 */
25081 do {
25082 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025083 ns = xmlSearchNs(iattr->node->doc,
25084 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025085 if (counter > 1000) {
25086 VERROR_INT(
25087 "xmlSchemaVAttributesComplex",
25088 "could not compute a ns prefix for a "
25089 "default/fixed attribute");
25090 if (normValue != NULL)
25091 xmlFree(normValue);
25092 goto internal_error;
25093 }
25094 } while (ns != NULL);
25095 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025096 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025097 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025098 /*
25099 * TODO:
25100 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25101 * If we have QNames: do we need to ensure there's a
25102 * prefix defined for the QName?
25103 */
25104 xmlNewNsProp(iattr->node->parent, ns,
25105 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025106 }
25107 if (normValue != NULL)
25108 xmlFree(normValue);
25109 }
25110 /*
25111 * Go directly to IDC evaluation.
25112 */
25113 goto eval_idcs;
25114 }
25115 /*
25116 * Validate the value.
25117 */
25118 if (vctxt->value != NULL) {
25119 /*
25120 * Free last computed value; just for safety reasons.
25121 */
25122 xmlSchemaFreeValue(vctxt->value);
25123 vctxt->value = NULL;
25124 }
25125 /*
25126 * Note that the attribute *use* can be unavailable, if
25127 * the attribute was a wild attribute.
25128 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025129 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25130 ((iattr->use != NULL) &&
25131 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025132 fixed = 1;
25133 else
25134 fixed = 0;
25135 /*
25136 * SPEC (cvc-attribute)
25137 * (3) "The item's ·normalized value· must be locally ·valid·
25138 * with respect to that {type definition} as per
25139 * String Valid (§3.14.4)."
25140 *
25141 * VAL TODO: Do we already have the
25142 * "normalized attribute value" here?
25143 */
25144 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025145 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025146 /*
25147 * Request a computed value.
25148 */
25149 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025150 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025151 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025152 1, 1, 0);
25153 } else {
25154 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025155 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025156 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025157 1, 0, 0);
25158 }
25159
25160 if (res != 0) {
25161 if (res == -1) {
25162 VERROR_INT("xmlSchemaVAttributesComplex",
25163 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25164 goto internal_error;
25165 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025166 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025167 /*
25168 * SPEC PSVI Assessment Outcome (Attribute)
25169 * [validity] = "invalid"
25170 */
25171 goto eval_idcs;
25172 }
25173
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025174 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025175 /*
25176 * SPEC Attribute Locally Valid (Use) (cvc-au)
25177 * "For an attribute information item to be·valid·
25178 * with respect to an attribute use its *normalized*
25179 * value· must match the *canonical* lexical
25180 * representation of the attribute use's {value
25181 * constraint}value, if it is present and fixed."
25182 *
25183 * VAL TODO: The requirement for the *canonical* value
25184 * will be removed in XML Schema 1.1.
25185 */
25186 /*
25187 * SPEC Attribute Locally Valid (cvc-attribute)
25188 * (4) "The item's *actual* value· must match the *value* of
25189 * the {value constraint}, if it is present and fixed."
25190 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025191 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025192 /* VAL TODO: A value was not precomputed. */
25193 TODO
25194 goto eval_idcs;
25195 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025196 if ((iattr->use != NULL) &&
25197 (iattr->use->defValue != NULL)) {
25198 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025199 /* VAL TODO: A default value was not precomputed. */
25200 TODO
25201 goto eval_idcs;
25202 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025203 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025204 /*
25205 if (xmlSchemaCompareValuesWhtsp(attr->val,
25206 (xmlSchemaWhitespaceValueType) ws,
25207 attr->use->defVal,
25208 (xmlSchemaWhitespaceValueType) ws) != 0) {
25209 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025210 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25211 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025212 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025213 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025214 /* VAL TODO: A default value was not precomputed. */
25215 TODO
25216 goto eval_idcs;
25217 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025218 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025219 /*
25220 if (xmlSchemaCompareValuesWhtsp(attr->val,
25221 (xmlSchemaWhitespaceValueType) ws,
25222 attrDecl->defVal,
25223 (xmlSchemaWhitespaceValueType) ws) != 0) {
25224 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025225 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25226 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025227 }
25228 /*
25229 * [validity] = "valid"
25230 */
25231 }
25232eval_idcs:
25233 /*
25234 * Evaluate IDCs.
25235 */
25236 if (xpathRes) {
25237 if (xmlSchemaXPathProcessHistory(vctxt,
25238 vctxt->depth +1) == -1) {
25239 VERROR_INT("xmlSchemaVAttributesComplex",
25240 "calling xmlSchemaXPathEvaluate()");
25241 goto internal_error;
25242 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025243 } else if (vctxt->xpathStates != NULL)
25244 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025245 }
25246
25247 /*
25248 * Report errors.
25249 */
25250 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025251 iattr = vctxt->attrInfos[i];
25252 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25253 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25254 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25255 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025256 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025257 ACTIVATE_ATTRIBUTE(iattr);
25258 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025259 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25260 xmlChar *str = NULL;
25261 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025262 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025263 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25264 "The attribute '%s' is required but missing",
25265 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025266 iattr->decl->targetNamespace,
25267 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025268 NULL);
25269 FREE_AND_NULL(str)
25270 break;
25271 }
25272 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25273 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25274 "The type definition is absent");
25275 break;
25276 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025277 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025278 XML_SCHEMAV_CVC_AU, NULL, NULL,
25279 "The value '%s' does not match the fixed "
25280 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025281 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025282 break;
25283 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25284 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25285 "No matching global attribute declaration available, but "
25286 "demanded by the strict wildcard");
25287 break;
25288 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025289 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025290 break;
25291 /*
25292 * MAYBE VAL TODO: One might report different error messages
25293 * for the following errors.
25294 */
25295 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025296 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025297 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025298 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025299 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025300 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025301 }
25302 break;
25303 default:
25304 break;
25305 }
25306 }
25307
25308 ACTIVATE_ELEM;
25309 return (0);
25310internal_error:
25311 ACTIVATE_ELEM;
25312 return (-1);
25313}
25314
25315static int
25316xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25317 int *skip)
25318{
25319 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25320 /*
25321 * The namespace of the element was already identified to be
25322 * matching the wildcard.
25323 */
25324 if ((skip == NULL) || (wild == NULL) ||
25325 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25326 VERROR_INT("xmlSchemaValidateElemWildcard",
25327 "bad arguments");
25328 return (-1);
25329 }
25330 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025331 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25332 /*
25333 * URGENT VAL TODO: Either we need to position the stream to the
25334 * next sibling, or walk the whole subtree.
25335 */
25336 *skip = 1;
25337 return (0);
25338 }
25339 {
25340 xmlSchemaElementPtr decl = NULL;
25341
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025342 decl = xmlSchemaGetElem(vctxt->schema,
25343 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025344 if (decl != NULL) {
25345 vctxt->inode->decl = decl;
25346 return (0);
25347 }
25348 }
25349 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25350 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025351 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025352 "No matching global element declaration available, but "
25353 "demanded by the strict wildcard");
25354 return (vctxt->err);
25355 }
25356 if (vctxt->nbAttrInfos != 0) {
25357 xmlSchemaAttrInfoPtr iattr;
25358 /*
25359 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25360 * (1.2.1.2.1) - (1.2.1.2.3 )
25361 *
25362 * Use the xsi:type attribute for the type definition.
25363 */
25364 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25365 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25366 if (iattr != NULL) {
25367 if (xmlSchemaProcessXSIType(vctxt, iattr,
25368 &(vctxt->inode->typeDef), NULL) == -1) {
25369 VERROR_INT("xmlSchemaValidateElemWildcard",
25370 "calling xmlSchemaProcessXSIType() to "
25371 "process the attribute 'xsi:nil'");
25372 return (-1);
25373 }
25374 /*
25375 * Don't return an error on purpose.
25376 */
25377 return (0);
25378 }
25379 }
25380 /*
25381 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25382 *
25383 * Fallback to "anyType".
25384 */
25385 vctxt->inode->typeDef =
25386 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25387 return (0);
25388}
25389
25390/*
25391* xmlSchemaCheckCOSValidDefault:
25392*
25393* This will be called if: not nilled, no content and a default/fixed
25394* value is provided.
25395*/
25396
25397static int
25398xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25399 const xmlChar *value,
25400 xmlSchemaValPtr *val)
25401{
25402 int ret = 0;
25403 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25404
25405 /*
25406 * cos-valid-default:
25407 * Schema Component Constraint: Element Default Valid (Immediate)
25408 * For a string to be a valid default with respect to a type
25409 * definition the appropriate case among the following must be true:
25410 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025411 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025412 /*
25413 * Complex type.
25414 *
25415 * SPEC (2.1) "its {content type} must be a simple type definition
25416 * or mixed."
25417 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25418 * type}'s particle must be ·emptiable· as defined by
25419 * Particle Emptiable (§3.9.6)."
25420 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025421 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25422 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25423 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025424 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25425 /* NOTE that this covers (2.2.2) as well. */
25426 VERROR(ret, NULL,
25427 "For a string to be a valid default, the type definition "
25428 "must be a simple type or a complex type with simple content "
25429 "or mixed content and a particle emptiable");
25430 return(ret);
25431 }
25432 }
25433 /*
25434 * 1 If the type definition is a simple type definition, then the string
25435 * must be ·valid· with respect to that definition as defined by String
25436 * Valid (§3.14.4).
25437 *
25438 * AND
25439 *
25440 * 2.2.1 If the {content type} is a simple type definition, then the
25441 * string must be ·valid· with respect to that simple type definition
25442 * as defined by String Valid (§3.14.4).
25443 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025444 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025445
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025446 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025447 NULL, inode->typeDef, value, val, 1, 1, 0);
25448
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025449 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025450
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025451 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025452 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25453 }
25454 if (ret < 0) {
25455 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25456 "calling xmlSchemaVCheckCVCSimpleType()");
25457 }
25458 return (ret);
25459}
25460
25461static void
25462xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25463 const xmlChar * name ATTRIBUTE_UNUSED,
25464 xmlSchemaElementPtr item,
25465 xmlSchemaNodeInfoPtr inode)
25466{
25467 inode->decl = item;
25468#ifdef DEBUG_CONTENT
25469 {
25470 xmlChar *str = NULL;
25471
25472 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25473 xmlGenericError(xmlGenericErrorContext,
25474 "AUTOMATON callback for '%s' [declaration]\n",
25475 xmlSchemaFormatQName(&str,
25476 inode->localName, inode->nsName));
25477 } else {
25478 xmlGenericError(xmlGenericErrorContext,
25479 "AUTOMATON callback for '%s' [wildcard]\n",
25480 xmlSchemaFormatQName(&str,
25481 inode->localName, inode->nsName));
25482
25483 }
25484 FREE_AND_NULL(str)
25485 }
25486#endif
25487}
25488
25489static int
25490xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025491{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025492 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25493 if (vctxt->inode == NULL) {
25494 VERROR_INT("xmlSchemaValidatorPushElem",
25495 "calling xmlSchemaGetFreshElemInfo()");
25496 return (-1);
25497 }
25498 vctxt->nbAttrInfos = 0;
25499 return (0);
25500}
25501
25502static int
25503xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25504 xmlSchemaNodeInfoPtr inode,
25505 xmlSchemaTypePtr type,
25506 const xmlChar *value)
25507{
25508 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25509 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025510 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025511 type, value, &(inode->val), 1, 1, 0));
25512 else
25513 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025514 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025515 type, value, NULL, 1, 0, 0));
25516}
25517
25518
25519
25520/*
25521* Process END of element.
25522*/
25523static int
25524xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25525{
25526 int ret = 0;
25527 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25528
25529 if (vctxt->nbAttrInfos != 0)
25530 xmlSchemaClearAttrInfos(vctxt);
25531 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25532 /*
25533 * This element was not expected;
25534 * we will not validate child elements of broken parents.
25535 * Skip validation of all content of the parent.
25536 */
25537 vctxt->skipDepth = vctxt->depth -1;
25538 goto end_elem;
25539 }
25540 if ((inode->typeDef == NULL) ||
25541 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25542 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025543 * 1. the type definition might be missing if the element was
25544 * error prone
25545 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025546 */
25547 goto end_elem;
25548 }
25549 /*
25550 * Check the content model.
25551 */
25552 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25553 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25554
25555 /*
25556 * Workaround for "anyType".
25557 */
25558 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25559 goto character_content;
25560
25561 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25562 xmlChar *values[10];
25563 int terminal, nbval = 10, nbneg;
25564
25565 if (inode->regexCtxt == NULL) {
25566 /*
25567 * Create the regex context.
25568 */
25569 inode->regexCtxt =
25570 xmlRegNewExecCtxt(inode->typeDef->contModel,
25571 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25572 vctxt);
25573 if (inode->regexCtxt == NULL) {
25574 VERROR_INT("xmlSchemaValidatorPopElem",
25575 "failed to create a regex context");
25576 goto internal_error;
25577 }
25578#ifdef DEBUG_AUTOMATA
25579 xmlGenericError(xmlGenericErrorContext,
25580 "AUTOMATON create on '%s'\n", inode->localName);
25581#endif
25582 }
25583 /*
25584 * Get hold of the still expected content, since a further
25585 * call to xmlRegExecPushString() will loose this information.
25586 */
25587 xmlRegExecNextValues(inode->regexCtxt,
25588 &nbval, &nbneg, &values[0], &terminal);
25589 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25590 if (ret <= 0) {
25591 /*
25592 * Still missing something.
25593 */
25594 ret = 1;
25595 inode->flags |=
25596 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025597 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025598 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25599 "Missing child element(s)",
25600 nbval, nbneg, values);
25601#ifdef DEBUG_AUTOMATA
25602 xmlGenericError(xmlGenericErrorContext,
25603 "AUTOMATON missing ERROR on '%s'\n",
25604 inode->localName);
25605#endif
25606 } else {
25607 /*
25608 * Content model is satisfied.
25609 */
25610 ret = 0;
25611#ifdef DEBUG_AUTOMATA
25612 xmlGenericError(xmlGenericErrorContext,
25613 "AUTOMATON succeeded on '%s'\n",
25614 inode->localName);
25615#endif
25616 }
25617
25618 }
25619 }
25620 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25621 goto end_elem;
25622
25623character_content:
25624
25625 if (vctxt->value != NULL) {
25626 xmlSchemaFreeValue(vctxt->value);
25627 vctxt->value = NULL;
25628 }
25629 /*
25630 * Check character content.
25631 */
25632 if (inode->decl == NULL) {
25633 /*
25634 * Speedup if no declaration exists.
25635 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025636 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025637 ret = xmlSchemaVCheckINodeDataType(vctxt,
25638 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025639 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025640 ret = xmlSchemaVCheckINodeDataType(vctxt,
25641 inode, inode->typeDef->contentTypeDef,
25642 inode->value);
25643 }
25644 if (ret < 0) {
25645 VERROR_INT("xmlSchemaValidatorPopElem",
25646 "calling xmlSchemaVCheckCVCSimpleType()");
25647 goto internal_error;
25648 }
25649 goto end_elem;
25650 }
25651 /*
25652 * cvc-elt (3.3.4) : 5
25653 * The appropriate case among the following must be true:
25654 */
25655 /*
25656 * cvc-elt (3.3.4) : 5.1
25657 * If the declaration has a {value constraint},
25658 * the item has neither element nor character [children] and
25659 * clause 3.2 has not applied, then all of the following must be true:
25660 */
25661 if ((inode->decl->value != NULL) &&
25662 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25663 (! INODE_NILLED(inode))) {
25664 /*
25665 * cvc-elt (3.3.4) : 5.1.1
25666 * If the ·actual type definition· is a ·local type definition·
25667 * then the canonical lexical representation of the {value constraint}
25668 * value must be a valid default for the ·actual type definition· as
25669 * defined in Element Default Valid (Immediate) (§3.3.6).
25670 */
25671 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025672 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025673 * NOTE: Although the *canonical* value is stated, it is not
25674 * relevant if canonical or not. Additionally XML Schema 1.1
25675 * will removed this requirement as well.
25676 */
25677 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25678
25679 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25680 inode->decl->value, &(inode->val));
25681 if (ret != 0) {
25682 if (ret < 0) {
25683 VERROR_INT("xmlSchemaValidatorPopElem",
25684 "calling xmlSchemaCheckCOSValidDefault()");
25685 goto internal_error;
25686 }
25687 goto end_elem;
25688 }
25689 /*
25690 * Stop here, to avoid redundant validation of the value
25691 * (see following).
25692 */
25693 goto default_psvi;
25694 }
25695 /*
25696 * cvc-elt (3.3.4) : 5.1.2
25697 * The element information item with the canonical lexical
25698 * representation of the {value constraint} value used as its
25699 * ·normalized value· must be ·valid· with respect to the
25700 * ·actual type definition· as defined by Element Locally Valid (Type)
25701 * (§3.3.4).
25702 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025703 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025704 ret = xmlSchemaVCheckINodeDataType(vctxt,
25705 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025706 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025707 ret = xmlSchemaVCheckINodeDataType(vctxt,
25708 inode, inode->typeDef->contentTypeDef,
25709 inode->decl->value);
25710 }
25711 if (ret != 0) {
25712 if (ret < 0) {
25713 VERROR_INT("xmlSchemaValidatorPopElem",
25714 "calling xmlSchemaVCheckCVCSimpleType()");
25715 goto internal_error;
25716 }
25717 goto end_elem;
25718 }
25719
25720default_psvi:
25721 /*
25722 * PSVI: Create a text node on the instance element.
25723 */
25724 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25725 (inode->node != NULL)) {
25726 xmlNodePtr textChild;
25727 xmlChar *normValue;
25728 /*
25729 * VAL TODO: Normalize the value.
25730 */
25731 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25732 inode->decl->value);
25733 if (normValue != NULL) {
25734 textChild = xmlNewText(BAD_CAST normValue);
25735 xmlFree(normValue);
25736 } else
25737 textChild = xmlNewText(inode->decl->value);
25738 if (textChild == NULL) {
25739 VERROR_INT("xmlSchemaValidatorPopElem",
25740 "calling xmlNewText()");
25741 goto internal_error;
25742 } else
25743 xmlAddChild(inode->node, textChild);
25744 }
25745
25746 } else if (! INODE_NILLED(inode)) {
25747 /*
25748 * 5.2.1 The element information item must be ·valid· with respect
25749 * to the ·actual type definition· as defined by Element Locally
25750 * Valid (Type) (§3.3.4).
25751 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025752 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025753 /*
25754 * SPEC (cvc-type) (3.1)
25755 * "If the type definition is a simple type definition, ..."
25756 * (3.1.3) "If clause 3.2 of Element Locally Valid
25757 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25758 * must be ·valid· with respect to the type definition as defined
25759 * by String Valid (§3.14.4).
25760 */
25761 ret = xmlSchemaVCheckINodeDataType(vctxt,
25762 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025763 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025764 /*
25765 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25766 * definition, then the element information item must be
25767 * ·valid· with respect to the type definition as per
25768 * Element Locally Valid (Complex Type) (§3.4.4);"
25769 *
25770 * SPEC (cvc-complex-type) (2.2)
25771 * "If the {content type} is a simple type definition, ...
25772 * the ·normalized value· of the element information item is
25773 * ·valid· with respect to that simple type definition as
25774 * defined by String Valid (§3.14.4)."
25775 */
25776 ret = xmlSchemaVCheckINodeDataType(vctxt,
25777 inode, inode->typeDef->contentTypeDef, inode->value);
25778 }
25779 if (ret != 0) {
25780 if (ret < 0) {
25781 VERROR_INT("xmlSchemaValidatorPopElem",
25782 "calling xmlSchemaVCheckCVCSimpleType()");
25783 goto internal_error;
25784 }
25785 goto end_elem;
25786 }
25787 /*
25788 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25789 * not applied, all of the following must be true:
25790 */
25791 if ((inode->decl->value != NULL) &&
25792 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25793
25794 /*
25795 * TODO: We will need a computed value, when comparison is
25796 * done on computed values.
25797 */
25798 /*
25799 * 5.2.2.1 The element information item must have no element
25800 * information item [children].
25801 */
25802 if (inode->flags &
25803 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25804 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25805 VERROR(ret, NULL,
25806 "The content must not containt element nodes since "
25807 "there is a fixed value constraint");
25808 goto end_elem;
25809 } else {
25810 /*
25811 * 5.2.2.2 The appropriate case among the following must
25812 * be true:
25813 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025814 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025815 /*
25816 * 5.2.2.2.1 If the {content type} of the ·actual type
25817 * definition· is mixed, then the *initial value* of the
25818 * item must match the canonical lexical representation
25819 * of the {value constraint} value.
25820 *
25821 * ... the *initial value* of an element information
25822 * item is the string composed of, in order, the
25823 * [character code] of each character information item in
25824 * the [children] of that element information item.
25825 */
25826 if (! xmlStrEqual(inode->value, inode->decl->value)){
25827 /*
25828 * VAL TODO: Report invalid & expected values as well.
25829 * VAL TODO: Implement the canonical stuff.
25830 */
25831 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025832 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025833 ret, NULL, NULL,
25834 "The initial value '%s' does not match the fixed "
25835 "value constraint '%s'",
25836 inode->value, inode->decl->value);
25837 goto end_elem;
25838 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025839 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025840 /*
25841 * 5.2.2.2.2 If the {content type} of the ·actual type
25842 * definition· is a simple type definition, then the
25843 * *actual value* of the item must match the canonical
25844 * lexical representation of the {value constraint} value.
25845 */
25846 /*
25847 * VAL TODO: *actual value* is the normalized value, impl.
25848 * this.
25849 * VAL TODO: Report invalid & expected values as well.
25850 * VAL TODO: Implement a comparison with the computed values.
25851 */
25852 if (! xmlStrEqual(inode->value,
25853 inode->decl->value)) {
25854 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025855 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025856 ret, NULL, NULL,
25857 "The actual value '%s' does not match the fixed "
25858 "value constraint '%s'",
25859 inode->value,
25860 inode->decl->value);
25861 goto end_elem;
25862 }
25863 }
25864 }
25865 }
25866 }
25867
25868end_elem:
25869 if (vctxt->depth < 0) {
25870 /* TODO: raise error? */
25871 return (0);
25872 }
25873 if (vctxt->depth == vctxt->skipDepth)
25874 vctxt->skipDepth = -1;
25875 /*
25876 * Evaluate the history of XPath state objects.
25877 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025878 if (inode->appliedXPath &&
25879 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025880 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025881 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025882 * MAYBE TODO:
25883 * SPEC (6) "The element information item must be ·valid· with
25884 * respect to each of the {identity-constraint definitions} as per
25885 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025886 */
25887 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025888 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25889 * need to be built in any case.
25890 * We will currently build IDC node-tables and bubble them only if
25891 * keyrefs do exist.
25892 */
25893
25894 /*
25895 * Add the current IDC target-nodes to the IDC node-tables.
25896 */
25897 if ((inode->idcMatchers != NULL) &&
25898 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25899 {
25900 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25901 goto internal_error;
25902 }
25903 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025904 * Validate IDC keyrefs.
25905 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025906 if (vctxt->inode->hasKeyrefs)
25907 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25908 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025909 /*
25910 * Merge/free the IDC table.
25911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025912 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025913#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025914 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025915 inode->nsName,
25916 inode->localName,
25917 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025918#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025919 if ((vctxt->depth > 0) &&
25920 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25921 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025922 /*
25923 * Merge the IDC node table with the table of the parent node.
25924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025925 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25926 goto internal_error;
25927 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025928 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025930 * Clear the current ielem.
25931 * VAL TODO: Don't free the PSVI IDC tables if they are
25932 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025933 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025934 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025935 /*
25936 * Skip further processing if we are on the validation root.
25937 */
25938 if (vctxt->depth == 0) {
25939 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025940 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025941 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025942 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025943 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025944 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025945 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025946 if (vctxt->aidcs != NULL) {
25947 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25948 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025949 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025950 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025951 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025952 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025953 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025954 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025955 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025956 }
25957 aidc = aidc->next;
25958 } while (aidc != NULL);
25959 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025960 vctxt->depth--;
25961 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025962 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025963 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025964 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25965 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025966 return (ret);
25967
25968internal_error:
25969 vctxt->err = -1;
25970 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025971}
25972
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025973/*
25974* 3.4.4 Complex Type Definition Validation Rules
25975* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
25976*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000025977static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025978xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000025979{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025980 xmlSchemaNodeInfoPtr pielem;
25981 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000025982 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000025983
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025984 if (vctxt->depth <= 0) {
25985 VERROR_INT("xmlSchemaValidateChildElem",
25986 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025987 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025988 }
25989 pielem = vctxt->elemInfos[vctxt->depth -1];
25990 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
25991 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025992 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025993 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025995 if (INODE_NILLED(pielem)) {
25996 /*
25997 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
25998 */
25999 ACTIVATE_PARENT_ELEM;
26000 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26001 VERROR(ret, NULL,
26002 "Neither character nor element content is allowed, "
26003 "because the element was 'nilled'");
26004 ACTIVATE_ELEM;
26005 goto unexpected_elem;
26006 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026007
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026008 ptype = pielem->typeDef;
26009
26010 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26011 /*
26012 * Workaround for "anyType": we have currently no content model
26013 * assigned for "anyType", so handle it explicitely.
26014 * "anyType" has an unbounded, lax "any" wildcard.
26015 */
26016 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26017 vctxt->inode->localName,
26018 vctxt->inode->nsName);
26019
26020 if (vctxt->inode->decl == NULL) {
26021 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026022 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026023 * Process "xsi:type".
26024 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026025 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026026 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26027 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26028 if (iattr != NULL) {
26029 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26030 &(vctxt->inode->typeDef), NULL);
26031 if (ret != 0) {
26032 if (ret == -1) {
26033 VERROR_INT("xmlSchemaValidateChildElem",
26034 "calling xmlSchemaProcessXSIType() to "
26035 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026036 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026038 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026040 } else {
26041 /*
26042 * Fallback to "anyType".
26043 *
26044 * SPEC (cvc-assess-elt)
26045 * "If the item cannot be ·strictly assessed·, [...]
26046 * an element information item's schema validity may be laxly
26047 * assessed if its ·context-determined declaration· is not
26048 * skip by ·validating· with respect to the ·ur-type
26049 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26050 */
26051 vctxt->inode->typeDef =
26052 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026053 }
26054 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026055 return (0);
26056 }
26057
26058 switch (ptype->contentType) {
26059 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026060 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026061 * SPEC (2.1) "If the {content type} is empty, then the
26062 * element information item has no character or element
26063 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026064 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026065 ACTIVATE_PARENT_ELEM
26066 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26067 VERROR(ret, NULL,
26068 "Element content is not allowed, "
26069 "because the content type is empty");
26070 ACTIVATE_ELEM
26071 goto unexpected_elem;
26072 break;
26073
26074 case XML_SCHEMA_CONTENT_MIXED:
26075 case XML_SCHEMA_CONTENT_ELEMENTS: {
26076 xmlRegExecCtxtPtr regexCtxt;
26077 xmlChar *values[10];
26078 int terminal, nbval = 10, nbneg;
26079
26080 /* VAL TODO: Optimized "anyType" validation.*/
26081
26082 if (ptype->contModel == NULL) {
26083 VERROR_INT("xmlSchemaValidateChildElem",
26084 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026085 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026086 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026087 /*
26088 * Safety belf for evaluation if the cont. model was already
26089 * examined to be invalid.
26090 */
26091 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26092 VERROR_INT("xmlSchemaValidateChildElem",
26093 "validating elem, but elem content is already invalid");
26094 return (-1);
26095 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026096
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026097 regexCtxt = pielem->regexCtxt;
26098 if (regexCtxt == NULL) {
26099 /*
26100 * Create the regex context.
26101 */
26102 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26103 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26104 vctxt);
26105 if (regexCtxt == NULL) {
26106 VERROR_INT("xmlSchemaValidateChildElem",
26107 "failed to create a regex context");
26108 return (-1);
26109 }
26110 pielem->regexCtxt = regexCtxt;
26111#ifdef DEBUG_AUTOMATA
26112 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26113 pielem->localName);
26114#endif
26115 }
26116
26117 /*
26118 * SPEC (2.4) "If the {content type} is element-only or mixed,
26119 * then the sequence of the element information item's
26120 * element information item [children], if any, taken in
26121 * order, is ·valid· with respect to the {content type}'s
26122 * particle, as defined in Element Sequence Locally Valid
26123 * (Particle) (§3.9.4)."
26124 */
26125 ret = xmlRegExecPushString2(regexCtxt,
26126 vctxt->inode->localName,
26127 vctxt->inode->nsName,
26128 vctxt->inode);
26129#ifdef DEBUG_AUTOMATA
26130 if (ret < 0)
26131 xmlGenericError(xmlGenericErrorContext,
26132 "AUTOMATON push ERROR for '%s' on '%s'\n",
26133 vctxt->inode->localName, pielem->localName);
26134 else
26135 xmlGenericError(xmlGenericErrorContext,
26136 "AUTOMATON push OK for '%s' on '%s'\n",
26137 vctxt->inode->localName, pielem->localName);
26138#endif
26139 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26140 VERROR_INT("xmlSchemaValidateChildElem",
26141 "calling xmlRegExecPushString2()");
26142 return (-1);
26143 }
26144 if (ret < 0) {
26145 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26146 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026147 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026148 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26149 "This element is not expected",
26150 nbval, nbneg, values);
26151 ret = vctxt->err;
26152 goto unexpected_elem;
26153 } else
26154 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026155 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026156 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026157 case XML_SCHEMA_CONTENT_SIMPLE:
26158 case XML_SCHEMA_CONTENT_BASIC:
26159 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026160 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026161 /*
26162 * SPEC (cvc-complex-type) (2.2)
26163 * "If the {content type} is a simple type definition, then
26164 * the element information item has no element information
26165 * item [children], ..."
26166 */
26167 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26168 VERROR(ret, NULL, "Element content is not allowed, "
26169 "because the content type is a simple type definition");
26170 } else {
26171 /*
26172 * SPEC (cvc-type) (3.1.2) "The element information item must
26173 * have no element information item [children]."
26174 */
26175 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26176 VERROR(ret, NULL, "Element content is not allowed, "
26177 "because the type definition is simple");
26178 }
26179 ACTIVATE_ELEM
26180 ret = vctxt->err;
26181 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026182 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026183
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026184 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026185 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026186 }
26187 return (ret);
26188unexpected_elem:
26189 /*
26190 * Pop this element and set the skipDepth to skip
26191 * all further content of the parent element.
26192 */
26193 vctxt->skipDepth = vctxt->depth;
26194 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26195 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26196 return (ret);
26197}
26198
26199#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26200#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26201#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26202
26203static int
26204xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26205 int nodeType, const xmlChar *value, int len,
26206 int mode, int *consumed)
26207{
26208 /*
26209 * Unfortunately we have to duplicate the text sometimes.
26210 * OPTIMIZE: Maybe we could skip it, if:
26211 * 1. content type is simple
26212 * 2. whitespace is "collapse"
26213 * 3. it consists of whitespace only
26214 *
26215 * Process character content.
26216 */
26217 if (consumed != NULL)
26218 *consumed = 0;
26219 if (INODE_NILLED(vctxt->inode)) {
26220 /*
26221 * SPEC cvc-elt (3.3.4 - 3.2.1)
26222 * "The element information item must have no character or
26223 * element information item [children]."
26224 */
26225 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26226 "Neither character nor element content is allowed "
26227 "because the element is 'nilled'");
26228 return (vctxt->err);
26229 }
26230 /*
26231 * SPEC (2.1) "If the {content type} is empty, then the
26232 * element information item has no character or element
26233 * information item [children]."
26234 */
26235 if (vctxt->inode->typeDef->contentType ==
26236 XML_SCHEMA_CONTENT_EMPTY) {
26237 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26238 "Character content is not allowed, "
26239 "because the content type is empty");
26240 return (vctxt->err);
26241 }
26242
26243 if (vctxt->inode->typeDef->contentType ==
26244 XML_SCHEMA_CONTENT_ELEMENTS) {
26245 if ((nodeType != XML_TEXT_NODE) ||
26246 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26247 /*
26248 * SPEC cvc-complex-type (2.3)
26249 * "If the {content type} is element-only, then the
26250 * element information item has no character information
26251 * item [children] other than those whose [character
26252 * code] is defined as a white space in [XML 1.0 (Second
26253 * Edition)]."
26254 */
26255 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26256 "Character content other than whitespace is not allowed "
26257 "because the content type is 'element-only'");
26258 return (vctxt->err);
26259 }
26260 return (0);
26261 }
26262
26263 if ((value == NULL) || (value[0] == 0))
26264 return (0);
26265 /*
26266 * Save the value.
26267 * NOTE that even if the content type is *mixed*, we need the
26268 * *initial value* for default/fixed value constraints.
26269 */
26270 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26271 ((vctxt->inode->decl == NULL) ||
26272 (vctxt->inode->decl->value == NULL)))
26273 return (0);
26274
26275 if (vctxt->inode->value == NULL) {
26276 /*
26277 * Set the value.
26278 */
26279 switch (mode) {
26280 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26281 /*
26282 * When working on a tree.
26283 */
26284 vctxt->inode->value = value;
26285 break;
26286 case XML_SCHEMA_PUSH_TEXT_CREATED:
26287 /*
26288 * When working with the reader.
26289 * The value will be freed by the element info.
26290 */
26291 vctxt->inode->value = value;
26292 if (consumed != NULL)
26293 *consumed = 1;
26294 vctxt->inode->flags |=
26295 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26296 break;
26297 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26298 /*
26299 * When working with SAX.
26300 * The value will be freed by the element info.
26301 */
26302 if (len != -1)
26303 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26304 else
26305 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26306 vctxt->inode->flags |=
26307 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26308 break;
26309 default:
26310 break;
26311 }
26312 } else {
26313 /*
26314 * Concat the value.
26315 */
26316 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026317 vctxt->inode->value = BAD_CAST xmlStrncat(
26318 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026319 } else {
26320 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026321 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026322 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26323 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026324 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026325
26326 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026327}
26328
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026329static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026330xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026331{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026332 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026333
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026334 if ((vctxt->skipDepth != -1) &&
26335 (vctxt->depth >= vctxt->skipDepth)) {
26336 VERROR_INT("xmlSchemaValidateElem",
26337 "in skip-state");
26338 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026339 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026340 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026341 /*
26342 * URGENT TODO: Better to fully stop validation
26343 * if there was an error during dynamic schema construction.
26344 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026345 if (xmlSchemaAssembleByXSI(vctxt) == -1)
26346 goto internal_error;
26347 }
26348 if (vctxt->depth > 0) {
26349 /*
26350 * Validate this element against the content model
26351 * of the parent.
26352 */
26353 ret = xmlSchemaValidateChildElem(vctxt);
26354 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026355 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026356 VERROR_INT("xmlSchemaValidateElem",
26357 "calling xmlSchemaStreamValidateChildElement()");
26358 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026359 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026360 goto exit;
26361 }
26362 if (vctxt->depth == vctxt->skipDepth)
26363 goto exit;
26364 if ((vctxt->inode->decl == NULL) &&
26365 (vctxt->inode->typeDef == NULL)) {
26366 VERROR_INT("xmlSchemaValidateElem",
26367 "the child element was valid but neither the "
26368 "declaration nor the type was set");
26369 goto internal_error;
26370 }
26371 } else {
26372 /*
26373 * Get the declaration of the validation root.
26374 */
26375 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26376 vctxt->inode->localName,
26377 vctxt->inode->nsName);
26378 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026379 ret = XML_SCHEMAV_CVC_ELT_1;
26380 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026381 "No matching global declaration available "
26382 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026383 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026384 }
26385 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026386
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026387 if (vctxt->inode->decl == NULL)
26388 goto type_validation;
26389
26390 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26391 int skip;
26392 /*
26393 * Wildcards.
26394 */
26395 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26396 if (ret != 0) {
26397 if (ret < 0) {
26398 VERROR_INT("xmlSchemaValidateElem",
26399 "calling xmlSchemaValidateElemWildcard()");
26400 goto internal_error;
26401 }
26402 goto exit;
26403 }
26404 if (skip) {
26405 vctxt->skipDepth = vctxt->depth;
26406 goto exit;
26407 }
26408 /*
26409 * The declaration might be set by the wildcard validation,
26410 * when the processContents is "lax" or "strict".
26411 */
26412 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26413 /*
26414 * Clear the "decl" field to not confuse further processing.
26415 */
26416 vctxt->inode->decl = NULL;
26417 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026418 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026419 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026420 /*
26421 * Validate against the declaration.
26422 */
26423 ret = xmlSchemaValidateElemDecl(vctxt);
26424 if (ret != 0) {
26425 if (ret < 0) {
26426 VERROR_INT("xmlSchemaValidateElem",
26427 "calling xmlSchemaValidateElemDecl()");
26428 goto internal_error;
26429 }
26430 goto exit;
26431 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026432 /*
26433 * Validate against the type definition.
26434 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026435type_validation:
26436
26437 if (vctxt->inode->typeDef == NULL) {
26438 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26439 ret = XML_SCHEMAV_CVC_TYPE_1;
26440 VERROR(ret, NULL,
26441 "The type definition is absent");
26442 goto exit;
26443 }
26444 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26445 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26446 ret = XML_SCHEMAV_CVC_TYPE_2;
26447 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026448 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026449 goto exit;
26450 }
26451 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026452 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026453 * during validation against the declaration. This must be done
26454 * _before_ attribute validation.
26455 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026456 if (vctxt->xpathStates != NULL) {
26457 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026458 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026459 if (ret == -1) {
26460 VERROR_INT("xmlSchemaValidateElem",
26461 "calling xmlSchemaXPathEvaluate()");
26462 goto internal_error;
26463 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026464 }
26465 /*
26466 * Validate attributes.
26467 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026468 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026469 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026470 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026471
26472 ret = xmlSchemaVAttributesComplex(vctxt);
26473 }
26474 } else if (vctxt->nbAttrInfos != 0) {
26475
26476 ret = xmlSchemaVAttributesSimple(vctxt);
26477 }
26478 /*
26479 * Clear registered attributes.
26480 */
26481 if (vctxt->nbAttrInfos != 0)
26482 xmlSchemaClearAttrInfos(vctxt);
26483 if (ret == -1) {
26484 VERROR_INT("xmlSchemaValidateElem",
26485 "calling attributes validation");
26486 goto internal_error;
26487 }
26488 /*
26489 * Don't return an error if attributes are invalid on purpose.
26490 */
26491 ret = 0;
26492
26493exit:
26494 if (ret != 0)
26495 vctxt->skipDepth = vctxt->depth;
26496 return (ret);
26497internal_error:
26498 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026499}
26500
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026501#ifdef XML_SCHEMA_READER_ENABLED
26502static int
26503xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026504{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026505 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26506 int depth, nodeType, ret = 0, consumed;
26507 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026508
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026509 vctxt->depth = -1;
26510 ret = xmlTextReaderRead(vctxt->reader);
26511 /*
26512 * Move to the document element.
26513 */
26514 while (ret == 1) {
26515 nodeType = xmlTextReaderNodeType(vctxt->reader);
26516 if (nodeType == XML_ELEMENT_NODE)
26517 goto root_found;
26518 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026519 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026520 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026521
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026522root_found:
26523
26524 do {
26525 depth = xmlTextReaderDepth(vctxt->reader);
26526 nodeType = xmlTextReaderNodeType(vctxt->reader);
26527
26528 if (nodeType == XML_ELEMENT_NODE) {
26529
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026530 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026531 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26532 VERROR_INT("xmlSchemaVReaderWalk",
26533 "calling xmlSchemaValidatorPushElem()");
26534 goto internal_error;
26535 }
26536 ielem = vctxt->inode;
26537 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26538 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26539 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26540 /*
26541 * Is the element empty?
26542 */
26543 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26544 if (ret == -1) {
26545 VERROR_INT("xmlSchemaVReaderWalk",
26546 "calling xmlTextReaderIsEmptyElement()");
26547 goto internal_error;
26548 }
26549 if (ret) {
26550 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26551 }
26552 /*
26553 * Register attributes.
26554 */
26555 vctxt->nbAttrInfos = 0;
26556 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26557 if (ret == -1) {
26558 VERROR_INT("xmlSchemaVReaderWalk",
26559 "calling xmlTextReaderMoveToFirstAttribute()");
26560 goto internal_error;
26561 }
26562 if (ret == 1) {
26563 do {
26564 /*
26565 * VAL TODO: How do we know that the reader works on a
26566 * node tree, to be able to pass a node here?
26567 */
26568 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26569 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26570 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26571 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26572
26573 VERROR_INT("xmlSchemaVReaderWalk",
26574 "calling xmlSchemaValidatorPushAttribute()");
26575 goto internal_error;
26576 }
26577 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26578 if (ret == -1) {
26579 VERROR_INT("xmlSchemaVReaderWalk",
26580 "calling xmlTextReaderMoveToFirstAttribute()");
26581 goto internal_error;
26582 }
26583 } while (ret == 1);
26584 /*
26585 * Back to element position.
26586 */
26587 ret = xmlTextReaderMoveToElement(vctxt->reader);
26588 if (ret == -1) {
26589 VERROR_INT("xmlSchemaVReaderWalk",
26590 "calling xmlTextReaderMoveToElement()");
26591 goto internal_error;
26592 }
26593 }
26594 /*
26595 * Validate the element.
26596 */
26597 ret= xmlSchemaValidateElem(vctxt);
26598 if (ret != 0) {
26599 if (ret == -1) {
26600 VERROR_INT("xmlSchemaVReaderWalk",
26601 "calling xmlSchemaValidateElem()");
26602 goto internal_error;
26603 }
26604 goto exit;
26605 }
26606 if (vctxt->depth == vctxt->skipDepth) {
26607 int curDepth;
26608 /*
26609 * Skip all content.
26610 */
26611 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26612 ret = xmlTextReaderRead(vctxt->reader);
26613 curDepth = xmlTextReaderDepth(vctxt->reader);
26614 while ((ret == 1) && (curDepth != depth)) {
26615 ret = xmlTextReaderRead(vctxt->reader);
26616 curDepth = xmlTextReaderDepth(vctxt->reader);
26617 }
26618 if (ret < 0) {
26619 /*
26620 * VAL TODO: A reader error occured; what to do here?
26621 */
26622 ret = 1;
26623 goto exit;
26624 }
26625 }
26626 goto leave_elem;
26627 }
26628 /*
26629 * READER VAL TODO: Is an END_ELEM really never called
26630 * if the elem is empty?
26631 */
26632 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26633 goto leave_elem;
26634 } else if (nodeType == END_ELEM) {
26635 /*
26636 * Process END of element.
26637 */
26638leave_elem:
26639 ret = xmlSchemaValidatorPopElem(vctxt);
26640 if (ret != 0) {
26641 if (ret < 0) {
26642 VERROR_INT("xmlSchemaVReaderWalk",
26643 "calling xmlSchemaValidatorPopElem()");
26644 goto internal_error;
26645 }
26646 goto exit;
26647 }
26648 if (vctxt->depth >= 0)
26649 ielem = vctxt->inode;
26650 else
26651 ielem = NULL;
26652 } else if ((nodeType == XML_TEXT_NODE) ||
26653 (nodeType == XML_CDATA_SECTION_NODE) ||
26654 (nodeType == WHTSP) ||
26655 (nodeType == SIGN_WHTSP)) {
26656 /*
26657 * Process character content.
26658 */
26659 xmlChar *value;
26660
26661 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26662 nodeType = XML_TEXT_NODE;
26663
26664 value = xmlTextReaderValue(vctxt->reader);
26665 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26666 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26667 if (! consumed)
26668 xmlFree(value);
26669 if (ret == -1) {
26670 VERROR_INT("xmlSchemaVReaderWalk",
26671 "calling xmlSchemaVPushText()");
26672 goto internal_error;
26673 }
26674 } else if ((nodeType == XML_ENTITY_NODE) ||
26675 (nodeType == XML_ENTITY_REF_NODE)) {
26676 /*
26677 * VAL TODO: What to do with entities?
26678 */
26679 TODO
26680 }
26681 /*
26682 * Read next node.
26683 */
26684 ret = xmlTextReaderRead(vctxt->reader);
26685 } while (ret == 1);
26686
26687exit:
26688 return (ret);
26689internal_error:
26690 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026691}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026692#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026693
26694/************************************************************************
26695 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026696 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026697 * *
26698 ************************************************************************/
26699
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026700/*
26701* Process text content.
26702*/
26703static void
26704xmlSchemaSAXHandleText(void *ctx,
26705 const xmlChar * ch,
26706 int len)
26707{
26708 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26709
26710 if (vctxt->depth < 0)
26711 return;
26712 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26713 return;
26714 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26715 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26716 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26717 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26718 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26719 "calling xmlSchemaVPushText()");
26720 vctxt->err = -1;
26721 xmlStopParser(vctxt->parserCtxt);
26722 }
26723}
26724
26725/*
26726* Process CDATA content.
26727*/
26728static void
26729xmlSchemaSAXHandleCDataSection(void *ctx,
26730 const xmlChar * ch,
26731 int len)
26732{
26733 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26734
26735 if (vctxt->depth < 0)
26736 return;
26737 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26738 return;
26739 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26740 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26741 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26742 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26743 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26744 "calling xmlSchemaVPushText()");
26745 vctxt->err = -1;
26746 xmlStopParser(vctxt->parserCtxt);
26747 }
26748}
26749
26750static void
26751xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26752 const xmlChar * name ATTRIBUTE_UNUSED)
26753{
26754 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26755
26756 if (vctxt->depth < 0)
26757 return;
26758 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26759 return;
26760 /* SAX VAL TODO: What to do here? */
26761 TODO
26762}
26763
26764static void
26765xmlSchemaSAXHandleStartElementNs(void *ctx,
26766 const xmlChar * localname,
26767 const xmlChar * prefix ATTRIBUTE_UNUSED,
26768 const xmlChar * URI,
26769 int nb_namespaces,
26770 const xmlChar ** namespaces,
26771 int nb_attributes,
26772 int nb_defaulted ATTRIBUTE_UNUSED,
26773 const xmlChar ** attributes)
26774{
26775 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26776 int ret;
26777 xmlSchemaNodeInfoPtr ielem;
26778 int i, j;
26779
26780 /*
26781 * SAX VAL TODO: What to do with nb_defaulted?
26782 */
26783 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026784 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026785 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026786 vctxt->depth++;
26787 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026788 return;
26789 /*
26790 * Push the element.
26791 */
26792 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26793 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26794 "calling xmlSchemaValidatorPushElem()");
26795 goto internal_error;
26796 }
26797 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026798 /*
26799 * TODO: Is this OK?
26800 */
26801 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026802 ielem->localName = localname;
26803 ielem->nsName = URI;
26804 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26805 /*
26806 * Register namespaces on the elem info.
26807 */
26808 if (nb_namespaces != 0) {
26809 /*
26810 * Although the parser builds its own namespace list,
26811 * we have no access to it, so we'll use an own one.
26812 */
26813 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26814 /*
26815 * Store prefix and namespace name.
26816 */
26817 if (ielem->nsBindings == NULL) {
26818 ielem->nsBindings =
26819 (const xmlChar **) xmlMalloc(10 *
26820 sizeof(const xmlChar *));
26821 if (ielem->nsBindings == NULL) {
26822 xmlSchemaVErrMemory(vctxt,
26823 "allocating namespace bindings for SAX validation",
26824 NULL);
26825 goto internal_error;
26826 }
26827 ielem->nbNsBindings = 0;
26828 ielem->sizeNsBindings = 5;
26829 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26830 ielem->sizeNsBindings *= 2;
26831 ielem->nsBindings =
26832 (const xmlChar **) xmlRealloc(
26833 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026834 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026835 if (ielem->nsBindings == NULL) {
26836 xmlSchemaVErrMemory(vctxt,
26837 "re-allocating namespace bindings for SAX validation",
26838 NULL);
26839 goto internal_error;
26840 }
26841 }
26842
26843 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26844 if (namespaces[j+1][0] == 0) {
26845 /*
26846 * Handle xmlns="".
26847 */
26848 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26849 } else
26850 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26851 namespaces[j+1];
26852 ielem->nbNsBindings++;
26853 }
26854 }
26855 /*
26856 * Register attributes.
26857 * SAX VAL TODO: We are not adding namespace declaration
26858 * attributes yet.
26859 */
26860 if (nb_attributes != 0) {
26861 xmlChar *value;
26862
26863 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26864 /*
26865 * Duplicate the value.
26866 */
26867 value = xmlStrndup(attributes[j+3],
26868 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026869 /*
26870 * TODO: Set the node line.
26871 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026872 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026873 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026874 value, 1);
26875 if (ret == -1) {
26876 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26877 "calling xmlSchemaValidatorPushAttribute()");
26878 goto internal_error;
26879 }
26880 }
26881 }
26882 /*
26883 * Validate the element.
26884 */
26885 ret = xmlSchemaValidateElem(vctxt);
26886 if (ret != 0) {
26887 if (ret == -1) {
26888 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26889 "calling xmlSchemaValidateElem()");
26890 goto internal_error;
26891 }
26892 goto exit;
26893 }
26894
26895exit:
26896 return;
26897internal_error:
26898 vctxt->err = -1;
26899 xmlStopParser(vctxt->parserCtxt);
26900 return;
26901}
26902
26903static void
26904xmlSchemaSAXHandleEndElementNs(void *ctx,
26905 const xmlChar * localname ATTRIBUTE_UNUSED,
26906 const xmlChar * prefix ATTRIBUTE_UNUSED,
26907 const xmlChar * URI ATTRIBUTE_UNUSED)
26908{
26909 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26910 int res;
26911
26912 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026913 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026914 */
26915 if (vctxt->skipDepth != -1) {
26916 if (vctxt->depth > vctxt->skipDepth) {
26917 vctxt->depth--;
26918 return;
26919 } else
26920 vctxt->skipDepth = -1;
26921 }
26922 /*
26923 * SAX VAL TODO: Just a temporary check.
26924 */
26925 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26926 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26927 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26928 "elem pop mismatch");
26929 }
26930 res = xmlSchemaValidatorPopElem(vctxt);
26931 if (res != 0) {
26932 if (res < 0) {
26933 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26934 "calling xmlSchemaValidatorPopElem()");
26935 goto internal_error;
26936 }
26937 goto exit;
26938 }
26939exit:
26940 return;
26941internal_error:
26942 vctxt->err = -1;
26943 xmlStopParser(vctxt->parserCtxt);
26944 return;
26945}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026946
Daniel Veillard4255d502002-04-16 15:50:10 +000026947/************************************************************************
26948 * *
26949 * Validation interfaces *
26950 * *
26951 ************************************************************************/
26952
26953/**
26954 * xmlSchemaNewValidCtxt:
26955 * @schema: a precompiled XML Schemas
26956 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026957 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026958 *
26959 * Returns the validation context or NULL in case of error
26960 */
26961xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026962xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
26963{
Daniel Veillard4255d502002-04-16 15:50:10 +000026964 xmlSchemaValidCtxtPtr ret;
26965
26966 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
26967 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026968 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000026969 return (NULL);
26970 }
26971 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026972 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026973 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000026974 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026975 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000026976 return (ret);
26977}
26978
26979/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026980 * xmlSchemaClearValidCtxt:
26981 * @ctxt: the schema validation context
26982 *
26983 * Free the resources associated to the schema validation context;
26984 * leaves some fields alive intended for reuse of the context.
26985 */
26986static void
26987xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
26988{
26989 if (vctxt == NULL)
26990 return;
26991
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026992 /*
26993 * TODO: Should we clear the flags?
26994 * Might be problematic if one reuses the context
26995 * and assumes that the options remain the same.
26996 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026997 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026998 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026999 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027000#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027001 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027002#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027003 vctxt->hasKeyrefs = 0;
27004
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027005 if (vctxt->value != NULL) {
27006 xmlSchemaFreeValue(vctxt->value);
27007 vctxt->value = NULL;
27008 }
27009 /*
27010 * Augmented IDC information.
27011 */
27012 if (vctxt->aidcs != NULL) {
27013 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27014 do {
27015 next = cur->next;
27016 xmlFree(cur);
27017 cur = next;
27018 } while (cur != NULL);
27019 vctxt->aidcs = NULL;
27020 }
27021 if (vctxt->idcNodes != NULL) {
27022 int i;
27023 xmlSchemaPSVIIDCNodePtr item;
27024
27025 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027026 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027027 xmlFree(item->keys);
27028 xmlFree(item);
27029 }
27030 xmlFree(vctxt->idcNodes);
27031 vctxt->idcNodes = NULL;
27032 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027033 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027034 * Note that we won't delete the XPath state pool here.
27035 */
27036 if (vctxt->xpathStates != NULL) {
27037 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27038 vctxt->xpathStates = NULL;
27039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027040 /*
27041 * Attribute info.
27042 */
27043 if (vctxt->nbAttrInfos != 0) {
27044 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027045 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027046 /*
27047 * Element info.
27048 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027049 if (vctxt->elemInfos != NULL) {
27050 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027051 xmlSchemaNodeInfoPtr ei;
27052
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027053 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027054 ei = vctxt->elemInfos[i];
27055 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027056 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027057 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027058 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027059 }
27060 xmlSchemaItemListClear(vctxt->nodeQNames);
27061 /* Recreate the dict. */
27062 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027063 /*
27064 * TODO: Is is save to recreate it? Do we have a scenario
27065 * where the user provides the dict?
27066 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027067 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027068}
27069
27070/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027071 * xmlSchemaFreeValidCtxt:
27072 * @ctxt: the schema validation context
27073 *
27074 * Free the resources associated to the schema validation context
27075 */
27076void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027077xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27078{
Daniel Veillard4255d502002-04-16 15:50:10 +000027079 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027080 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027081 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027082 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027083 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027084 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027085 if (ctxt->idcNodes != NULL) {
27086 int i;
27087 xmlSchemaPSVIIDCNodePtr item;
27088
27089 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027090 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027091 xmlFree(item->keys);
27092 xmlFree(item);
27093 }
27094 xmlFree(ctxt->idcNodes);
27095 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027096 if (ctxt->idcKeys != NULL) {
27097 int i;
27098 for (i = 0; i < ctxt->nbIdcKeys; i++)
27099 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27100 xmlFree(ctxt->idcKeys);
27101 }
27102
27103 if (ctxt->xpathStates != NULL)
27104 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27105 if (ctxt->xpathStatePool != NULL)
27106 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27107
27108 /*
27109 * Augmented IDC information.
27110 */
27111 if (ctxt->aidcs != NULL) {
27112 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27113 do {
27114 next = cur->next;
27115 xmlFree(cur);
27116 cur = next;
27117 } while (cur != NULL);
27118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027119 if (ctxt->attrInfos != NULL) {
27120 int i;
27121 xmlSchemaAttrInfoPtr attr;
27122
27123 /* Just a paranoid call to the cleanup. */
27124 if (ctxt->nbAttrInfos != 0)
27125 xmlSchemaClearAttrInfos(ctxt);
27126 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27127 attr = ctxt->attrInfos[i];
27128 xmlFree(attr);
27129 }
27130 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027131 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027132 if (ctxt->elemInfos != NULL) {
27133 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027134 xmlSchemaNodeInfoPtr ei;
27135
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027136 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027137 ei = ctxt->elemInfos[i];
27138 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027139 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027140 xmlSchemaClearElemInfo(ei);
27141 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027142 }
27143 xmlFree(ctxt->elemInfos);
27144 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027145 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027146 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027147 if (ctxt->dict != NULL)
27148 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027149 xmlFree(ctxt);
27150}
27151
27152/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027153 * xmlSchemaIsValid:
27154 * @ctxt: the schema validation context
27155 *
27156 * Check if any error was detected during validation.
27157 *
27158 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27159 * of internal error.
27160 */
27161int
27162xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27163{
27164 if (ctxt == NULL)
27165 return(-1);
27166 return(ctxt->err == 0);
27167}
27168
27169/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027170 * xmlSchemaSetValidErrors:
27171 * @ctxt: a schema validation context
27172 * @err: the error function
27173 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027174 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027175 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027176 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027177 */
27178void
27179xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027180 xmlSchemaValidityErrorFunc err,
27181 xmlSchemaValidityWarningFunc warn, void *ctx)
27182{
Daniel Veillard4255d502002-04-16 15:50:10 +000027183 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027184 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027185 ctxt->error = err;
27186 ctxt->warning = warn;
27187 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027188 if (ctxt->pctxt != NULL)
27189 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027190}
27191
27192/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027193 * xmlSchemaSetValidStructuredErrors:
27194 * @ctxt: a schema validation context
27195 * @serror: the structured error function
27196 * @ctx: the functions context
27197 *
27198 * Set the structured error callback
27199 */
27200void
27201xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27202 xmlStructuredErrorFunc serror, void *ctx)
27203{
27204 if (ctxt == NULL)
27205 return;
27206 ctxt->serror = serror;
27207 ctxt->error = NULL;
27208 ctxt->warning = NULL;
27209 ctxt->userData = ctx;
27210}
27211
27212/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027213 * xmlSchemaGetValidErrors:
27214 * @ctxt: a XML-Schema validation context
27215 * @err: the error function result
27216 * @warn: the warning function result
27217 * @ctx: the functions context result
27218 *
27219 * Get the error and warning callback informations
27220 *
27221 * Returns -1 in case of error and 0 otherwise
27222 */
27223int
27224xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27225 xmlSchemaValidityErrorFunc * err,
27226 xmlSchemaValidityWarningFunc * warn, void **ctx)
27227{
27228 if (ctxt == NULL)
27229 return (-1);
27230 if (err != NULL)
27231 *err = ctxt->error;
27232 if (warn != NULL)
27233 *warn = ctxt->warning;
27234 if (ctx != NULL)
27235 *ctx = ctxt->userData;
27236 return (0);
27237}
27238
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027239
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027240/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027241 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027242 * @ctxt: a schema validation context
27243 * @options: a combination of xmlSchemaValidOption
27244 *
27245 * Sets the options to be used during the validation.
27246 *
27247 * Returns 0 in case of success, -1 in case of an
27248 * API error.
27249 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027250int
27251xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27252 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027253
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027254{
27255 int i;
27256
27257 if (ctxt == NULL)
27258 return (-1);
27259 /*
27260 * WARNING: Change the start value if adding to the
27261 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027262 * TODO: Is there an other, more easy to maintain,
27263 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027264 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027265 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027266 if (options & 1<<i)
27267 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027268 }
27269 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027270 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027271}
27272
27273/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027274 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027275 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027276 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027277 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027278 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027279 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027280 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027281int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027282xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027283
27284{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027285 if (ctxt == NULL)
27286 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027287 else
27288 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027289}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027290
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027291static int
27292xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27293{
27294 xmlAttrPtr attr;
27295 int ret = 0;
27296 xmlSchemaNodeInfoPtr ielem = NULL;
27297 xmlNodePtr node, valRoot;
27298 const xmlChar *nsName;
27299
27300 /* DOC VAL TODO: Move this to the start function. */
27301 valRoot = xmlDocGetRootElement(vctxt->doc);
27302 if (valRoot == NULL) {
27303 /* VAL TODO: Error code? */
27304 VERROR(1, NULL, "The document has no document element");
27305 return (1);
27306 }
27307 vctxt->depth = -1;
27308 vctxt->validationRoot = valRoot;
27309 node = valRoot;
27310 while (node != NULL) {
27311 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27312 goto next_sibling;
27313 if (node->type == XML_ELEMENT_NODE) {
27314
27315 /*
27316 * Init the node-info.
27317 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027318 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027319 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27320 goto internal_error;
27321 ielem = vctxt->inode;
27322 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027323 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027324 ielem->localName = node->name;
27325 if (node->ns != NULL)
27326 ielem->nsName = node->ns->href;
27327 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27328 /*
27329 * Register attributes.
27330 * DOC VAL TODO: We do not register namespace declaration
27331 * attributes yet.
27332 */
27333 vctxt->nbAttrInfos = 0;
27334 if (node->properties != NULL) {
27335 attr = node->properties;
27336 do {
27337 if (attr->ns != NULL)
27338 nsName = attr->ns->href;
27339 else
27340 nsName = NULL;
27341 ret = xmlSchemaValidatorPushAttribute(vctxt,
27342 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027343 /*
27344 * Note that we give it the line number of the
27345 * parent element.
27346 */
27347 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027348 attr->name, nsName, 0,
27349 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27350 if (ret == -1) {
27351 VERROR_INT("xmlSchemaDocWalk",
27352 "calling xmlSchemaValidatorPushAttribute()");
27353 goto internal_error;
27354 }
27355 attr = attr->next;
27356 } while (attr);
27357 }
27358 /*
27359 * Validate the element.
27360 */
27361 ret = xmlSchemaValidateElem(vctxt);
27362 if (ret != 0) {
27363 if (ret == -1) {
27364 VERROR_INT("xmlSchemaDocWalk",
27365 "calling xmlSchemaValidateElem()");
27366 goto internal_error;
27367 }
27368 /*
27369 * Don't stop validation; just skip the content
27370 * of this element.
27371 */
27372 goto leave_node;
27373 }
27374 if ((vctxt->skipDepth != -1) &&
27375 (vctxt->depth >= vctxt->skipDepth))
27376 goto leave_node;
27377 } else if ((node->type == XML_TEXT_NODE) ||
27378 (node->type == XML_CDATA_SECTION_NODE)) {
27379 /*
27380 * Process character content.
27381 */
27382 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27383 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27384 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27385 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27386 if (ret < 0) {
27387 VERROR_INT("xmlSchemaVDocWalk",
27388 "calling xmlSchemaVPushText()");
27389 goto internal_error;
27390 }
27391 /*
27392 * DOC VAL TODO: Should we skip further validation of the
27393 * element content here?
27394 */
27395 } else if ((node->type == XML_ENTITY_NODE) ||
27396 (node->type == XML_ENTITY_REF_NODE)) {
27397 /*
27398 * DOC VAL TODO: What to do with entities?
27399 */
27400 TODO
27401 } else {
27402 goto leave_node;
27403 /*
27404 * DOC VAL TODO: XInclude nodes, etc.
27405 */
27406 }
27407 /*
27408 * Walk the doc.
27409 */
27410 if (node->children != NULL) {
27411 node = node->children;
27412 continue;
27413 }
27414leave_node:
27415 if (node->type == XML_ELEMENT_NODE) {
27416 /*
27417 * Leaving the scope of an element.
27418 */
27419 if (node != vctxt->inode->node) {
27420 VERROR_INT("xmlSchemaVDocWalk",
27421 "element position mismatch");
27422 goto internal_error;
27423 }
27424 ret = xmlSchemaValidatorPopElem(vctxt);
27425 if (ret != 0) {
27426 if (ret < 0) {
27427 VERROR_INT("xmlSchemaVDocWalk",
27428 "calling xmlSchemaValidatorPopElem()");
27429 goto internal_error;
27430 }
27431 }
27432 if (node == valRoot)
27433 goto exit;
27434 }
27435next_sibling:
27436 if (node->next != NULL)
27437 node = node->next;
27438 else {
27439 node = node->parent;
27440 goto leave_node;
27441 }
27442 }
27443
27444exit:
27445 return (ret);
27446internal_error:
27447 return (-1);
27448}
27449
27450static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027451xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027452 /*
27453 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027455 vctxt->err = 0;
27456 vctxt->nberrors = 0;
27457 vctxt->depth = -1;
27458 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027459 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027460 vctxt->hasKeyrefs = 0;
27461#ifdef ENABLE_IDC_NODE_TABLES
27462 vctxt->createIDCNodeTables = 1;
27463#else
27464 vctxt->createIDCNodeTables = 0;
27465#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027466 /*
27467 * Create a schema + parser if necessary.
27468 */
27469 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027470 xmlSchemaParserCtxtPtr pctxt;
27471
27472 vctxt->xsiAssemble = 1;
27473 /*
27474 * If not schema was given then we will create a schema
27475 * dynamically using XSI schema locations.
27476 *
27477 * Create the schema parser context.
27478 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027479 if ((vctxt->pctxt == NULL) &&
27480 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27481 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027482 pctxt = vctxt->pctxt;
27483 pctxt->xsiAssemble = 1;
27484 /*
27485 * Create the schema.
27486 */
27487 vctxt->schema = xmlSchemaNewSchema(pctxt);
27488 if (vctxt->schema == NULL)
27489 return (-1);
27490 /*
27491 * Create the schema construction context.
27492 */
27493 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27494 if (pctxt->constructor == NULL)
27495 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027496 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027497 /*
27498 * Take ownership of the constructor to be able to free it.
27499 */
27500 pctxt->ownsConstructor = 1;
27501 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027502 /*
27503 * Augment the IDC definitions.
27504 */
27505 if (vctxt->schema->idcDef != NULL) {
27506 xmlHashScan(vctxt->schema->idcDef,
27507 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27508 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027509 return(0);
27510}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027511
Daniel Veillardf10ae122005-07-10 19:03:16 +000027512static void
27513xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027514 if (vctxt->xsiAssemble) {
27515 if (vctxt->schema != NULL) {
27516 xmlSchemaFree(vctxt->schema);
27517 vctxt->schema = NULL;
27518 }
27519 }
27520 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027521}
27522
27523static int
27524xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27525{
27526 int ret = 0;
27527
27528 if (xmlSchemaPreRun(vctxt) < 0)
27529 return(-1);
27530
27531 if (vctxt->doc != NULL) {
27532 /*
27533 * Tree validation.
27534 */
27535 ret = xmlSchemaVDocWalk(vctxt);
27536#ifdef LIBXML_READER_ENABLED
27537 } else if (vctxt->reader != NULL) {
27538 /*
27539 * XML Reader validation.
27540 */
27541#ifdef XML_SCHEMA_READER_ENABLED
27542 ret = xmlSchemaVReaderWalk(vctxt);
27543#endif
27544#endif
27545 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27546 /*
27547 * SAX validation.
27548 */
27549 ret = xmlParseDocument(vctxt->parserCtxt);
27550 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027551 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027552 "no instance to validate");
27553 ret = -1;
27554 }
27555
27556 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027557 if (ret == 0)
27558 ret = vctxt->err;
27559 return (ret);
27560}
27561
27562/**
27563 * xmlSchemaValidateOneElement:
27564 * @ctxt: a schema validation context
27565 * @elem: an element node
27566 *
27567 * Validate a branch of a tree, starting with the given @elem.
27568 *
27569 * Returns 0 if the element and its subtree is valid, a positive error
27570 * code number otherwise and -1 in case of an internal or API error.
27571 */
27572int
27573xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27574{
27575 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27576 return (-1);
27577
27578 if (ctxt->schema == NULL)
27579 return (-1);
27580
27581 ctxt->doc = elem->doc;
27582 ctxt->node = elem;
27583 ctxt->validationRoot = elem;
27584 return(xmlSchemaVStart(ctxt));
27585}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027586
Daniel Veillard259f0df2004-08-18 09:13:18 +000027587/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027588 * xmlSchemaValidateDoc:
27589 * @ctxt: a schema validation context
27590 * @doc: a parsed document tree
27591 *
27592 * Validate a document tree in memory.
27593 *
27594 * Returns 0 if the document is schemas valid, a positive error code
27595 * number otherwise and -1 in case of internal or API error.
27596 */
27597int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027598xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27599{
Daniel Veillard4255d502002-04-16 15:50:10 +000027600 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027601 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027602
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027603 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027604 ctxt->node = xmlDocGetRootElement(doc);
27605 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027606 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027607 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27608 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027609 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027610 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027611 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027612 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027613 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027614}
27615
Daniel Veillardcdc82732005-07-08 15:04:06 +000027616
27617/************************************************************************
27618 * *
27619 * Function and data for SAX streaming API *
27620 * *
27621 ************************************************************************/
27622typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27623typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27624
27625struct _xmlSchemaSplitSAXData {
27626 xmlSAXHandlerPtr user_sax;
27627 void *user_data;
27628 xmlSchemaValidCtxtPtr ctxt;
27629 xmlSAXHandlerPtr schemas_sax;
27630};
27631
Daniel Veillard971771e2005-07-09 17:32:57 +000027632#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27633
27634struct _xmlSchemaSAXPlug {
27635 unsigned int magic;
27636
27637 /* the original callbacks informations */
27638 xmlSAXHandlerPtr *user_sax_ptr;
27639 xmlSAXHandlerPtr user_sax;
27640 void **user_data_ptr;
27641 void *user_data;
27642
27643 /* the block plugged back and validation informations */
27644 xmlSAXHandler schemas_sax;
27645 xmlSchemaValidCtxtPtr ctxt;
27646};
27647
Daniel Veillardcdc82732005-07-08 15:04:06 +000027648/* All those functions just bounces to the user provided SAX handlers */
27649static void
27650internalSubsetSplit(void *ctx, const xmlChar *name,
27651 const xmlChar *ExternalID, const xmlChar *SystemID)
27652{
Daniel Veillard971771e2005-07-09 17:32:57 +000027653 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027654 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27655 (ctxt->user_sax->internalSubset != NULL))
27656 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27657 SystemID);
27658}
27659
27660static int
27661isStandaloneSplit(void *ctx)
27662{
Daniel Veillard971771e2005-07-09 17:32:57 +000027663 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027664 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27665 (ctxt->user_sax->isStandalone != NULL))
27666 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27667 return(0);
27668}
27669
27670static int
27671hasInternalSubsetSplit(void *ctx)
27672{
Daniel Veillard971771e2005-07-09 17:32:57 +000027673 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027674 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27675 (ctxt->user_sax->hasInternalSubset != NULL))
27676 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27677 return(0);
27678}
27679
27680static int
27681hasExternalSubsetSplit(void *ctx)
27682{
Daniel Veillard971771e2005-07-09 17:32:57 +000027683 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027684 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27685 (ctxt->user_sax->hasExternalSubset != NULL))
27686 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27687 return(0);
27688}
27689
27690static void
27691externalSubsetSplit(void *ctx, const xmlChar *name,
27692 const xmlChar *ExternalID, const xmlChar *SystemID)
27693{
Daniel Veillard971771e2005-07-09 17:32:57 +000027694 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027695 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27696 (ctxt->user_sax->internalSubset != NULL))
27697 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27698 SystemID);
27699}
27700
27701static xmlParserInputPtr
27702resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27703{
Daniel Veillard971771e2005-07-09 17:32:57 +000027704 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027705 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27706 (ctxt->user_sax->resolveEntity != NULL))
27707 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27708 systemId));
27709 return(NULL);
27710}
27711
27712static xmlEntityPtr
27713getEntitySplit(void *ctx, const xmlChar *name)
27714{
Daniel Veillard971771e2005-07-09 17:32:57 +000027715 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027716 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27717 (ctxt->user_sax->getEntity != NULL))
27718 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27719 return(NULL);
27720}
27721
27722static xmlEntityPtr
27723getParameterEntitySplit(void *ctx, const xmlChar *name)
27724{
Daniel Veillard971771e2005-07-09 17:32:57 +000027725 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027726 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27727 (ctxt->user_sax->getParameterEntity != NULL))
27728 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27729 return(NULL);
27730}
27731
27732
27733static void
27734entityDeclSplit(void *ctx, const xmlChar *name, int type,
27735 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27736{
Daniel Veillard971771e2005-07-09 17:32:57 +000027737 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027738 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27739 (ctxt->user_sax->entityDecl != NULL))
27740 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27741 systemId, content);
27742}
27743
27744static void
27745attributeDeclSplit(void *ctx, const xmlChar * elem,
27746 const xmlChar * name, int type, int def,
27747 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27748{
Daniel Veillard971771e2005-07-09 17:32:57 +000027749 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027750 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27751 (ctxt->user_sax->attributeDecl != NULL)) {
27752 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27753 def, defaultValue, tree);
27754 } else {
27755 xmlFreeEnumeration(tree);
27756 }
27757}
27758
27759static void
27760elementDeclSplit(void *ctx, const xmlChar *name, int type,
27761 xmlElementContentPtr content)
27762{
Daniel Veillard971771e2005-07-09 17:32:57 +000027763 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027764 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27765 (ctxt->user_sax->elementDecl != NULL))
27766 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27767}
27768
27769static void
27770notationDeclSplit(void *ctx, const xmlChar *name,
27771 const xmlChar *publicId, const xmlChar *systemId)
27772{
Daniel Veillard971771e2005-07-09 17:32:57 +000027773 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027774 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27775 (ctxt->user_sax->notationDecl != NULL))
27776 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27777 systemId);
27778}
27779
27780static void
27781unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27782 const xmlChar *publicId, const xmlChar *systemId,
27783 const xmlChar *notationName)
27784{
Daniel Veillard971771e2005-07-09 17:32:57 +000027785 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027786 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27787 (ctxt->user_sax->unparsedEntityDecl != NULL))
27788 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27789 systemId, notationName);
27790}
27791
27792static void
27793setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27794{
Daniel Veillard971771e2005-07-09 17:32:57 +000027795 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027796 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27797 (ctxt->user_sax->setDocumentLocator != NULL))
27798 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27799}
27800
27801static void
27802startDocumentSplit(void *ctx)
27803{
Daniel Veillard971771e2005-07-09 17:32:57 +000027804 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027805 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27806 (ctxt->user_sax->startDocument != NULL))
27807 ctxt->user_sax->startDocument(ctxt->user_data);
27808}
27809
27810static void
27811endDocumentSplit(void *ctx)
27812{
Daniel Veillard971771e2005-07-09 17:32:57 +000027813 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027814 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27815 (ctxt->user_sax->endDocument != NULL))
27816 ctxt->user_sax->endDocument(ctxt->user_data);
27817}
27818
27819static void
27820processingInstructionSplit(void *ctx, const xmlChar *target,
27821 const xmlChar *data)
27822{
Daniel Veillard971771e2005-07-09 17:32:57 +000027823 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027824 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27825 (ctxt->user_sax->processingInstruction != NULL))
27826 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27827}
27828
27829static void
27830commentSplit(void *ctx, const xmlChar *value)
27831{
Daniel Veillard971771e2005-07-09 17:32:57 +000027832 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027833 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27834 (ctxt->user_sax->comment != NULL))
27835 ctxt->user_sax->comment(ctxt->user_data, value);
27836}
27837
27838/*
27839 * Varargs error callbacks to the user application, harder ...
27840 */
27841
Daniel Veillardffa3c742005-07-21 13:24:09 +000027842static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027843warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027844 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027845 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27846 (ctxt->user_sax->warning != NULL)) {
27847 TODO
27848 }
27849}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027850static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027851errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027852 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027853 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27854 (ctxt->user_sax->error != NULL)) {
27855 TODO
27856 }
27857}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027858static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027859fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027860 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027861 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27862 (ctxt->user_sax->fatalError != NULL)) {
27863 TODO
27864 }
27865}
27866
27867/*
27868 * Those are function where both the user handler and the schemas handler
27869 * need to be called.
27870 */
27871static void
27872charactersSplit(void *ctx, const xmlChar *ch, int len)
27873{
Daniel Veillard971771e2005-07-09 17:32:57 +000027874 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027875 if (ctxt == NULL)
27876 return;
27877 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27878 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27879 if (ctxt->ctxt != NULL)
27880 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27881}
27882
27883static void
27884ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27885{
Daniel Veillard971771e2005-07-09 17:32:57 +000027886 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027887 if (ctxt == NULL)
27888 return;
27889 if ((ctxt->user_sax != NULL) &&
27890 (ctxt->user_sax->ignorableWhitespace != NULL))
27891 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27892 if (ctxt->ctxt != NULL)
27893 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27894}
27895
27896static void
27897cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27898{
Daniel Veillard971771e2005-07-09 17:32:57 +000027899 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027900 if (ctxt == NULL)
27901 return;
27902 if ((ctxt->user_sax != NULL) &&
27903 (ctxt->user_sax->ignorableWhitespace != NULL))
27904 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27905 if (ctxt->ctxt != NULL)
27906 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27907}
27908
27909static void
27910referenceSplit(void *ctx, const xmlChar *name)
27911{
Daniel Veillard971771e2005-07-09 17:32:57 +000027912 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027913 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27914 (ctxt->user_sax->reference != NULL))
27915 ctxt->user_sax->reference(ctxt->user_data, name);
27916 if (ctxt->ctxt != NULL)
27917 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27918}
27919
27920static void
27921startElementNsSplit(void *ctx, const xmlChar * localname,
27922 const xmlChar * prefix, const xmlChar * URI,
27923 int nb_namespaces, const xmlChar ** namespaces,
27924 int nb_attributes, int nb_defaulted,
27925 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027926 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027927 if (ctxt == NULL)
27928 return;
27929 if ((ctxt->user_sax != NULL) &&
27930 (ctxt->user_sax->startElementNs != NULL))
27931 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27932 URI, nb_namespaces, namespaces,
27933 nb_attributes, nb_defaulted,
27934 attributes);
27935 if (ctxt->ctxt != NULL)
27936 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27937 URI, nb_namespaces, namespaces,
27938 nb_attributes, nb_defaulted,
27939 attributes);
27940}
27941
27942static void
27943endElementNsSplit(void *ctx, const xmlChar * localname,
27944 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027945 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027946 if (ctxt == NULL)
27947 return;
27948 if ((ctxt->user_sax != NULL) &&
27949 (ctxt->user_sax->endElementNs != NULL))
27950 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27951 if (ctxt->ctxt != NULL)
27952 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27953}
27954
Daniel Veillard4255d502002-04-16 15:50:10 +000027955/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027956 * xmlSchemaSAXPlug:
27957 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000027958 * @sax: a pointer to the original xmlSAXHandlerPtr
27959 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000027960 *
27961 * Plug a SAX based validation layer in a SAX parsing event flow.
27962 * The original @saxptr and @dataptr data are replaced by new pointers
27963 * but the calls to the original will be maintained.
27964 *
27965 * Returns a pointer to a data structure needed to unplug the validation layer
27966 * or NULL in case of errors.
27967 */
27968xmlSchemaSAXPlugPtr
27969xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
27970 xmlSAXHandlerPtr *sax, void **user_data)
27971{
27972 xmlSchemaSAXPlugPtr ret;
27973 xmlSAXHandlerPtr old_sax;
27974
27975 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
27976 return(NULL);
27977
27978 /*
27979 * We only allow to plug into SAX2 event streams
27980 */
27981 old_sax = *sax;
27982 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
27983 return(NULL);
27984 if ((old_sax != NULL) &&
27985 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
27986 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
27987 return(NULL);
27988
27989 /*
27990 * everything seems right allocate the local data needed for that layer
27991 */
27992 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
27993 if (ret == NULL) {
27994 return(NULL);
27995 }
27996 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
27997 ret->magic = XML_SAX_PLUG_MAGIC;
27998 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
27999 ret->ctxt = ctxt;
28000 ret->user_sax_ptr = sax;
28001 ret->user_sax = old_sax;
28002 if (old_sax == NULL) {
28003 /*
28004 * go direct, no need for the split block and functions.
28005 */
28006 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28007 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28008 /*
28009 * Note that we use the same text-function for both, to prevent
28010 * the parser from testing for ignorable whitespace.
28011 */
28012 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28013 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28014
28015 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28016 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28017
28018 ret->user_data = ctxt;
28019 *user_data = ctxt;
28020 } else {
28021 /*
28022 * for each callback unused by Schemas initialize it to the Split
28023 * routine only if non NULL in the user block, this can speed up
28024 * things at the SAX level.
28025 */
28026 if (old_sax->internalSubset != NULL)
28027 ret->schemas_sax.internalSubset = internalSubsetSplit;
28028 if (old_sax->isStandalone != NULL)
28029 ret->schemas_sax.isStandalone = isStandaloneSplit;
28030 if (old_sax->hasInternalSubset != NULL)
28031 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28032 if (old_sax->hasExternalSubset != NULL)
28033 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28034 if (old_sax->resolveEntity != NULL)
28035 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28036 if (old_sax->getEntity != NULL)
28037 ret->schemas_sax.getEntity = getEntitySplit;
28038 if (old_sax->entityDecl != NULL)
28039 ret->schemas_sax.entityDecl = entityDeclSplit;
28040 if (old_sax->notationDecl != NULL)
28041 ret->schemas_sax.notationDecl = notationDeclSplit;
28042 if (old_sax->attributeDecl != NULL)
28043 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28044 if (old_sax->elementDecl != NULL)
28045 ret->schemas_sax.elementDecl = elementDeclSplit;
28046 if (old_sax->unparsedEntityDecl != NULL)
28047 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28048 if (old_sax->setDocumentLocator != NULL)
28049 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28050 if (old_sax->startDocument != NULL)
28051 ret->schemas_sax.startDocument = startDocumentSplit;
28052 if (old_sax->endDocument != NULL)
28053 ret->schemas_sax.endDocument = endDocumentSplit;
28054 if (old_sax->processingInstruction != NULL)
28055 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28056 if (old_sax->comment != NULL)
28057 ret->schemas_sax.comment = commentSplit;
28058 if (old_sax->warning != NULL)
28059 ret->schemas_sax.warning = warningSplit;
28060 if (old_sax->error != NULL)
28061 ret->schemas_sax.error = errorSplit;
28062 if (old_sax->fatalError != NULL)
28063 ret->schemas_sax.fatalError = fatalErrorSplit;
28064 if (old_sax->getParameterEntity != NULL)
28065 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28066 if (old_sax->externalSubset != NULL)
28067 ret->schemas_sax.externalSubset = externalSubsetSplit;
28068
28069 /*
28070 * the 6 schemas callback have to go to the splitter functions
28071 * Note that we use the same text-function for ignorableWhitespace
28072 * if possible, to prevent the parser from testing for ignorable
28073 * whitespace.
28074 */
28075 ret->schemas_sax.characters = charactersSplit;
28076 if ((old_sax->ignorableWhitespace != NULL) &&
28077 (old_sax->ignorableWhitespace != old_sax->characters))
28078 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28079 else
28080 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28081 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28082 ret->schemas_sax.reference = referenceSplit;
28083 ret->schemas_sax.startElementNs = startElementNsSplit;
28084 ret->schemas_sax.endElementNs = endElementNsSplit;
28085
28086 ret->user_data_ptr = user_data;
28087 ret->user_data = *user_data;
28088 *user_data = ret;
28089 }
28090
28091 /*
28092 * plug the pointers back.
28093 */
28094 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028095 ctxt->sax = *sax;
28096 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28097 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028098 return(ret);
28099}
28100
28101/**
28102 * xmlSchemaSAXUnplug:
28103 * @plug: a data structure returned by xmlSchemaSAXPlug
28104 *
28105 * Unplug a SAX based validation layer in a SAX parsing event flow.
28106 * The original pointers used in the call are restored.
28107 *
28108 * Returns 0 in case of success and -1 in case of failure.
28109 */
28110int
28111xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28112{
28113 xmlSAXHandlerPtr *sax;
28114 void **user_data;
28115
28116 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28117 return(-1);
28118 plug->magic = 0;
28119
Daniel Veillardf10ae122005-07-10 19:03:16 +000028120 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028121 /* restore the data */
28122 sax = plug->user_sax_ptr;
28123 *sax = plug->user_sax;
28124 if (plug->user_sax != NULL) {
28125 user_data = plug->user_data_ptr;
28126 *user_data = plug->user_data;
28127 }
28128
28129 /* free and return */
28130 xmlFree(plug);
28131 return(0);
28132}
28133
28134/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028135 * xmlSchemaValidateStream:
28136 * @ctxt: a schema validation context
28137 * @input: the input to use for reading the data
28138 * @enc: an optional encoding information
28139 * @sax: a SAX handler for the resulting events
28140 * @user_data: the context to provide to the SAX handler.
28141 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028142 * Validate an input based on a flow of SAX event from the parser
28143 * and forward the events to the @sax handler with the provided @user_data
28144 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028145 *
28146 * Returns 0 if the document is schemas valid, a positive error code
28147 * number otherwise and -1 in case of internal or API error.
28148 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028149int
Daniel Veillard4255d502002-04-16 15:50:10 +000028150xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028151 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28152 xmlSAXHandlerPtr sax, void *user_data)
28153{
Daniel Veillard971771e2005-07-09 17:32:57 +000028154 xmlSchemaSAXPlugPtr plug = NULL;
28155 xmlSAXHandlerPtr old_sax = NULL;
28156 xmlParserCtxtPtr pctxt = NULL;
28157 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028158 int ret;
28159
Daniel Veillard4255d502002-04-16 15:50:10 +000028160 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028161 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028162
Daniel Veillardcdc82732005-07-08 15:04:06 +000028163 /*
28164 * prepare the parser
28165 */
28166 pctxt = xmlNewParserCtxt();
28167 if (pctxt == NULL)
28168 return (-1);
28169 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028170 pctxt->sax = sax;
28171 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028172#if 0
28173 if (options)
28174 xmlCtxtUseOptions(pctxt, options);
28175#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028176 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028177
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028178 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028179 if (inputStream == NULL) {
28180 ret = -1;
28181 goto done;
28182 }
28183 inputPush(pctxt, inputStream);
28184 ctxt->parserCtxt = pctxt;
28185 ctxt->input = input;
28186
28187 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028188 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028189 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028190 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28191 if (plug == NULL) {
28192 ret = -1;
28193 goto done;
28194 }
28195 ctxt->input = input;
28196 ctxt->enc = enc;
28197 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028198 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28199 ret = xmlSchemaVStart(ctxt);
28200
28201 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28202 ret = ctxt->parserCtxt->errNo;
28203 if (ret == 0)
28204 ret = 1;
28205 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028206
28207done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028208 ctxt->parserCtxt = NULL;
28209 ctxt->sax = NULL;
28210 ctxt->input = NULL;
28211 if (plug != NULL) {
28212 xmlSchemaSAXUnplug(plug);
28213 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028214 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028215 if (pctxt != NULL) {
28216 pctxt->sax = old_sax;
28217 xmlFreeParserCtxt(pctxt);
28218 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028219 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028220}
28221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028222/**
28223 * xmlSchemaValidateFile:
28224 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028225 * @filename: the URI of the instance
28226 * @options: a future set of options, currently unused
28227 *
28228 * Do a schemas validation of the given resource, it will use the
28229 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028230 *
28231 * Returns 0 if the document is valid, a positive error code
28232 * number otherwise and -1 in case of an internal or API error.
28233 */
28234int
28235xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028236 const char * filename,
28237 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028238{
28239 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028240 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028241
28242 if ((ctxt == NULL) || (filename == NULL))
28243 return (-1);
28244
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028245 input = xmlParserInputBufferCreateFilename(filename,
28246 XML_CHAR_ENCODING_NONE);
28247 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028248 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028249 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28250 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028251 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028252}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028253
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028254#define bottom_xmlschemas
28255#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028256#endif /* LIBXML_SCHEMAS_ENABLED */