blob: f8504582178138dffcf29c8358dcc78aa7f57407 [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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000583 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000584 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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000960 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000961 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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001883 data = ctxt->errCtxt;
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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001949 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001950 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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002029 data = vctxt->errCtxt;
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;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002081 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002082 __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 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005027 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005028 default:
5029 /* Should not be hit. */
5030 return(NULL);
5031 }
5032 }
5033 }
5034subschemas:
5035 /*
5036 * Process imported/included schemas.
5037 */
5038 if (bucket->relations != NULL) {
5039 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5040
5041 /*
5042 * TODO: Marking the bucket will not avoid multiple searches
5043 * in the same schema, but avoids at least circularity.
5044 */
5045 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5046 do {
5047 if ((rel->bucket != NULL) &&
5048 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5049 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5050 type, name, nsName);
5051 if (ret != NULL)
5052 return(ret);
5053 }
5054 rel = rel->next;
5055 } while (rel != NULL);
5056 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5057 }
5058 return(NULL);
5059}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005060
5061/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005062 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005063 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005064 * @schema: the schema being built
5065 * @name: the item name
5066 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005068 * *WARNING* this interface is highly subject to change
5069 *
5070 * Returns the new struture or NULL in case of error
5071 */
5072static xmlSchemaNotationPtr
5073xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005074 const xmlChar *name, const xmlChar *nsName,
5075 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005076{
5077 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005078
5079 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5080 return (NULL);
5081
Daniel Veillard4255d502002-04-16 15:50:10 +00005082 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5083 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005085 return (NULL);
5086 }
5087 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005088 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005089 ret->name = name;
5090 ret->targetNamespace = nsName;
5091 /* TODO: do we need the node to be set?
5092 * ret->node = node;*/
5093 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 return (ret);
5095}
5096
Daniel Veillard4255d502002-04-16 15:50:10 +00005097/**
5098 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005099 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005100 * @schema: the schema being built
5101 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005102 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005103 *
5104 * Add an XML schema Attrribute declaration
5105 * *WARNING* this interface is highly subject to change
5106 *
5107 * Returns the new struture or NULL in case of error
5108 */
5109static xmlSchemaAttributePtr
5110xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005111 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005112 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005113{
5114 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005115
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005116 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 return (NULL);
5118
5119 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5120 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005121 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005122 return (NULL);
5123 }
5124 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005125 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5126 ret->node = node;
5127 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005128 ret->targetNamespace = nsName;
5129
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005130 if (topLevel)
5131 WXS_ADD_GLOBAL(ctxt, ret);
5132 else
5133 WXS_ADD_LOCAL(ctxt, ret);
5134 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 return (ret);
5136}
5137
5138/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005139 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005140 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005141 * @schema: the schema being built
5142 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005143 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005144 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005145 * Add an XML schema Attrribute declaration
5146 * *WARNING* this interface is highly subject to change
5147 *
5148 * Returns the new struture or NULL in case of error
5149 */
5150static xmlSchemaAttributeUsePtr
5151xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5152 xmlNodePtr node)
5153{
5154 xmlSchemaAttributeUsePtr ret = NULL;
5155
5156 if (pctxt == NULL)
5157 return (NULL);
5158
5159 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5160 if (ret == NULL) {
5161 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5162 return (NULL);
5163 }
5164 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5165 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5166 ret->node = node;
5167
5168 WXS_ADD_LOCAL(pctxt, ret);
5169 return (ret);
5170}
5171
5172/*
5173* xmlSchemaAddRedef:
5174*
5175* Adds a redefinition information. This is used at a later stage to:
5176* resolve references to the redefined components and to check constraints.
5177*/
5178static xmlSchemaRedefPtr
5179xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5180 xmlSchemaBucketPtr targetBucket,
5181 void *item,
5182 const xmlChar *refName,
5183 const xmlChar *refTargetNs)
5184{
5185 xmlSchemaRedefPtr ret;
5186
5187 ret = (xmlSchemaRedefPtr)
5188 xmlMalloc(sizeof(xmlSchemaRedef));
5189 if (ret == NULL) {
5190 xmlSchemaPErrMemory(pctxt,
5191 "allocating redefinition info", NULL);
5192 return (NULL);
5193 }
5194 memset(ret, 0, sizeof(xmlSchemaRedef));
5195 ret->item = item;
5196 ret->targetBucket = targetBucket;
5197 ret->refName = refName;
5198 ret->refTargetNs = refTargetNs;
5199 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5200 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5201 else
5202 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5203 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5204
5205 return (ret);
5206}
5207
5208/**
5209 * xmlSchemaAddAttributeGroupDefinition:
5210 * @ctxt: a schema parser context
5211 * @schema: the schema being built
5212 * @name: the item name
5213 * @nsName: the target namespace
5214 * @node: the corresponding node
5215 *
5216 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005217 *
5218 * Returns the new struture or NULL in case of error
5219 */
5220static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005221xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5222 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5223 const xmlChar *name,
5224 const xmlChar *nsName,
5225 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005226{
5227 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005228
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005229 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005230 return (NULL);
5231
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005232 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005233 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005235 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005236 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 }
5238 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005239 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005240 ret->name = name;
5241 ret->targetNamespace = nsName;
5242 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005243
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005244 /* TODO: Remove the flag. */
5245 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5246 if (pctxt->isRedefine) {
5247 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5248 ret, name, nsName);
5249 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005250 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005251 return(NULL);
5252 }
5253 pctxt->redefCounter = 0;
5254 }
5255 WXS_ADD_GLOBAL(pctxt, ret);
5256 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005257 return (ret);
5258}
5259
5260/**
5261 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005262 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 * @schema: the schema being built
5264 * @name: the type name
5265 * @namespace: the type namespace
5266 *
5267 * Add an XML schema Element declaration
5268 * *WARNING* this interface is highly subject to change
5269 *
5270 * Returns the new struture or NULL in case of error
5271 */
5272static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005273xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005274 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005275 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005276{
5277 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005278
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005279 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005280 return (NULL);
5281
Daniel Veillard4255d502002-04-16 15:50:10 +00005282 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5283 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005284 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005285 return (NULL);
5286 }
5287 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005288 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5289 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005290 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005291 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005292
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005293 if (topLevel)
5294 WXS_ADD_GLOBAL(ctxt, ret);
5295 else
5296 WXS_ADD_LOCAL(ctxt, ret);
5297 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 return (ret);
5299}
5300
5301/**
5302 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005303 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 * @schema: the schema being built
5305 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005306 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005307 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005308 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005309 * *WARNING* this interface is highly subject to change
5310 *
5311 * Returns the new struture or NULL in case of error
5312 */
5313static xmlSchemaTypePtr
5314xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005315 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005316 const xmlChar * name, const xmlChar * nsName,
5317 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005318{
5319 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005320
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005321 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 return (NULL);
5323
5324 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5325 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005326 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005327 return (NULL);
5328 }
5329 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005330 ret->type = type;
5331 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005332 ret->targetNamespace = nsName;
5333 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005334 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005335 if (ctxt->isRedefine) {
5336 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5337 ret, name, nsName);
5338 if (ctxt->redef == NULL) {
5339 xmlFree(ret);
5340 return(NULL);
5341 }
5342 ctxt->redefCounter = 0;
5343 }
5344 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005345 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005346 WXS_ADD_LOCAL(ctxt, ret);
5347 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005348 return (ret);
5349}
5350
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005351static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005352xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005353 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005354 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005355 const xmlChar *refNs)
5356{
5357 xmlSchemaQNameRefPtr ret;
5358
5359 ret = (xmlSchemaQNameRefPtr)
5360 xmlMalloc(sizeof(xmlSchemaQNameRef));
5361 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005362 xmlSchemaPErrMemory(pctxt,
5363 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005364 return (NULL);
5365 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005366 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005367 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5368 ret->name = refName;
5369 ret->targetNamespace = refNs;
5370 ret->item = NULL;
5371 ret->itemType = refType;
5372 /*
5373 * Store the reference item in the schema.
5374 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005375 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005376 return (ret);
5377}
5378
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005379static xmlSchemaAttributeUseProhibPtr
5380xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5381{
5382 xmlSchemaAttributeUseProhibPtr ret;
5383
5384 ret = (xmlSchemaAttributeUseProhibPtr)
5385 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5386 if (ret == NULL) {
5387 xmlSchemaPErrMemory(pctxt,
5388 "allocating attribute use prohibition", NULL);
5389 return (NULL);
5390 }
5391 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5392 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5393 WXS_ADD_LOCAL(pctxt, ret);
5394 return (ret);
5395}
5396
5397
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005398/**
5399 * xmlSchemaAddModelGroup:
5400 * @ctxt: a schema parser context
5401 * @schema: the schema being built
5402 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005403 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005404 *
5405 * Adds a schema model group
5406 * *WARNING* this interface is highly subject to change
5407 *
5408 * Returns the new struture or NULL in case of error
5409 */
5410static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005411xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5412 xmlSchemaPtr schema,
5413 xmlSchemaTypeType type,
5414 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005415{
5416 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005417
5418 if ((ctxt == NULL) || (schema == NULL))
5419 return (NULL);
5420
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005421 ret = (xmlSchemaModelGroupPtr)
5422 xmlMalloc(sizeof(xmlSchemaModelGroup));
5423 if (ret == NULL) {
5424 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5425 NULL);
5426 return (NULL);
5427 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005428 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005429 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005431 WXS_ADD_LOCAL(ctxt, ret);
5432 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5433 (type == XML_SCHEMA_TYPE_CHOICE))
5434 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005435 return (ret);
5436}
5437
5438
5439/**
5440 * xmlSchemaAddParticle:
5441 * @ctxt: a schema parser context
5442 * @schema: the schema being built
5443 * @node: the corresponding node in the schema doc
5444 * @min: the minOccurs
5445 * @max: the maxOccurs
5446 *
5447 * Adds an XML schema particle component.
5448 * *WARNING* this interface is highly subject to change
5449 *
5450 * Returns the new struture or NULL in case of error
5451 */
5452static xmlSchemaParticlePtr
5453xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5454 xmlNodePtr node, int min, int max)
5455{
5456 xmlSchemaParticlePtr ret = NULL;
5457 if ((ctxt == NULL) || (schema == NULL))
5458 return (NULL);
5459
5460#ifdef DEBUG
5461 fprintf(stderr, "Adding particle component\n");
5462#endif
5463 ret = (xmlSchemaParticlePtr)
5464 xmlMalloc(sizeof(xmlSchemaParticle));
5465 if (ret == NULL) {
5466 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5467 NULL);
5468 return (NULL);
5469 }
5470 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5471 ret->annot = NULL;
5472 ret->node = node;
5473 ret->minOccurs = min;
5474 ret->maxOccurs = max;
5475 ret->next = NULL;
5476 ret->children = NULL;
5477
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005478 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005479 /*
5480 * Note that addition to pending components will be done locally
5481 * to the specific parsing function, since the most particles
5482 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005483 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005484 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005485 return (ret);
5486}
5487
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005488/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005489 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005490 * @ctxt: a schema validation context
5491 * @schema: the schema being built
5492 * @name: the group name
5493 *
5494 * Add an XML schema Group definition
5495 *
5496 * Returns the new struture or NULL in case of error
5497 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005498static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005499xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5500 xmlSchemaPtr schema,
5501 const xmlChar *name,
5502 const xmlChar *nsName,
5503 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005504{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005505 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005506
5507 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5508 return (NULL);
5509
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005510 ret = (xmlSchemaModelGroupDefPtr)
5511 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005512 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005513 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005514 return (NULL);
5515 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005516 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005517 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005519 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005520 ret->targetNamespace = nsName;
5521
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005522 if (ctxt->isRedefine) {
5523 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5524 ret, name, nsName);
5525 if (ctxt->redef == NULL) {
5526 xmlFree(ret);
5527 return(NULL);
5528 }
5529 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005530 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005531 WXS_ADD_GLOBAL(ctxt, ret);
5532 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005533 return (ret);
5534}
5535
Daniel Veillard3646d642004-06-02 19:19:14 +00005536/**
5537 * xmlSchemaNewWildcardNs:
5538 * @ctxt: a schema validation context
5539 *
5540 * Creates a new wildcard namespace constraint.
5541 *
5542 * Returns the new struture or NULL in case of error
5543 */
5544static xmlSchemaWildcardNsPtr
5545xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5546{
5547 xmlSchemaWildcardNsPtr ret;
5548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005549 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005550 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5551 if (ret == NULL) {
5552 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005553 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005554 }
5555 ret->value = NULL;
5556 ret->next = NULL;
5557 return (ret);
5558}
5559
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005560static xmlSchemaIDCPtr
5561xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5562 const xmlChar *name, const xmlChar *nsName,
5563 int category, xmlNodePtr node)
5564{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005565 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005566
5567 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5568 return (NULL);
5569
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005570 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5571 if (ret == NULL) {
5572 xmlSchemaPErrMemory(ctxt,
5573 "allocating an identity-constraint definition", NULL);
5574 return (NULL);
5575 }
5576 memset(ret, 0, sizeof(xmlSchemaIDC));
5577 /* The target namespace of the parent element declaration. */
5578 ret->targetNamespace = nsName;
5579 ret->name = name;
5580 ret->type = category;
5581 ret->node = node;
5582
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005583 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005584 /*
5585 * Only keyrefs need to be fixup up.
5586 */
5587 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005588 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005589 return (ret);
5590}
5591
Daniel Veillard3646d642004-06-02 19:19:14 +00005592/**
5593 * xmlSchemaAddWildcard:
5594 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005595 * @schema: a schema
5596 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005597 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005598 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005599 *
5600 * Returns the new struture or NULL in case of error
5601 */
5602static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005603xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5604 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005605{
5606 xmlSchemaWildcardPtr ret = NULL;
5607
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005608 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005609 return (NULL);
5610
5611 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5612 if (ret == NULL) {
5613 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5614 return (NULL);
5615 }
5616 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005617 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005618 ret->node = node;
5619 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005620 return (ret);
5621}
5622
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005623static void
5624xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5625{
5626 if (group == NULL)
5627 return;
5628 if (group->members != NULL)
5629 xmlSchemaItemListFree(group->members);
5630 xmlFree(group);
5631}
5632
5633static xmlSchemaSubstGroupPtr
5634xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5635 xmlSchemaElementPtr head)
5636{
5637 xmlSchemaSubstGroupPtr ret;
5638
5639 /* Init subst group hash. */
5640 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5641 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5642 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5643 return(NULL);
5644 }
5645 /* Create a new substitution group. */
5646 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5647 if (ret == NULL) {
5648 xmlSchemaPErrMemory(NULL,
5649 "allocating a substitution group container", NULL);
5650 return(NULL);
5651 }
5652 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5653 ret->head = head;
5654 /* Create list of members. */
5655 ret->members = xmlSchemaItemListCreate();
5656 if (ret->members == NULL) {
5657 xmlSchemaSubstGroupFree(ret);
5658 return(NULL);
5659 }
5660 /* Add subst group to hash. */
5661 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5662 head->name, head->targetNamespace, ret) != 0) {
5663 PERROR_INT("xmlSchemaSubstGroupAdd",
5664 "failed to add a new substitution container");
5665 xmlSchemaSubstGroupFree(ret);
5666 return(NULL);
5667 }
5668 return(ret);
5669}
5670
5671static xmlSchemaSubstGroupPtr
5672xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5673 xmlSchemaElementPtr head)
5674{
5675 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676 return(NULL);
5677 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5678 head->name, head->targetNamespace));
5679
5680}
5681
5682/**
5683 * xmlSchemaAddElementSubstitutionMember:
5684 * @pctxt: a schema parser context
5685 * @head: the head of the substitution group
5686 * @member: the new member of the substitution group
5687 *
5688 * Allocate a new annotation structure.
5689 *
5690 * Returns the newly allocated structure or NULL in case or error
5691 */
5692static int
5693xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5694 xmlSchemaElementPtr head,
5695 xmlSchemaElementPtr member)
5696{
5697 xmlSchemaSubstGroupPtr substGroup = NULL;
5698
5699 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5700 return (-1);
5701
5702 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5703 if (substGroup == NULL)
5704 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5705 if (substGroup == NULL)
5706 return(-1);
5707 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5708 return(-1);
5709 return(0);
5710}
5711
Daniel Veillard4255d502002-04-16 15:50:10 +00005712/************************************************************************
5713 * *
5714 * Utilities for parsing *
5715 * *
5716 ************************************************************************/
5717
Daniel Veillard4255d502002-04-16 15:50:10 +00005718/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005719 * xmlSchemaPValAttrNodeQNameValue:
5720 * @ctxt: a schema parser context
5721 * @schema: the schema context
5722 * @ownerDes: the designation of the parent element
5723 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005724 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005725 * @local: the resulting local part if found, the attribute value otherwise
5726 * @uri: the resulting namespace URI if found
5727 *
5728 * Extracts the local name and the URI of a QName value and validates it.
5729 * This one is intended to be used on attribute values that
5730 * should resolve to schema components.
5731 *
5732 * Returns 0, in case the QName is valid, a positive error code
5733 * if not valid and -1 if an internal error occurs.
5734 */
5735static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005738 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 xmlAttrPtr attr,
5740 const xmlChar *value,
5741 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 const xmlChar **local)
5743{
5744 const xmlChar *pref;
5745 xmlNsPtr ns;
5746 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005747
Daniel Veillardc0826a72004-08-10 14:17:33 +00005748 *uri = NULL;
5749 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005750 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005751 if (ret > 0) {
5752 xmlSchemaPSimpleTypeErr(ctxt,
5753 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5754 ownerItem, (xmlNodePtr) attr,
5755 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5756 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005757 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 } else if (ret < 0)
5760 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005761
5762 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005763 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 if (ns)
5765 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5766 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005767 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5768 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 /*
5770 * This one takes care of included schemas with no
5771 * target namespace.
5772 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005773 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005774 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005775 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005776 return (0);
5777 }
5778 /*
5779 * At this point xmlSplitQName3 has to return a local name.
5780 */
5781 *local = xmlSplitQName3(value, &len);
5782 *local = xmlDictLookup(ctxt->dict, *local, -1);
5783 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005784 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5785 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005786 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005787 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005788 ownerItem, (xmlNodePtr) attr,
5789 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5790 "The value '%s' of simple type 'xs:QName' has no "
5791 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005792 return (ctxt->err);
5793 } else {
5794 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005795 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005796 return (0);
5797}
5798
5799/**
5800 * xmlSchemaPValAttrNodeQName:
5801 * @ctxt: a schema parser context
5802 * @schema: the schema context
5803 * @ownerDes: the designation of the owner element
5804 * @ownerItem: the owner as a schema object
5805 * @attr: the attribute node
5806 * @local: the resulting local part if found, the attribute value otherwise
5807 * @uri: the resulting namespace URI if found
5808 *
5809 * Extracts and validates the QName of an attribute value.
5810 * This one is intended to be used on attribute values that
5811 * should resolve to schema components.
5812 *
5813 * Returns 0, in case the QName is valid, a positive error code
5814 * if not valid and -1 if an internal error occurs.
5815 */
5816static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005817xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005818 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005819 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005820 xmlAttrPtr attr,
5821 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005822 const xmlChar **local)
5823{
5824 const xmlChar *value;
5825
5826 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005827 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005828 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005829}
5830
5831/**
5832 * xmlSchemaPValAttrQName:
5833 * @ctxt: a schema parser context
5834 * @schema: the schema context
5835 * @ownerDes: the designation of the parent element
5836 * @ownerItem: the owner as a schema object
5837 * @ownerElem: the parent node of the attribute
5838 * @name: the name of the attribute
5839 * @local: the resulting local part if found, the attribute value otherwise
5840 * @uri: the resulting namespace URI if found
5841 *
5842 * Extracts and validates the QName of an attribute value.
5843 *
5844 * Returns 0, in case the QName is valid, a positive error code
5845 * if not valid and -1 if an internal error occurs.
5846 */
5847static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005848xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5849 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005850 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005851 xmlNodePtr ownerElem,
5852 const char *name,
5853 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005854 const xmlChar **local)
5855{
5856 xmlAttrPtr attr;
5857
5858 attr = xmlSchemaGetPropNode(ownerElem, name);
5859 if (attr == NULL) {
5860 *local = NULL;
5861 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005862 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005863 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005864 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005865 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866}
5867
5868/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005869 * xmlSchemaPValAttrID:
5870 * @ctxt: a schema parser context
5871 * @schema: the schema context
5872 * @ownerDes: the designation of the parent element
5873 * @ownerItem: the owner as a schema object
5874 * @ownerElem: the parent node of the attribute
5875 * @name: the name of the attribute
5876 *
5877 * Extracts and validates the ID of an attribute value.
5878 *
5879 * Returns 0, in case the ID is valid, a positive error code
5880 * if not valid and -1 if an internal error occurs.
5881 */
5882static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005883xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005884{
5885 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005886 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005887
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005888 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005889 return(0);
5890 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5891 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005892 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005893 /*
5894 * NOTE: the IDness might have already be declared in the DTD
5895 */
5896 if (attr->atype != XML_ATTRIBUTE_ID) {
5897 xmlIDPtr res;
5898 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899
5900 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005901 * TODO: Use xmlSchemaStrip here; it's not exported at this
5902 * moment.
5903 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005904 strip = xmlSchemaCollapseString(value);
5905 if (strip != NULL) {
5906 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005907 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005908 }
5909 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005910 if (res == NULL) {
5911 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005912 xmlSchemaPSimpleTypeErr(ctxt,
5913 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005914 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005915 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5916 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005917 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005918 } else
5919 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005920 }
5921 } else if (ret > 0) {
5922 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005923 xmlSchemaPSimpleTypeErr(ctxt,
5924 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005925 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005926 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5927 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5928 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005929 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005930 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005931 if (value != NULL)
5932 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005933
5934 return (ret);
5935}
5936
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005937static int
5938xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5939 xmlNodePtr ownerElem,
5940 const xmlChar *name)
5941{
5942 xmlAttrPtr attr;
5943
5944 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5945 if (attr == NULL)
5946 return(0);
5947 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5948
5949}
5950
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005951/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005952 * xmlGetMaxOccurs:
5953 * @ctxt: a schema validation context
5954 * @node: a subtree containing XML Schema informations
5955 *
5956 * Get the maxOccurs property
5957 *
5958 * Returns the default if not found, or the value
5959 */
5960static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005961xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5962 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005963{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005964 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005965 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005966 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005967
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005968 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5969 if (attr == NULL)
5970 return (def);
5971 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005972
5973 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005974 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005975 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005976 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5977 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005979 val, NULL, NULL, NULL);
5980 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005981 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005982 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005983 }
5984
5985 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005986 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005987 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005988 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005989 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005990 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5991 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005992 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005993 val, NULL, NULL, NULL);
5994 return (def);
5995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005996 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005997 ret = ret * 10 + (*cur - '0');
5998 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 }
William M. Brack76e95df2003-10-18 16:20:14 +00006000 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006001 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006002 /*
6003 * TODO: Restrict the maximal value to Integer.
6004 */
6005 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006006 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006007 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6008 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006009 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006010 val, NULL, NULL, NULL);
6011 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006012 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006013 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006014}
6015
6016/**
6017 * xmlGetMinOccurs:
6018 * @ctxt: a schema validation context
6019 * @node: a subtree containing XML Schema informations
6020 *
6021 * Get the minOccurs property
6022 *
6023 * Returns the default if not found, or the value
6024 */
6025static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006026xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006027 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006028{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006029 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006030 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006031 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006032
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006033 attr = xmlSchemaGetPropNode(node, "minOccurs");
6034 if (attr == NULL)
6035 return (def);
6036 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006037 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006038 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006039 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006040 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006041 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006042 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6043 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006044 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006045 val, NULL, NULL, NULL);
6046 return (def);
6047 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006048 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006049 ret = ret * 10 + (*cur - '0');
6050 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 }
William M. Brack76e95df2003-10-18 16:20:14 +00006052 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006053 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006054 /*
6055 * TODO: Restrict the maximal value to Integer.
6056 */
6057 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006058 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006059 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6060 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006061 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006062 val, NULL, NULL, NULL);
6063 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006064 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006065 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006066}
6067
6068/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006069 * xmlSchemaPGetBoolNodeValue:
6070 * @ctxt: a schema validation context
6071 * @ownerDes: owner designation
6072 * @ownerItem: the owner as a schema item
6073 * @node: the node holding the value
6074 *
6075 * Converts a boolean string value into 1 or 0.
6076 *
6077 * Returns 0 or 1.
6078 */
6079static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006080xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006081 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006082 xmlNodePtr node)
6083{
6084 xmlChar *value = NULL;
6085 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006086
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006087 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006088 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006089 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006090 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006091 * can have the following legal literals {true, false, 1, 0}.
6092 */
6093 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6094 res = 1;
6095 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6096 res = 0;
6097 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6098 res = 1;
6099 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006100 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006101 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006102 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006103 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006104 ownerItem, node,
6105 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6106 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006107 NULL, NULL, NULL);
6108 }
6109 if (value != NULL)
6110 xmlFree(value);
6111 return (res);
6112}
6113
6114/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006115 * xmlGetBooleanProp:
6116 * @ctxt: a schema validation context
6117 * @node: a subtree containing XML Schema informations
6118 * @name: the attribute name
6119 * @def: the default value
6120 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006121 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006122 *
6123 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006124 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006125 */
6126static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006127xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006128 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006129 const char *name, int def)
6130{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006131 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006132
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006133 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006134 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006135 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006136 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006137 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006138 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006139 * can have the following legal literals {true, false, 1, 0}.
6140 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006141 if (xmlStrEqual(val, BAD_CAST "true"))
6142 def = 1;
6143 else if (xmlStrEqual(val, BAD_CAST "false"))
6144 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006145 else if (xmlStrEqual(val, BAD_CAST "1"))
6146 def = 1;
6147 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006148 def = 0;
6149 else {
6150 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006151 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006152 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006153 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006154 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6155 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006157 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006158}
6159
6160/************************************************************************
6161 * *
6162 * Shema extraction from an Infoset *
6163 * *
6164 ************************************************************************/
6165static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6166 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006167 xmlNodePtr node,
6168 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006169static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6170 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006172 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006173 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006174static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6175 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006176 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006177 xmlNodePtr node,
6178 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006179static xmlSchemaBasicItemPtr
6180xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6181 xmlSchemaPtr schema,
6182 xmlNodePtr node,
6183 xmlSchemaItemListPtr uses,
6184 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6186 xmlSchemaPtr schema,
6187 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006188static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6190 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006191
6192/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006193 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006194 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006195 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006196 * @ownerDes: the designation of the parent element
6197 * @ownerItem: the schema object owner if existent
6198 * @attr: the schema attribute node being validated
6199 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006200 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006201 *
6202 * Validates a value against the given built-in type.
6203 * This one is intended to be used internally for validation
6204 * of schema attribute values during parsing of the schema.
6205 *
6206 * Returns 0 if the value is valid, a positive error code
6207 * number otherwise and -1 in case of an internal or API error.
6208 */
6209static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006210xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006211 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006212 xmlAttrPtr attr,
6213 const xmlChar *value,
6214 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006215{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006216
6217 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006218
6219 /*
6220 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6221 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 */
6223 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006224 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006225 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6226 PERROR_INT("xmlSchemaPValAttrNodeValue",
6227 "the given type is not a built-in type");
6228 return (-1);
6229 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006230 switch (type->builtInType) {
6231 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006232 case XML_SCHEMAS_QNAME:
6233 case XML_SCHEMAS_ANYURI:
6234 case XML_SCHEMAS_TOKEN:
6235 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006236 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6237 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006238 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006239 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006240 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006241 "validation using the given type is not supported while "
6242 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006243 return (-1);
6244 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006245 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006246 /*
6247 * TODO: Should we use the S4S error codes instead?
6248 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006249 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006250 PERROR_INT("xmlSchemaPValAttrNodeValue",
6251 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006252 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006253 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006254 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006255 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6256 else
6257 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6258 xmlSchemaPSimpleTypeErr(pctxt,
6259 ret, ownerItem, (xmlNodePtr) attr,
6260 type, NULL, value, NULL, NULL, NULL);
6261 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006262 return (ret);
6263}
6264
6265/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006267 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006268 * @ctxt: a schema parser context
6269 * @ownerDes: the designation of the parent element
6270 * @ownerItem: the schema object owner if existent
6271 * @attr: the schema attribute node being validated
6272 * @type: the built-in type to be validated against
6273 * @value: the resulting value if any
6274 *
6275 * Extracts and validates a value against the given built-in type.
6276 * This one is intended to be used internally for validation
6277 * of schema attribute values during parsing of the schema.
6278 *
6279 * Returns 0 if the value is valid, a positive error code
6280 * number otherwise and -1 in case of an internal or API error.
6281 */
6282static int
6283xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006284 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006285 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006286 xmlSchemaTypePtr type,
6287 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006288{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 const xmlChar *val;
6290
6291 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006292 return (-1);
6293
Daniel Veillardc0826a72004-08-10 14:17:33 +00006294 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6295 if (value != NULL)
6296 *value = val;
6297
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006298 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006299 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300}
6301
6302/**
6303 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 * @ctxt: a schema parser context
6306 * @node: the element node of the attribute
6307 * @ownerDes: the designation of the parent element
6308 * @ownerItem: the schema object owner if existent
6309 * @ownerElem: the owner element node
6310 * @name: the name of the schema attribute node
6311 * @type: the built-in type to be validated against
6312 * @value: the resulting value if any
6313 *
6314 * Extracts and validates a value against the given built-in type.
6315 * This one is intended to be used internally for validation
6316 * of schema attribute values during parsing of the schema.
6317 *
6318 * Returns 0 if the value is valid, a positive error code
6319 * number otherwise and -1 in case of an internal or API error.
6320 */
6321static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006322xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6323 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006324 xmlNodePtr ownerElem,
6325 const char *name,
6326 xmlSchemaTypePtr type,
6327 const xmlChar **value)
6328{
6329 xmlAttrPtr attr;
6330
6331 if ((ctxt == NULL) || (type == NULL)) {
6332 if (value != NULL)
6333 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006335 }
6336 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6337 if (value != NULL)
6338 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006339 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006340 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006341 "Internal error: xmlSchemaPValAttr, the given "
6342 "type '%s' is not a built-in type.\n",
6343 type->name, NULL);
6344 return (-1);
6345 }
6346 attr = xmlSchemaGetPropNode(ownerElem, name);
6347 if (attr == NULL) {
6348 if (value != NULL)
6349 *value = NULL;
6350 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006351 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006352 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006353 type, value));
6354}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006355
6356static int
6357xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006358 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006359 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006360 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006361 const xmlChar *namespaceName)
6362{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006363 /* TODO: Pointer comparison instead? */
6364 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006365 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006367 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006368 /*
6369 * Check if the referenced namespace was <import>ed.
6370 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006371 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006372 xmlSchemaSchemaRelationPtr rel;
6373
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006374 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006375 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006376 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006377 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006378 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006379 rel = rel->next;
6380 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006381 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006382 /*
6383 * No matching <import>ed namespace found.
6384 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006385 {
6386 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6387
6388 if (namespaceName == NULL)
6389 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6390 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6391 "References from this schema to components in no "
6392 "namespace are not allowed, since not indicated by an "
6393 "import statement", NULL, NULL);
6394 else
6395 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6396 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6397 "References from this schema to components in the "
6398 "namespace '%s' are not allowed, since not indicated by an "
6399 "import statement", namespaceName, NULL);
6400 }
6401 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006402}
6403
Daniel Veillardc0826a72004-08-10 14:17:33 +00006404/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006405 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006406 * @ctxt: a schema validation context
6407 * @schema: the schema being built
6408 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006409 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006410 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006411 * Parses attribute uses and attribute declarations and
6412 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006413 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006414static int
6415xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6416 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6417 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006418{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006419 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006420
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006421 while ((IS_SCHEMA((*child), "attribute")) ||
6422 (IS_SCHEMA((*child), "attributeGroup"))) {
6423 if (IS_SCHEMA((*child), "attribute")) {
6424 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6425 *list, parentType);
6426 } else {
6427 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6428 if ((item != NULL) && (hasRefs != NULL))
6429 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006430 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006431 if (item != NULL) {
6432 if (*list == NULL) {
6433 /* TODO: Customize grow factor. */
6434 *list = xmlSchemaItemListCreate();
6435 if (*list == NULL)
6436 return(-1);
6437 }
6438 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6439 return(-1);
6440 }
6441 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006442 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006443 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006444}
6445
6446/**
6447 * xmlSchemaParseAnnotation:
6448 * @ctxt: a schema validation context
6449 * @schema: the schema being built
6450 * @node: a subtree containing XML Schema informations
6451 *
6452 * parse a XML schema Attrribute declaration
6453 * *WARNING* this interface is highly subject to change
6454 *
William M. Bracke7091952004-05-11 15:09:58 +00006455 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006456 * 1 in case of success.
6457 */
6458static xmlSchemaAnnotPtr
6459xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006460 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006461{
6462 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006463 xmlNodePtr child = NULL;
6464 xmlAttrPtr attr;
6465 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006466
Daniel Veillardc0826a72004-08-10 14:17:33 +00006467 /*
6468 * INFO: S4S completed.
6469 */
6470 /*
6471 * id = ID
6472 * {any attributes with non-schema namespace . . .}>
6473 * Content: (appinfo | documentation)*
6474 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006475 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6476 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006477 if (needed)
6478 ret = xmlSchemaNewAnnot(ctxt, node);
6479 else
6480 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 attr = node->properties;
6482 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006483 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006484 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006487
6488 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006489 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 }
6491 attr = attr->next;
6492 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006493 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006494 /*
6495 * And now for the children...
6496 */
6497 child = node->children;
6498 while (child != NULL) {
6499 if (IS_SCHEMA(child, "appinfo")) {
6500 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006502 * source = anyURI
6503 * {any attributes with non-schema namespace . . .}>
6504 * Content: ({any})*
6505 */
6506 attr = child->properties;
6507 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006508 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006509 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006512
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006513 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006514 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 }
6516 attr = attr->next;
6517 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006518 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006519 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 child = child->next;
6521 } else if (IS_SCHEMA(child, "documentation")) {
6522 /* TODO: make available the content of "documentation". */
6523 /*
6524 * source = anyURI
6525 * {any attributes with non-schema namespace . . .}>
6526 * Content: ({any})*
6527 */
6528 attr = child->properties;
6529 while (attr != NULL) {
6530 if (attr->ns == NULL) {
6531 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006532 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006533 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 }
6535 } else {
6536 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6537 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6538 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539
6540 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006541 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006542 }
6543 }
6544 attr = attr->next;
6545 }
6546 /*
6547 * Attribute "xml:lang".
6548 */
6549 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6550 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006551 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006552 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006553 child = child->next;
6554 } else {
6555 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 xmlSchemaPContentErr(ctxt,
6557 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006558 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 barked = 1;
6560 child = child->next;
6561 }
6562 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006563
Daniel Veillard4255d502002-04-16 15:50:10 +00006564 return (ret);
6565}
6566
6567/**
6568 * xmlSchemaParseFacet:
6569 * @ctxt: a schema validation context
6570 * @schema: the schema being built
6571 * @node: a subtree containing XML Schema informations
6572 *
6573 * parse a XML schema Facet declaration
6574 * *WARNING* this interface is highly subject to change
6575 *
6576 * Returns the new type structure or NULL in case of error
6577 */
6578static xmlSchemaFacetPtr
6579xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006580 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006581{
6582 xmlSchemaFacetPtr facet;
6583 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006584 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006585
6586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6587 return (NULL);
6588
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006589 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006590 if (facet == NULL) {
6591 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6592 return (NULL);
6593 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006594 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006595 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006597 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6598 "Facet %s has no value\n", node->name, NULL);
6599 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 return (NULL);
6601 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006602 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006603 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006604 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006605 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006606 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006608 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006610 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006611 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006612 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006613 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006614 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006615 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006616 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006618 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006619 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006620 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006621 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006623 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6624 } else if (IS_SCHEMA(node, "minLength")) {
6625 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6626 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006627 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6628 "Unknown facet type %s\n", node->name, NULL);
6629 xmlSchemaFreeFacet(facet);
6630 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006631 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006632 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006633 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006634 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6635 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6636 const xmlChar *fixed;
6637
6638 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6639 if (fixed != NULL) {
6640 if (xmlStrEqual(fixed, BAD_CAST "true"))
6641 facet->fixed = 1;
6642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006643 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006644 child = node->children;
6645
6646 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006647 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006648 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 }
6650 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006651 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6652 "Facet %s has unexpected child content\n",
6653 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006654 }
6655 return (facet);
6656}
6657
6658/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006659 * xmlSchemaParseWildcardNs:
6660 * @ctxt: a schema parser context
6661 * @wildc: the wildcard, already created
6662 * @node: a subtree containing XML Schema informations
6663 *
6664 * Parses the attribute "processContents" and "namespace"
6665 * of a xsd:anyAttribute and xsd:any.
6666 * *WARNING* this interface is highly subject to change
6667 *
6668 * Returns 0 if everything goes fine, a positive error code
6669 * if something is not valid and -1 if an internal error occurs.
6670 */
6671static int
6672xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006673 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006674 xmlSchemaWildcardPtr wildc,
6675 xmlNodePtr node)
6676{
6677 const xmlChar *pc, *ns, *dictnsItem;
6678 int ret = 0;
6679 xmlChar *nsItem;
6680 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6681 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006682
Daniel Veillardc0826a72004-08-10 14:17:33 +00006683 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6684 if ((pc == NULL)
6685 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6686 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6687 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6688 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6689 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6690 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6691 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006692 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006693 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006694 NULL, node,
6695 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006696 NULL, NULL, NULL);
6697 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006698 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006699 }
6700 /*
6701 * Build the namespace constraints.
6702 */
6703 attr = xmlSchemaGetPropNode(node, "namespace");
6704 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006705 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006706 wildc->any = 1;
6707 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6708 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006710 return (-1);
6711 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006712 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006713 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006714 const xmlChar *end, *cur;
6715
6716 cur = ns;
6717 do {
6718 while (IS_BLANK_CH(*cur))
6719 cur++;
6720 end = cur;
6721 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6722 end++;
6723 if (end == cur)
6724 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006725 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006726 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6727 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006728 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006730 NULL, (xmlNodePtr) attr,
6731 NULL,
6732 "((##any | ##other) | List of (xs:anyURI | "
6733 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006734 nsItem, NULL, NULL, NULL);
6735 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6736 } else {
6737 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006738 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006739 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6740 dictnsItem = NULL;
6741 } else {
6742 /*
6743 * Validate the item (anyURI).
6744 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006745 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006746 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6747 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6748 }
6749 /*
6750 * Avoid dublicate namespaces.
6751 */
6752 tmp = wildc->nsSet;
6753 while (tmp != NULL) {
6754 if (dictnsItem == tmp->value)
6755 break;
6756 tmp = tmp->next;
6757 }
6758 if (tmp == NULL) {
6759 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6760 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006761 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006762 return (-1);
6763 }
6764 tmp->value = dictnsItem;
6765 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006767 wildc->nsSet = tmp;
6768 else
6769 lastNs->next = tmp;
6770 lastNs = tmp;
6771 }
6772
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006773 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774 xmlFree(nsItem);
6775 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006776 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006777 }
6778 return (ret);
6779}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006780
6781static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006782xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6783 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006784 xmlNodePtr node,
6785 int minOccurs,
6786 int maxOccurs) {
6787
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006788 if ((maxOccurs == 0) && ( minOccurs == 0))
6789 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006790 if (maxOccurs != UNBOUNDED) {
6791 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 * TODO: Maybe we should better not create the particle,
6793 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006794 * content model.
6795 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006797 * 3.9.6 Schema Component Constraint: Particle Correct
6798 *
6799 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006800 if (maxOccurs < 1) {
6801 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006802 * 2.2 {max occurs} must be greater than or equal to 1.
6803 */
6804 xmlSchemaPCustomAttrErr(ctxt,
6805 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006806 NULL, NULL,
6807 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006808 "The value must be greater than or equal to 1");
6809 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6810 } else if (minOccurs > maxOccurs) {
6811 /*
6812 * 2.1 {min occurs} must not be greater than {max occurs}.
6813 */
6814 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006815 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006816 NULL, NULL,
6817 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006818 "The value must not be greater than the value of 'maxOccurs'");
6819 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6820 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006821 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006822 return (0);
6823}
6824
Daniel Veillardc0826a72004-08-10 14:17:33 +00006825/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006826 * xmlSchemaParseAny:
6827 * @ctxt: a schema validation context
6828 * @schema: the schema being built
6829 * @node: a subtree containing XML Schema informations
6830 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006831 * Parsea a XML schema <any> element. A particle and wildcard
6832 * will be created (except if minOccurs==maxOccurs==0, in this case
6833 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006834 * *WARNING* this interface is highly subject to change
6835 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006836 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006837 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006838static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006839xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6840 xmlNodePtr node)
6841{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006842 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006843 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006844 xmlSchemaWildcardPtr wild;
6845 int min, max;
6846 xmlAttrPtr attr;
6847 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006848
6849 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6850 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006851 /*
6852 * Check for illegal attributes.
6853 */
6854 attr = node->properties;
6855 while (attr != NULL) {
6856 if (attr->ns == NULL) {
6857 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6858 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6859 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6860 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6861 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006862 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006863 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006864 }
6865 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006867 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006868 }
6869 attr = attr->next;
6870 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006871 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006872 /*
6873 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006874 */
6875 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6876 "(xs:nonNegativeInteger | unbounded)");
6877 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6878 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006879 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6880 /*
6881 * Create & parse the wildcard.
6882 */
6883 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6884 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006885 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006886 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006887 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006888 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006889 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006890 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006892 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006893 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006894 }
6895 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006896 xmlSchemaPContentErr(ctxt,
6897 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006898 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006899 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006900 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006901 /*
6902 * No component if minOccurs==maxOccurs==0.
6903 */
6904 if ((min == 0) && (max == 0)) {
6905 /* Don't free the wildcard, since it's already on the list. */
6906 return (NULL);
6907 }
6908 /*
6909 * Create the particle.
6910 */
6911 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6912 if (particle == NULL)
6913 return (NULL);
6914 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006915 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006916
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006917 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006918}
6919
6920/**
6921 * xmlSchemaParseNotation:
6922 * @ctxt: a schema validation context
6923 * @schema: the schema being built
6924 * @node: a subtree containing XML Schema informations
6925 *
6926 * parse a XML schema Notation declaration
6927 *
6928 * Returns the new structure or NULL in case of error
6929 */
6930static xmlSchemaNotationPtr
6931xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006932 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006933{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006934 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006935 xmlSchemaNotationPtr ret;
6936 xmlNodePtr child = NULL;
6937
6938 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6939 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006940 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006941 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006942 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6943 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006944 return (NULL);
6945 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006946 ret = xmlSchemaAddNotation(ctxt, schema, name,
6947 ctxt->targetNamespace, node);
6948 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006950 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006951
6952 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006953 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006954 child = child->next;
6955 }
6956
Daniel Veillard4255d502002-04-16 15:50:10 +00006957 child = node->children;
6958 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006959 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006960 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006961 }
6962 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006963 xmlSchemaPContentErr(ctxt,
6964 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006965 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006966 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 }
6968
6969 return (ret);
6970}
6971
6972/**
6973 * xmlSchemaParseAnyAttribute:
6974 * @ctxt: a schema validation context
6975 * @schema: the schema being built
6976 * @node: a subtree containing XML Schema informations
6977 *
6978 * parse a XML schema AnyAttrribute declaration
6979 * *WARNING* this interface is highly subject to change
6980 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006981 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006982 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006983static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006984xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6985 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006986{
Daniel Veillard3646d642004-06-02 19:19:14 +00006987 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006988 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006989 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990
6991 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6992 return (NULL);
6993
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006994 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6995 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006996 if (ret == NULL) {
6997 return (NULL);
6998 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006999 /*
7000 * Check for illegal attributes.
7001 */
7002 attr = node->properties;
7003 while (attr != NULL) {
7004 if (attr->ns == NULL) {
7005 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7006 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7007 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007008 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007010 }
7011 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007012 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007013 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007014 }
7015 attr = attr->next;
7016 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007017 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007018 /*
7019 * Parse the namespace list.
7020 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007021 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007022 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007023 /*
7024 * And now for the children...
7025 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007026 child = node->children;
7027 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007028 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007030 }
7031 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007032 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007033 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007034 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007035 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 }
7037
7038 return (ret);
7039}
7040
7041
7042/**
7043 * xmlSchemaParseAttribute:
7044 * @ctxt: a schema validation context
7045 * @schema: the schema being built
7046 * @node: a subtree containing XML Schema informations
7047 *
7048 * parse a XML schema Attrribute declaration
7049 * *WARNING* this interface is highly subject to change
7050 *
William M. Bracke7091952004-05-11 15:09:58 +00007051 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007052 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007053static xmlSchemaBasicItemPtr
7054xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7055 xmlSchemaPtr schema,
7056 xmlNodePtr node,
7057 xmlSchemaItemListPtr uses,
7058 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007059{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007060 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7061 xmlSchemaAttributeUsePtr use = NULL;
7062 xmlNodePtr child = NULL;
7063 xmlAttrPtr attr;
7064 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7065 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7066 int nberrors, hasForm = 0, defValueType = 0;
7067
7068#define WXS_ATTR_DEF_VAL_DEFAULT 1
7069#define WXS_ATTR_DEF_VAL_FIXED 2
7070
7071 /*
7072 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7073 */
7074
7075 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7076 return (NULL);
7077 attr = xmlSchemaGetPropNode(node, "ref");
7078 if (attr != NULL) {
7079 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7080 NULL, attr, &tmpNs, &tmpName) != 0) {
7081 return (NULL);
7082 }
7083 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7084 return(NULL);
7085 isRef = 1;
7086 }
7087 nberrors = pctxt->nberrors;
7088 /*
7089 * Check for illegal attributes.
7090 */
7091 attr = node->properties;
7092 while (attr != NULL) {
7093 if (attr->ns == NULL) {
7094 if (isRef) {
7095 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7096 xmlSchemaPValAttrNodeID(pctxt, attr);
7097 goto attr_next;
7098 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7099 goto attr_next;
7100 }
7101 } else {
7102 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7103 goto attr_next;
7104 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7105 xmlSchemaPValAttrNodeID(pctxt, attr);
7106 goto attr_next;
7107 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7108 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7109 attr, &tmpNs, &tmpName);
7110 goto attr_next;
7111 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7112 /*
7113 * Evaluate the target namespace
7114 */
7115 hasForm = 1;
7116 attrValue = xmlSchemaGetNodeContent(pctxt,
7117 (xmlNodePtr) attr);
7118 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7119 ns = pctxt->targetNamespace;
7120 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7121 {
7122 xmlSchemaPSimpleTypeErr(pctxt,
7123 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7124 NULL, (xmlNodePtr) attr,
7125 NULL, "(qualified | unqualified)",
7126 attrValue, NULL, NULL, NULL);
7127 }
7128 goto attr_next;
7129 }
7130 }
7131 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7132
7133 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7134 /* TODO: Maybe we need to normalize the value beforehand. */
7135 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7136 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7137 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7138 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7139 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7140 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7141 else {
7142 xmlSchemaPSimpleTypeErr(pctxt,
7143 XML_SCHEMAP_INVALID_ATTR_USE,
7144 NULL, (xmlNodePtr) attr,
7145 NULL, "(optional | prohibited | required)",
7146 attrValue, NULL, NULL, NULL);
7147 }
7148 goto attr_next;
7149 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7150 /*
7151 * 3.2.3 : 1
7152 * default and fixed must not both be present.
7153 */
7154 if (defValue) {
7155 xmlSchemaPMutualExclAttrErr(pctxt,
7156 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7157 NULL, attr, "default", "fixed");
7158 } else {
7159 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7160 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7161 }
7162 goto attr_next;
7163 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7164 /*
7165 * 3.2.3 : 1
7166 * default and fixed must not both be present.
7167 */
7168 if (defValue) {
7169 xmlSchemaPMutualExclAttrErr(pctxt,
7170 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7171 NULL, attr, "default", "fixed");
7172 } else {
7173 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7174 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7175 }
7176 goto attr_next;
7177 }
7178 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7179 goto attr_next;
7180
7181 xmlSchemaPIllegalAttrErr(pctxt,
7182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7183
7184attr_next:
7185 attr = attr->next;
7186 }
7187 /*
7188 * 3.2.3 : 2
7189 * If default and use are both present, use must have
7190 * the actual value optional.
7191 */
7192 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7193 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7194 xmlSchemaPSimpleTypeErr(pctxt,
7195 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7196 NULL, node, NULL,
7197 "(optional | prohibited | required)", NULL,
7198 "The value of the attribute 'use' must be 'optional' "
7199 "if the attribute 'default' is present",
7200 NULL, NULL);
7201 }
7202 /*
7203 * We want correct attributes.
7204 */
7205 if (nberrors != pctxt->nberrors)
7206 return(NULL);
7207 if (! isRef) {
7208 xmlSchemaAttributePtr attrDecl;
7209
7210 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7211 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7212 ns = pctxt->targetNamespace;
7213 /*
7214 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7215 * TODO: Move this to the component layer.
7216 */
7217 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7218 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7219 XML_SCHEMAP_NO_XSI,
7220 node, NULL,
7221 "The target namespace must not match '%s'",
7222 xmlSchemaInstanceNs, NULL);
7223 }
7224 attr = xmlSchemaGetPropNode(node, "name");
7225 if (attr == NULL) {
7226 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7227 NULL, node, "name", NULL);
7228 return (NULL);
7229 }
7230 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7231 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7232 return (NULL);
7233 }
7234 /*
7235 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7236 * TODO: Move this to the component layer.
7237 */
7238 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7239 xmlSchemaPSimpleTypeErr(pctxt,
7240 XML_SCHEMAP_NO_XMLNS,
7241 NULL, (xmlNodePtr) attr,
7242 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7243 "The value of the attribute must not match 'xmlns'",
7244 NULL, NULL);
7245 return (NULL);
7246 }
7247 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7248 goto check_children;
7249 /*
7250 * Create the attribute use component.
7251 */
7252 use = xmlSchemaAddAttributeUse(pctxt, node);
7253 if (use == NULL)
7254 return(NULL);
7255 use->occurs = occurs;
7256 /*
7257 * Create the attribute declaration.
7258 */
7259 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7260 if (attrDecl == NULL)
7261 return (NULL);
7262 if (tmpName != NULL) {
7263 attrDecl->typeName = tmpName;
7264 attrDecl->typeNs = tmpNs;
7265 }
7266 use->attrDecl = attrDecl;
7267 /*
7268 * Value constraint.
7269 */
7270 if (defValue != NULL) {
7271 attrDecl->defValue = defValue;
7272 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7273 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7274 }
7275 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7276 xmlSchemaQNameRefPtr ref;
7277
7278 /*
7279 * Create the attribute use component.
7280 */
7281 use = xmlSchemaAddAttributeUse(pctxt, node);
7282 if (use == NULL)
7283 return(NULL);
7284 /*
7285 * We need to resolve the reference at later stage.
7286 */
7287 WXS_ADD_PENDING(pctxt, use);
7288 use->occurs = occurs;
7289 /*
7290 * Create a QName reference to the attribute declaration.
7291 */
7292 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7293 tmpName, tmpNs);
7294 if (ref == NULL)
7295 return(NULL);
7296 /*
7297 * Assign the reference. This will be substituted for the
7298 * referenced attribute declaration when the QName is resolved.
7299 */
7300 use->attrDecl = WXS_ATTR_CAST ref;
7301 /*
7302 * Value constraint.
7303 */
7304 if (defValue != NULL)
7305 use->defValue = defValue;
7306 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7307 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7308 }
7309
7310check_children:
7311 /*
7312 * And now for the children...
7313 */
7314 child = node->children;
7315 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7316 xmlSchemaAttributeUseProhibPtr prohib;
7317
7318 if (IS_SCHEMA(child, "annotation")) {
7319 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7320 child = child->next;
7321 }
7322 if (child != NULL) {
7323 xmlSchemaPContentErr(pctxt,
7324 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7325 NULL, node, child, NULL,
7326 "(annotation?)");
7327 }
7328 /*
7329 * Check for pointlessness of attribute prohibitions.
7330 */
7331 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7332 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7333 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7334 node, NULL,
7335 "Skipping attribute use prohibition, since it is "
7336 "pointless inside an <attributeGroup>",
7337 NULL, NULL, NULL);
7338 return(NULL);
7339 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7340 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7341 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7342 node, NULL,
7343 "Skipping attribute use prohibition, since it is "
7344 "pointless when extending a type",
7345 NULL, NULL, NULL);
7346 return(NULL);
7347 }
7348 if (! isRef) {
7349 tmpName = name;
7350 tmpNs = ns;
7351 }
7352 /*
7353 * Check for duplicate attribute prohibitions.
7354 */
7355 if (uses) {
7356 int i;
7357
7358 for (i = 0; i < uses->nbItems; i++) {
7359 use = uses->items[i];
7360 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7361 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7362 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7363 {
7364 xmlChar *str = NULL;
7365
7366 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7367 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7368 node, NULL,
7369 "Skipping duplicate attribute use prohibition '%s'",
7370 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7371 NULL, NULL);
7372 FREE_AND_NULL(str)
7373 return(NULL);
7374 }
7375 }
7376 }
7377 /*
7378 * Create the attribute prohibition helper component.
7379 */
7380 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7381 if (prohib == NULL)
7382 return(NULL);
7383 prohib->node = node;
7384 prohib->name = tmpName;
7385 prohib->targetNamespace = tmpNs;
7386 if (isRef) {
7387 /*
7388 * We need at least to resolve to the attribute declaration.
7389 */
7390 WXS_ADD_PENDING(pctxt, prohib);
7391 }
7392 return(WXS_BASIC_CAST prohib);
7393 } else {
7394 if (IS_SCHEMA(child, "annotation")) {
7395 /*
7396 * TODO: Should this go into the attr decl?
7397 */
7398 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7399 child = child->next;
7400 }
7401 if (isRef) {
7402 if (child != NULL) {
7403 if (IS_SCHEMA(child, "simpleType"))
7404 /*
7405 * 3.2.3 : 3.2
7406 * If ref is present, then all of <simpleType>,
7407 * form and type must be absent.
7408 */
7409 xmlSchemaPContentErr(pctxt,
7410 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7411 NULL, node, child, NULL,
7412 "(annotation?)");
7413 else
7414 xmlSchemaPContentErr(pctxt,
7415 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7416 NULL, node, child, NULL,
7417 "(annotation?)");
7418 }
7419 } else {
7420 if (IS_SCHEMA(child, "simpleType")) {
7421 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7422 /*
7423 * 3.2.3 : 4
7424 * type and <simpleType> must not both be present.
7425 */
7426 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7427 NULL, node, child,
7428 "The attribute 'type' and the <simpleType> child "
7429 "are mutually exclusive", NULL);
7430 } else
7431 WXS_ATTRUSE_TYPEDEF(use) =
7432 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7433 child = child->next;
7434 }
7435 if (child != NULL)
7436 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7437 NULL, node, child, NULL,
7438 "(annotation?, simpleType?)");
7439 }
7440 }
7441 return (WXS_BASIC_CAST use);
7442}
7443
7444
7445static xmlSchemaAttributePtr
7446xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7447 xmlSchemaPtr schema,
7448 xmlNodePtr node)
7449{
7450 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007451 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007452 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007453 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007454
7455 /*
7456 * Note that the w3c spec assumes the schema to be validated with schema
7457 * for schemas beforehand.
7458 *
7459 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007460 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007461 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7462 return (NULL);
7463 /*
7464 * 3.2.3 : 3.1
7465 * One of ref or name must be present, but not both
7466 */
7467 attr = xmlSchemaGetPropNode(node, "name");
7468 if (attr == NULL) {
7469 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7470 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 return (NULL);
7472 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007473 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7474 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7475 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007476 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007477 /*
7478 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7479 * TODO: Move this to the component layer.
7480 */
7481 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7482 xmlSchemaPSimpleTypeErr(pctxt,
7483 XML_SCHEMAP_NO_XMLNS,
7484 NULL, (xmlNodePtr) attr,
7485 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7486 "The value of the attribute must not match 'xmlns'",
7487 NULL, NULL);
7488 return (NULL);
7489 }
7490 /*
7491 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7492 * TODO: Move this to the component layer.
7493 * Or better leave it here and add it to the component layer
7494 * if we have a schema construction API.
7495 */
7496 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7497 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7498 XML_SCHEMAP_NO_XSI, node, NULL,
7499 "The target namespace must not match '%s'",
7500 xmlSchemaInstanceNs, NULL);
7501 }
7502
7503 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7504 pctxt->targetNamespace, node, 1);
7505 if (ret == NULL)
7506 return (NULL);
7507 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7508
7509 /*
7510 * Check for illegal attributes.
7511 */
7512 attr = node->properties;
7513 while (attr != NULL) {
7514 if (attr->ns == NULL) {
7515 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7516 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7517 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7518 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7519 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7520 {
7521 xmlSchemaPIllegalAttrErr(pctxt,
7522 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7523 }
7524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7525 xmlSchemaPIllegalAttrErr(pctxt,
7526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7527 }
7528 attr = attr->next;
7529 }
7530 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7531 node, "type", &ret->typeNs, &ret->typeName);
7532
7533 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007534 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007536 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007537 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007538 if (ret->defValue != NULL)
7539 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 * Attribute "default".
7542 */
7543 attr = xmlSchemaGetPropNode(node, "default");
7544 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007545 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007548 */
7549 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007550 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7551 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007552 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007553 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007554 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 /*
7556 * And now for the children...
7557 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 child = node->children;
7559 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007560 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007561 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007562 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007563 if (IS_SCHEMA(child, "simpleType")) {
7564 if (ret->typeName != NULL) {
7565 /*
7566 * 3.2.3 : 4
7567 * type and <simpleType> must not both be present.
7568 */
7569 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7570 NULL, node, child,
7571 "The attribute 'type' and the <simpleType> child "
7572 "are mutually exclusive", NULL);
7573 } else
7574 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7575 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007576 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007577 if (child != NULL)
7578 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7579 NULL, node, child, NULL,
7580 "(annotation?, simpleType?)");
7581
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 return (ret);
7583}
7584
7585/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007586 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007587 * @ctxt: a schema validation context
7588 * @schema: the schema being built
7589 * @node: a subtree containing XML Schema informations
7590 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007591 * Parse an attribute group definition reference.
7592 * Note that a reference to an attribute group does not
7593 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007594 * *WARNING* this interface is highly subject to change
7595 *
7596 * Returns the attribute group or NULL in case of error.
7597 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007598static xmlSchemaQNameRefPtr
7599xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7600 xmlSchemaPtr schema,
7601 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007602{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007603 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007605 xmlAttrPtr attr;
7606 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007607
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007608 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007609 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007610
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007612 if (attr == NULL) {
7613 xmlSchemaPMissingAttrErr(pctxt,
7614 XML_SCHEMAP_S4S_ATTR_MISSING,
7615 NULL, node, "ref", NULL);
7616 return (NULL);
7617 }
7618 xmlSchemaPValAttrNodeQName(pctxt, schema,
7619 NULL, attr, &refNs, &ref);
7620 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7621 return(NULL);
7622
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007623 /*
7624 * Check for illegal attributes.
7625 */
7626 attr = node->properties;
7627 while (attr != NULL) {
7628 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007629 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007630 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007631 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007632 xmlSchemaPIllegalAttrErr(pctxt,
7633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007634 }
7635 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007636 xmlSchemaPIllegalAttrErr(pctxt,
7637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007638 }
7639 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007640 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007641 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007642 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7643
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007644 /*
7645 * And now for the children...
7646 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007647 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007648 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007649 /*
7650 * TODO: We do not have a place to store the annotation, do we?
7651 */
7652 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007653 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007654 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007655 if (child != NULL) {
7656 xmlSchemaPContentErr(pctxt,
7657 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7658 NULL, node, child, NULL,
7659 "(annotation?)");
7660 }
7661
7662 /*
7663 * Handle attribute group redefinitions.
7664 */
7665 if (pctxt->isRedefine && pctxt->redef &&
7666 (pctxt->redef->item->type ==
7667 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7668 (ref == pctxt->redef->refName) &&
7669 (refNs == pctxt->redef->refTargetNs))
7670 {
7671 /*
7672 * SPEC src-redefine:
7673 * (7.1) "If it has an <attributeGroup> among its contents
7674 * the ·actual value· of whose ref [attribute] is the same
7675 * as the ·actual value· of its own name attribute plus
7676 * target namespace, then it must have exactly one such group."
7677 */
7678 if (pctxt->redefCounter != 0) {
7679 xmlChar *str = NULL;
7680
7681 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7682 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7683 "The redefining attribute group definition "
7684 "'%s' must not contain more than one "
7685 "reference to the redefined definition",
7686 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7687 FREE_AND_NULL(str);
7688 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007689 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007690 pctxt->redefCounter++;
7691 /*
7692 * URGENT TODO: How to ensure that the reference will not be
7693 * handled by the normal component resolution mechanism?
7694 */
7695 ret = xmlSchemaNewQNameRef(pctxt,
7696 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7697 if (ret == NULL)
7698 return(NULL);
7699 ret->node = node;
7700 pctxt->redef->reference = WXS_BASIC_CAST ret;
7701 } else {
7702 /*
7703 * Create a QName-reference helper component. We will substitute this
7704 * component for the attribute uses of the referenced attribute group
7705 * definition.
7706 */
7707 ret = xmlSchemaNewQNameRef(pctxt,
7708 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7709 if (ret == NULL)
7710 return(NULL);
7711 ret->node = node;
7712 /* Add to pending items, to be able to resolve the reference. */
7713 WXS_ADD_PENDING(pctxt, ret);
7714 }
7715 return (ret);
7716}
7717
7718/**
7719 * xmlSchemaParseAttributeGroupDefinition:
7720 * @pctxt: a schema validation context
7721 * @schema: the schema being built
7722 * @node: a subtree containing XML Schema informations
7723 *
7724 * parse a XML schema Attribute Group declaration
7725 * *WARNING* this interface is highly subject to change
7726 *
7727 * Returns the attribute group definition or NULL in case of error.
7728 */
7729static xmlSchemaAttributeGroupPtr
7730xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7731 xmlSchemaPtr schema,
7732 xmlNodePtr node)
7733{
7734 const xmlChar *name;
7735 xmlSchemaAttributeGroupPtr ret;
7736 xmlNodePtr child = NULL;
7737 xmlAttrPtr attr;
7738 int hasRefs = 0;
7739
7740 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7741 return (NULL);
7742
7743 attr = xmlSchemaGetPropNode(node, "name");
7744 if (attr == NULL) {
7745 xmlSchemaPMissingAttrErr(pctxt,
7746 XML_SCHEMAP_S4S_ATTR_MISSING,
7747 NULL, node, "name", NULL);
7748 return (NULL);
7749 }
7750 /*
7751 * The name is crucial, exit if invalid.
7752 */
7753 if (xmlSchemaPValAttrNode(pctxt,
7754 NULL, attr,
7755 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7756 return (NULL);
7757 }
7758 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7759 name, pctxt->targetNamespace, node);
7760 if (ret == NULL)
7761 return (NULL);
7762 /*
7763 * Check for illegal attributes.
7764 */
7765 attr = node->properties;
7766 while (attr != NULL) {
7767 if (attr->ns == NULL) {
7768 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7769 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7770 {
7771 xmlSchemaPIllegalAttrErr(pctxt,
7772 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7773 }
7774 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7775 xmlSchemaPIllegalAttrErr(pctxt,
7776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7777 }
7778 attr = attr->next;
7779 }
7780 /* Attribute ID */
7781 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7782 /*
7783 * And now for the children...
7784 */
7785 child = node->children;
7786 if (IS_SCHEMA(child, "annotation")) {
7787 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7788 child = child->next;
7789 }
7790 /*
7791 * Parse contained attribute decls/refs.
7792 */
7793 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7794 (xmlSchemaItemListPtr *) &(ret->attrUses),
7795 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7796 return(NULL);
7797 if (hasRefs)
7798 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7799 /*
7800 * Parse the attribute wildcard.
7801 */
7802 if (IS_SCHEMA(child, "anyAttribute")) {
7803 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7804 schema, child);
7805 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007806 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007807 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007808 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007809 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007810 NULL, node, child, NULL,
7811 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007812 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007813 return (ret);
7814}
7815
7816/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007817 * xmlSchemaPValAttrFormDefault:
7818 * @value: the value
7819 * @flags: the flags to be modified
7820 * @flagQualified: the specific flag for "qualified"
7821 *
7822 * Returns 0 if the value is valid, 1 otherwise.
7823 */
7824static int
7825xmlSchemaPValAttrFormDefault(const xmlChar *value,
7826 int *flags,
7827 int flagQualified)
7828{
7829 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7830 if ((*flags & flagQualified) == 0)
7831 *flags |= flagQualified;
7832 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007833 return (1);
7834
William M. Brack2f2a6632004-08-20 23:09:47 +00007835 return (0);
7836}
7837
7838/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007839 * xmlSchemaPValAttrBlockFinal:
7840 * @value: the value
7841 * @flags: the flags to be modified
7842 * @flagAll: the specific flag for "#all"
7843 * @flagExtension: the specific flag for "extension"
7844 * @flagRestriction: the specific flag for "restriction"
7845 * @flagSubstitution: the specific flag for "substitution"
7846 * @flagList: the specific flag for "list"
7847 * @flagUnion: the specific flag for "union"
7848 *
7849 * Validates the value of the attribute "final" and "block". The value
7850 * is converted into the specified flag values and returned in @flags.
7851 *
7852 * Returns 0 if the value is valid, 1 otherwise.
7853 */
7854
7855static int
7856xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007857 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007858 int flagAll,
7859 int flagExtension,
7860 int flagRestriction,
7861 int flagSubstitution,
7862 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007864{
7865 int ret = 0;
7866
7867 /*
7868 * TODO: This does not check for dublicate entries.
7869 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007870 if ((flags == NULL) || (value == NULL))
7871 return (-1);
7872 if (value[0] == 0)
7873 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007874 if (xmlStrEqual(value, BAD_CAST "#all")) {
7875 if (flagAll != -1)
7876 *flags |= flagAll;
7877 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007878 if (flagExtension != -1)
7879 *flags |= flagExtension;
7880 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007881 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007882 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007883 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007884 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007885 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007886 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007887 *flags |= flagUnion;
7888 }
7889 } else {
7890 const xmlChar *end, *cur = value;
7891 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007892
Daniel Veillardc0826a72004-08-10 14:17:33 +00007893 do {
7894 while (IS_BLANK_CH(*cur))
7895 cur++;
7896 end = cur;
7897 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7898 end++;
7899 if (end == cur)
7900 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007902 if (xmlStrEqual(item, BAD_CAST "extension")) {
7903 if (flagExtension != -1) {
7904 if ((*flags & flagExtension) == 0)
7905 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007906 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007907 ret = 1;
7908 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7909 if (flagRestriction != -1) {
7910 if ((*flags & flagRestriction) == 0)
7911 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007913 ret = 1;
7914 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7915 if (flagSubstitution != -1) {
7916 if ((*flags & flagSubstitution) == 0)
7917 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007918 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007919 ret = 1;
7920 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7921 if (flagList != -1) {
7922 if ((*flags & flagList) == 0)
7923 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007924 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007925 ret = 1;
7926 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7927 if (flagUnion != -1) {
7928 if ((*flags & flagUnion) == 0)
7929 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007930 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007931 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007933 ret = 1;
7934 if (item != NULL)
7935 xmlFree(item);
7936 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007937 } while ((ret == 0) && (*cur != 0));
7938 }
7939
Daniel Veillardc0826a72004-08-10 14:17:33 +00007940 return (ret);
7941}
7942
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007943static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007944xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007945 xmlSchemaIDCPtr idc,
7946 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007947 xmlAttrPtr attr,
7948 int isField)
7949{
7950 xmlNodePtr node;
7951
7952 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007953 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007954 * Schema Component Constraint: Selector Value OK
7955 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007956 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007957 * in [XPath].
7958 */
7959 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007960 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007961 XML_SCHEMAP_INTERNAL,
7962 "Internal error: xmlSchemaCheckCSelectorXPath, "
7963 "the selector is not specified.\n", NULL, NULL);
7964 return (-1);
7965 }
7966 if (attr == NULL)
7967 node = idc->node;
7968 else
7969 node = (xmlNodePtr) attr;
7970 if (selector->xpath == NULL) {
7971 xmlSchemaPCustomErr(ctxt,
7972 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007973 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007974 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007975 "The XPath expression of the selector is not valid", NULL);
7976 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7977 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007978 const xmlChar **nsArray = NULL;
7979 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007980 /*
7981 * Compile the XPath expression.
7982 */
7983 /*
7984 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007985 * TODO: Call xmlPatterncompile with different options for selector/
7986 * field.
7987 */
7988 nsList = xmlGetNsList(attr->doc, attr->parent);
7989 /*
7990 * Build an array of prefixes and namespaces.
7991 */
7992 if (nsList != NULL) {
7993 int i, count = 0;
7994 xmlNsPtr ns;
7995
7996 for (i = 0; nsList[i] != NULL; i++)
7997 count++;
7998
7999 nsArray = (const xmlChar **) xmlMalloc(
8000 (count * 2 + 1) * sizeof(const xmlChar *));
8001 if (nsArray == NULL) {
8002 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8003 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008004 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008005 return (-1);
8006 }
8007 for (i = 0; i < count; i++) {
8008 ns = nsList[i];
8009 nsArray[2 * i] = nsList[i]->href;
8010 nsArray[2 * i + 1] = nsList[i]->prefix;
8011 }
8012 nsArray[count * 2] = NULL;
8013 xmlFree(nsList);
8014 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008015 /*
8016 * TODO: Differentiate between "selector" and "field".
8017 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008018 if (isField)
8019 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008020 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008021 else
8022 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008023 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008024 if (nsArray != NULL)
8025 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008026
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008027 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008028 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008029 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008030 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008031 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008032 "The XPath expression '%s' could not be "
8033 "compiled", selector->xpath);
8034 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008035 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008036 }
8037 return (0);
8038}
8039
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008040#define ADD_ANNOTATION(annot) \
8041 xmlSchemaAnnotPtr cur = item->annot; \
8042 if (item->annot == NULL) { \
8043 item->annot = annot; \
8044 return (annot); \
8045 } \
8046 cur = item->annot; \
8047 if (cur->next != NULL) { \
8048 cur = cur->next; \
8049 } \
8050 cur->next = annot;
8051
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008052/**
8053 * xmlSchemaAssignAnnotation:
8054 * @item: the schema component
8055 * @annot: the annotation
8056 *
8057 * Adds the annotation to the given schema component.
8058 *
8059 * Returns the given annotaion.
8060 */
8061static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008062xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8063 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008065 if ((annItem == NULL) || (annot == NULL))
8066 return (NULL);
8067 switch (annItem->type) {
8068 case XML_SCHEMA_TYPE_ELEMENT: {
8069 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8070 ADD_ANNOTATION(annot)
8071 }
8072 break;
8073 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8074 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8075 ADD_ANNOTATION(annot)
8076 }
8077 break;
8078 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8079 case XML_SCHEMA_TYPE_ANY: {
8080 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8081 ADD_ANNOTATION(annot)
8082 }
8083 break;
8084 case XML_SCHEMA_TYPE_PARTICLE:
8085 case XML_SCHEMA_TYPE_IDC_KEY:
8086 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008087 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008088 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8089 ADD_ANNOTATION(annot)
8090 }
8091 break;
8092 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8093 xmlSchemaAttributeGroupPtr item =
8094 (xmlSchemaAttributeGroupPtr) annItem;
8095 ADD_ANNOTATION(annot)
8096 }
8097 break;
8098 case XML_SCHEMA_TYPE_NOTATION: {
8099 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8100 ADD_ANNOTATION(annot)
8101 }
8102 break;
8103 case XML_SCHEMA_FACET_MININCLUSIVE:
8104 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8105 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8106 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8107 case XML_SCHEMA_FACET_TOTALDIGITS:
8108 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8109 case XML_SCHEMA_FACET_PATTERN:
8110 case XML_SCHEMA_FACET_ENUMERATION:
8111 case XML_SCHEMA_FACET_WHITESPACE:
8112 case XML_SCHEMA_FACET_LENGTH:
8113 case XML_SCHEMA_FACET_MAXLENGTH:
8114 case XML_SCHEMA_FACET_MINLENGTH: {
8115 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8116 ADD_ANNOTATION(annot)
8117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008118 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008119 case XML_SCHEMA_TYPE_SIMPLE:
8120 case XML_SCHEMA_TYPE_COMPLEX: {
8121 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8122 ADD_ANNOTATION(annot)
8123 }
8124 break;
8125 case XML_SCHEMA_TYPE_GROUP: {
8126 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8127 ADD_ANNOTATION(annot)
8128 }
8129 break;
8130 case XML_SCHEMA_TYPE_SEQUENCE:
8131 case XML_SCHEMA_TYPE_CHOICE:
8132 case XML_SCHEMA_TYPE_ALL: {
8133 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8134 ADD_ANNOTATION(annot)
8135 }
8136 break;
8137 default:
8138 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008140 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008141 "Internal error: xmlSchemaAddAnnotation, "
8142 "The item is not a annotated schema component", NULL);
8143 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008144 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008145 return (annot);
8146}
8147
8148/**
8149 * xmlSchemaParseIDCSelectorAndField:
8150 * @ctxt: a schema validation context
8151 * @schema: the schema being built
8152 * @node: a subtree containing XML Schema informations
8153 *
8154 * Parses a XML Schema identity-contraint definition's
8155 * <selector> and <field> elements.
8156 *
8157 * Returns the parsed identity-constraint definition.
8158 */
8159static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008161 xmlSchemaPtr schema,
8162 xmlSchemaIDCPtr idc,
8163 xmlNodePtr node,
8164 int isField)
8165{
8166 xmlSchemaIDCSelectPtr item;
8167 xmlNodePtr child = NULL;
8168 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008169
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008170 /*
8171 * Check for illegal attributes.
8172 */
8173 attr = node->properties;
8174 while (attr != NULL) {
8175 if (attr->ns == NULL) {
8176 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8177 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008178 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008179 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008180 }
8181 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008182 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008184 }
8185 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008187 /*
8188 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008189 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008190 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8191 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008192 xmlSchemaPErrMemory(ctxt,
8193 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008194 NULL);
8195 return (NULL);
8196 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008197 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008198 /*
8199 * Attribute "xpath" (mandatory).
8200 */
8201 attr = xmlSchemaGetPropNode(node, "xpath");
8202 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008203 xmlSchemaPMissingAttrErr(ctxt,
8204 XML_SCHEMAP_S4S_ATTR_MISSING,
8205 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008206 "name", NULL);
8207 } else {
8208 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8209 /*
8210 * URGENT TODO: "field"s have an other syntax than "selector"s.
8211 */
8212
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008213 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8214 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008215 xmlSchemaPErr(ctxt,
8216 (xmlNodePtr) attr,
8217 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008218 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008219 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008220 NULL, NULL);
8221 }
8222
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008223 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008224 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008225 /*
8226 * And now for the children...
8227 */
8228 child = node->children;
8229 if (IS_SCHEMA(child, "annotation")) {
8230 /*
8231 * Add the annotation to the parent IDC.
8232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008233 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008234 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008235 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008237 if (child != NULL) {
8238 xmlSchemaPContentErr(ctxt,
8239 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008240 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008241 NULL, "(annotation?)");
8242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008243
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008244 return (item);
8245}
8246
8247/**
8248 * xmlSchemaParseIDC:
8249 * @ctxt: a schema validation context
8250 * @schema: the schema being built
8251 * @node: a subtree containing XML Schema informations
8252 *
8253 * Parses a XML Schema identity-contraint definition.
8254 *
8255 * Returns the parsed identity-constraint definition.
8256 */
8257static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008258xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008259 xmlSchemaPtr schema,
8260 xmlNodePtr node,
8261 xmlSchemaTypeType idcCategory,
8262 const xmlChar *targetNamespace)
8263{
8264 xmlSchemaIDCPtr item = NULL;
8265 xmlNodePtr child = NULL;
8266 xmlAttrPtr attr;
8267 const xmlChar *name = NULL;
8268 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008269
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008270 /*
8271 * Check for illegal attributes.
8272 */
8273 attr = node->properties;
8274 while (attr != NULL) {
8275 if (attr->ns == NULL) {
8276 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8277 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8278 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8279 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008280 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008282 }
8283 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008284 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008285 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008286 }
8287 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008288 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008289 /*
8290 * Attribute "name" (mandatory).
8291 */
8292 attr = xmlSchemaGetPropNode(node, "name");
8293 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008294 xmlSchemaPMissingAttrErr(ctxt,
8295 XML_SCHEMAP_S4S_ATTR_MISSING,
8296 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008297 "name", NULL);
8298 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008299 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008300 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008301 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8302 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008304 /* Create the component. */
8305 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8306 idcCategory, node);
8307 if (item == NULL)
8308 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008309
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008310 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008311 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8312 /*
8313 * Attribute "refer" (mandatory).
8314 */
8315 attr = xmlSchemaGetPropNode(node, "refer");
8316 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 xmlSchemaPMissingAttrErr(ctxt,
8318 XML_SCHEMAP_S4S_ATTR_MISSING,
8319 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008320 "refer", NULL);
8321 } else {
8322 /*
8323 * Create a reference item.
8324 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008325 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008326 NULL, NULL);
8327 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008328 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008329 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008330 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008331 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008332 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008333 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008334 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008335 }
8336 }
8337 /*
8338 * And now for the children...
8339 */
8340 child = node->children;
8341 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008342 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008343 child = child->next;
8344 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008345 if (child == NULL) {
8346 xmlSchemaPContentErr(ctxt,
8347 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008348 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008349 "A child element is missing",
8350 "(annotation?, (selector, field+))");
8351 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008352 /*
8353 * Child element <selector>.
8354 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008355 if (IS_SCHEMA(child, "selector")) {
8356 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008357 item, child, 0);
8358 child = child->next;
8359 /*
8360 * Child elements <field>.
8361 */
8362 if (IS_SCHEMA(child, "field")) {
8363 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008364 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008365 item, child, 1);
8366 if (field != NULL) {
8367 field->index = item->nbFields;
8368 item->nbFields++;
8369 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008371 else
8372 item->fields = field;
8373 lastField = field;
8374 }
8375 child = child->next;
8376 } while (IS_SCHEMA(child, "field"));
8377 } else {
8378 xmlSchemaPContentErr(ctxt,
8379 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008380 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008381 NULL, "(annotation?, (selector, field+))");
8382 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008383 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008384 if (child != NULL) {
8385 xmlSchemaPContentErr(ctxt,
8386 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008387 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008388 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008389 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008390
8391 return (item);
8392}
8393
Daniel Veillardc0826a72004-08-10 14:17:33 +00008394/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008395 * xmlSchemaParseElement:
8396 * @ctxt: a schema validation context
8397 * @schema: the schema being built
8398 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008399 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008400 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008401 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008402 * *WARNING* this interface is highly subject to change
8403 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008404 * Returns the element declaration or a particle; NULL in case
8405 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008406 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008407static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008408xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008409 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008410{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008411 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008412 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008413 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008414 xmlNodePtr child = NULL;
8415 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008416 int min, max, isRef = 0;
8417 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008418
8419 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8420 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008421
Daniel Veillard4255d502002-04-16 15:50:10 +00008422 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008423 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008424
8425 if (isElemRef != NULL)
8426 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008427 /*
8428 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008429 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008430 * robust.
8431 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008432 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008433 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008434 if ((topLevel) || (attr == NULL)) {
8435 if (nameAttr == NULL) {
8436 xmlSchemaPMissingAttrErr(ctxt,
8437 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008438 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008439 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008440 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008441 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008442 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008443
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008444 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008445 child = node->children;
8446 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008447 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008448 child = child->next;
8449 }
8450 /*
8451 * Skip particle part if a global declaration.
8452 */
8453 if (topLevel)
8454 goto declaration_part;
8455 /*
8456 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008457 */
8458 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8459 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8460 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008461 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8462 if (particle == NULL)
8463 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008464
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008465 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008467 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008468 const xmlChar *refNs = NULL, *ref = NULL;
8469 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008470 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008471 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008472 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008473 if (isElemRef != NULL)
8474 *isElemRef = 1;
8475
Daniel Veillardc0826a72004-08-10 14:17:33 +00008476 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008477 NULL, attr, &refNs, &ref);
8478 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008479 /*
8480 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008481 */
8482 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008483 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008484 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008486 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008487 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008488 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008489 attr = node->properties;
8490 while (attr != NULL) {
8491 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008492 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8493 xmlStrEqual(attr->name, BAD_CAST "name") ||
8494 xmlStrEqual(attr->name, BAD_CAST "id") ||
8495 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8496 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8497 {
8498 attr = attr->next;
8499 continue;
8500 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008501 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008502 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008503 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008504 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008505 "Only the attributes 'minOccurs', 'maxOccurs' and "
8506 "'id' are allowed in addition to 'ref'");
8507 break;
8508 }
8509 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8510 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008512 }
8513 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008514 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008515 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008516 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008517 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008518 if (child != NULL) {
8519 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008520 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008521 }
8522 if ((min == 0) && (max == 0))
8523 goto return_null;
8524 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008525 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008526 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008527 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008528 ref, refNs);
8529 if (refer == NULL)
8530 goto return_null;
8531 particle->children = (xmlSchemaTreeItemPtr) refer;
8532 particle->annot = annot;
8533 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008534 * Add the particle to pending components, since the reference
8535 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008536 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008537 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008538 return ((xmlSchemaBasicItemPtr) particle);
8539 }
8540 /*
8541 * The declaration part ===============================================
8542 */
8543declaration_part:
8544 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008545 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008546 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8547
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008548 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008549 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008550 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008551 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008552 * Evaluate the target namespace.
8553 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008554 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008555 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008556 } else {
8557 attr = xmlSchemaGetPropNode(node, "form");
8558 if (attr != NULL) {
8559 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8560 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008561 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008562 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008563 xmlSchemaPSimpleTypeErr(ctxt,
8564 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8565 NULL, (xmlNodePtr) attr,
8566 NULL, "(qualified | unqualified)",
8567 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008568 }
8569 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008570 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008572 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008574 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008575 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008576 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008577 * Check for illegal attributes.
8578 */
William M. Bracke7091952004-05-11 15:09:58 +00008579 attr = node->properties;
8580 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008581 if (attr->ns == NULL) {
8582 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8583 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008584 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008585 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008586 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008587 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8589 {
8590 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008591 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008592 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008594 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008595 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008596 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8599 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008600 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8601
8602 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008604 }
8605 }
8606 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607
Daniel Veillardc0826a72004-08-10 14:17:33 +00008608 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008609 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008610 }
8611 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008612 }
William M. Bracke7091952004-05-11 15:09:58 +00008613 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008614 * Extract/validate attributes.
8615 */
8616 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008618 * Process top attributes of global element declarations here.
8619 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008620 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8621 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008622 xmlSchemaPValAttrQName(ctxt, schema,
8623 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008624 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008625 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008627 /*
8628 * Attribute "final".
8629 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008631 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008632 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8633 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8634 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8635 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008636 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008637 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8638 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 -1,
8640 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8641 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008642 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008643 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008644 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008645 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008646 attrValue, NULL, NULL, NULL);
8647 }
8648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008649 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008650 /*
8651 * Attribute "block".
8652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008653 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008655 /*
8656 * Apply default "block" values.
8657 */
8658 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8659 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8660 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8661 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8662 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8663 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008664 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008665 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8666 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008667 -1,
8668 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008669 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008670 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8671 xmlSchemaPSimpleTypeErr(ctxt,
8672 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008673 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008674 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008675 "restriction | substitution))", attrValue,
8676 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008677 }
8678 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008679 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008680 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 attr = xmlSchemaGetPropNode(node, "type");
8683 if (attr != NULL) {
8684 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008685 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008686 &(decl->namedTypeNs), &(decl->namedType));
8687 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008688 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008689 }
8690 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8691 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008692 if (attr != NULL) {
8693 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008694 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008695 /*
8696 * 3.3.3 : 1
8697 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008698 */
8699 xmlSchemaPMutualExclAttrErr(ctxt,
8700 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008701 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008702 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8704 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008705 }
William M. Bracke7091952004-05-11 15:09:58 +00008706 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008707 /*
8708 * And now for the children...
8709 */
William M. Bracke7091952004-05-11 15:09:58 +00008710 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008711 /*
8712 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008713 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008714 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008715 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008716 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008717 xmlSchemaPContentErr(ctxt,
8718 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008719 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008720 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008721 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008722 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008723 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008724 child = child->next;
8725 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008726 /*
8727 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008728 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008730 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008731 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008732 xmlSchemaPContentErr(ctxt,
8733 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008734 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008735 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008736 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008737 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008738 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008739 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008740 }
William M. Bracke7091952004-05-11 15:09:58 +00008741 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008742 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008743 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008745 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008746 } else if (IS_SCHEMA(child, "key")) {
8747 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008748 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008749 } else if (IS_SCHEMA(child, "keyref")) {
8750 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008751 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008752 }
8753 if (lastIDC != NULL)
8754 lastIDC->next = curIDC;
8755 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008756 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008757 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008758 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008759 }
8760 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008761 xmlSchemaPContentErr(ctxt,
8762 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008763 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764 NULL, "(annotation?, ((simpleType | complexType)?, "
8765 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008766 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008767 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008768 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008769 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008770 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008771 * different layer.
8772 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008773 FREE_AND_NULL(des)
8774 if (topLevel)
8775 return ((xmlSchemaBasicItemPtr) decl);
8776 else {
8777 particle->children = (xmlSchemaTreeItemPtr) decl;
8778 return ((xmlSchemaBasicItemPtr) particle);
8779 }
8780
8781return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008782 FREE_AND_NULL(des);
8783 if (annot != NULL) {
8784 if (particle != NULL)
8785 particle->annot = NULL;
8786 if (decl != NULL)
8787 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008788 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008790 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008791}
8792
8793/**
8794 * xmlSchemaParseUnion:
8795 * @ctxt: a schema validation context
8796 * @schema: the schema being built
8797 * @node: a subtree containing XML Schema informations
8798 *
8799 * parse a XML schema Union definition
8800 * *WARNING* this interface is highly subject to change
8801 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008802 * Returns -1 in case of internal error, 0 in case of success and a positive
8803 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008804 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008805static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008806xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008807 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008808{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008809 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008810 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008811 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008812 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008813
8814 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008815 return (-1);
8816 /* Not a component, don't create it. */
8817 type = ctxt->ctxtType;
8818 /*
8819 * Mark the simple type as being of variety "union".
8820 */
8821 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008823 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8824 * then the ·simple ur-type definition·."
8825 */
8826 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008827 /*
8828 * Check for illegal attributes.
8829 */
8830 attr = node->properties;
8831 while (attr != NULL) {
8832 if (attr->ns == NULL) {
8833 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8834 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008835 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008836 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008837 }
8838 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008839 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008840 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008841 }
8842 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008844 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008845 /*
8846 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008847 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008849 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008850 if (attr != NULL) {
8851 const xmlChar *end;
8852 xmlChar *tmp;
8853 const xmlChar *localName, *nsName;
8854 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8855 xmlSchemaQNameRefPtr ref;
8856
8857 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008858 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008859 do {
8860 while (IS_BLANK_CH(*cur))
8861 cur++;
8862 end = cur;
8863 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8864 end++;
8865 if (end == cur)
8866 break;
8867 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008868 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008869 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008870 /*
8871 * Create the member type link.
8872 */
8873 link = (xmlSchemaTypeLinkPtr)
8874 xmlMalloc(sizeof(xmlSchemaTypeLink));
8875 if (link == NULL) {
8876 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8877 "allocating a type link", NULL);
8878 return (-1);
8879 }
8880 link->type = NULL;
8881 link->next = NULL;
8882 if (lastLink == NULL)
8883 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008884 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008885 lastLink->next = link;
8886 lastLink = link;
8887 /*
8888 * Create a reference item.
8889 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008890 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008891 localName, nsName);
8892 if (ref == NULL) {
8893 FREE_AND_NULL(tmp)
8894 return (-1);
8895 }
8896 /*
8897 * Assign the reference to the link, it will be resolved
8898 * later during fixup of the union simple type.
8899 */
8900 link->type = (xmlSchemaTypePtr) ref;
8901 }
8902 FREE_AND_NULL(tmp)
8903 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008904 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008905
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008906 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008907 /*
8908 * And now for the children...
8909 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008910 child = node->children;
8911 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008912 /*
8913 * Add the annotation to the simple type ancestor.
8914 */
8915 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008916 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008917 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008918 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008919 if (IS_SCHEMA(child, "simpleType")) {
8920 xmlSchemaTypePtr subtype, last = NULL;
8921
8922 /*
8923 * Anchor the member types in the "subtypes" field of the
8924 * simple type.
8925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008926 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008927 subtype = (xmlSchemaTypePtr)
8928 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8929 if (subtype != NULL) {
8930 if (last == NULL) {
8931 type->subtypes = subtype;
8932 last = subtype;
8933 } else {
8934 last->next = subtype;
8935 last = subtype;
8936 }
8937 last->next = NULL;
8938 }
8939 child = child->next;
8940 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008941 }
8942 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008943 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008945 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008947 if ((attr == NULL) && (type->subtypes == NULL)) {
8948 /*
8949 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008950 * Either the memberTypes [attribute] of the <union> element must
8951 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008952 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008954 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008955 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008956 "Either the attribute 'memberTypes' or "
8957 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008958 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008959 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008960}
8961
8962/**
8963 * xmlSchemaParseList:
8964 * @ctxt: a schema validation context
8965 * @schema: the schema being built
8966 * @node: a subtree containing XML Schema informations
8967 *
8968 * parse a XML schema List definition
8969 * *WARNING* this interface is highly subject to change
8970 *
William M. Bracke7091952004-05-11 15:09:58 +00008971 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008972 * 1 in case of success.
8973 */
8974static xmlSchemaTypePtr
8975xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008976 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008977{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008978 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008979 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008980 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008981
8982 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8983 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008984 /* Not a component, don't create it. */
8985 type = ctxt->ctxtType;
8986 /*
8987 * Mark the type as being of variety "list".
8988 */
8989 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008990 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008991 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8992 * then the ·simple ur-type definition·."
8993 */
8994 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008995 /*
8996 * Check for illegal attributes.
8997 */
8998 attr = node->properties;
8999 while (attr != NULL) {
9000 if (attr->ns == NULL) {
9001 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9002 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009003 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009005 }
9006 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009008 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009009 }
9010 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009012
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009013 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009014
William M. Brack2f2a6632004-08-20 23:09:47 +00009015 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009016 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9017 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009018 *
9019 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9020 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009021 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009022 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9023 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009024 /*
9025 * And now for the children...
9026 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009027 child = node->children;
9028 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009029 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009030 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009031 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009032 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009033 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009034 /*
9035 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036 * Either the itemType [attribute] or the <simpleType> [child] of
9037 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009038 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009039 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009040 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009041 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009042 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009043 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009044 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009045 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009046 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009047 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009049 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009050 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009051 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009052 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009053 "Either the attribute 'itemType' or the <simpleType> child "
9054 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009055 }
9056 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009057 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009058 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009059 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009060 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009061 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009062 (type->subtypes == NULL) &&
9063 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009064 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009065 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009066 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009067 "Either the attribute 'itemType' or the <simpleType> child "
9068 "must be present", NULL);
9069 }
9070 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009071}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009072
Daniel Veillard4255d502002-04-16 15:50:10 +00009073/**
9074 * xmlSchemaParseSimpleType:
9075 * @ctxt: a schema validation context
9076 * @schema: the schema being built
9077 * @node: a subtree containing XML Schema informations
9078 *
9079 * parse a XML schema Simple Type definition
9080 * *WARNING* this interface is highly subject to change
9081 *
William M. Bracke7091952004-05-11 15:09:58 +00009082 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009083 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009084 */
9085static xmlSchemaTypePtr
9086xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009087 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009088{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009089 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009090 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009091 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009092 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009093 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009094
9095 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9096 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009097
Daniel Veillardc0826a72004-08-10 14:17:33 +00009098 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009099 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009100 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009101 xmlSchemaPMissingAttrErr(ctxt,
9102 XML_SCHEMAP_S4S_ATTR_MISSING,
9103 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009104 "name", NULL);
9105 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009106 } else {
9107 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009108 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009109 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9110 return (NULL);
9111 /*
9112 * Skip built-in types.
9113 */
9114 if (ctxt->isS4S) {
9115 xmlSchemaTypePtr biType;
9116
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009117 if (ctxt->isRedefine) {
9118 /*
9119 * REDEFINE: Disallow redefinition of built-in-types.
9120 * TODO: It seems that the spec does not say anything
9121 * about this case.
9122 */
9123 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009124 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009125 "Redefinition of built-in simple types is not "
9126 "supported", NULL);
9127 return(NULL);
9128 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009129 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9130 if (biType != NULL)
9131 return (biType);
9132 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009133 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009134 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009135 /*
9136 * TargetNamespace:
9137 * SPEC "The ·actual value· of the targetNamespace [attribute]
9138 * of the <schema> ancestor element information item if present,
9139 * otherwise ·absent·.
9140 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009141 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009142#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009143 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009144#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009145 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009146 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009147 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009148#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009149 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009150 type = xmlSchemaAddType(ctxt, schema,
9151 XML_SCHEMA_TYPE_SIMPLE,
9152 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009153 ctxt->targetNamespace, node, 0);
9154#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009155 type = xmlSchemaAddType(ctxt, schema,
9156 XML_SCHEMA_TYPE_SIMPLE,
9157 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009158#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009159 if (type == NULL)
9160 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009161 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009162 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009163 /*
9164 * Check for illegal attributes.
9165 */
9166 attr = node->properties;
9167 while (attr != NULL) {
9168 if (attr->ns == NULL) {
9169 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009170 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009171 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009172 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009173 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009174 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009175 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009176 }
9177 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009178 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009179 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009180 /*
9181 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009182 *
9183 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009184 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009185 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9186 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009187 if (type == NULL)
9188 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009189 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009190 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009191 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9192 /*
9193 * Check for illegal attributes.
9194 */
9195 attr = node->properties;
9196 while (attr != NULL) {
9197 if (attr->ns == NULL) {
9198 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9199 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009200 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009202 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009203 }
9204 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009205 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009206 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207 }
9208 attr = attr->next;
9209 }
9210 /*
9211 * Attribute "final".
9212 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009213 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009214 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009215 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9216 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9217 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9218 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9219 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9220 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009221 } else {
9222 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009223 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9224 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009225 XML_SCHEMAS_TYPE_FINAL_LIST,
9226 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9227
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009228 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009229 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009230 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009231 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009232 attrValue, NULL, NULL, NULL);
9233 }
9234 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009235 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009236 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009237 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009238 /*
9239 * And now for the children...
9240 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009241 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009242
Daniel Veillardc0826a72004-08-10 14:17:33 +00009243 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009244
Daniel Veillard4255d502002-04-16 15:50:10 +00009245 child = node->children;
9246 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009247 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009248 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009249 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009250 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009251 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009252 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009253 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009254 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009255 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009256 XML_SCHEMA_TYPE_SIMPLE);
9257 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009258 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009259 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009260 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009261 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009262 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009263 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009264 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009265 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009266 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009267 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009268 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009269 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009270 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009271 /*
9272 * REDEFINE: SPEC src-redefine (5)
9273 * "Within the [children], each <simpleType> must have a
9274 * <restriction> among its [children] ... the ·actual value· of whose
9275 * base [attribute] must be the same as the ·actual value· of its own
9276 * name attribute plus target namespace;"
9277 */
9278 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9279 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009280 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009281 "<simpleType> must have a <restriction> child", NULL);
9282 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009284 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009285 return (type);
9286}
9287
Daniel Veillard4255d502002-04-16 15:50:10 +00009288/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009289 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009290 * @ctxt: the parser context
9291 * @schema: the schema being built
9292 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009293 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009294 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009295 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009296 * We will return a particle component with a qname-component or
9297 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009298 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009299static xmlSchemaTreeItemPtr
9300xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9301 xmlSchemaPtr schema,
9302 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009303{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009304 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009305 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009306 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009307 const xmlChar *ref = NULL, *refNs = NULL;
9308 int min, max;
9309
9310 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009311 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009312
9313 attr = xmlSchemaGetPropNode(node, "ref");
9314 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009315 xmlSchemaPMissingAttrErr(ctxt,
9316 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009317 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009318 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009319 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009321 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009322 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009323 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009324 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009325 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009326 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009327 /*
9328 * Check for illegal attributes.
9329 */
9330 attr = node->properties;
9331 while (attr != NULL) {
9332 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009334 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9335 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9336 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009337 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009338 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009339 }
9340 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009341 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009342 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009343 }
9344 attr = attr->next;
9345 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009346 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009347 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9348 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009349 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009350 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009351 * Create a qname-reference and set as the term; it will be substituted
9352 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009353 */
9354 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009355 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009356 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9357 /*
9358 * And now for the children...
9359 */
9360 child = node->children;
9361 /* TODO: Is annotation even allowed for a model group reference? */
9362 if (IS_SCHEMA(child, "annotation")) {
9363 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009364 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009365 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009366 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009367 child = child->next;
9368 }
9369 if (child != NULL) {
9370 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009371 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009372 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009373 "(annotation?)");
9374 }
9375 /*
9376 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9377 */
9378 if ((min == 0) && (max == 0))
9379 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009380
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009381 return ((xmlSchemaTreeItemPtr) item);
9382}
9383
9384/**
9385 * xmlSchemaParseModelGroupDefinition:
9386 * @ctxt: a schema validation context
9387 * @schema: the schema being built
9388 * @node: a subtree containing XML Schema informations
9389 *
9390 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009391 *
9392 * Note that the contraint src-redefine (6.2) can't be applied until
9393 * references have been resolved. So we will do this at the
9394 * component fixup level.
9395 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009396 * *WARNING* this interface is highly subject to change
9397 *
9398 * Returns -1 in case of error, 0 if the declaration is improper and
9399 * 1 in case of success.
9400 */
9401static xmlSchemaModelGroupDefPtr
9402xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9403 xmlSchemaPtr schema,
9404 xmlNodePtr node)
9405{
9406 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009407 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009408 xmlAttrPtr attr;
9409 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009410
9411 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009412 return (NULL);
9413
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009414 attr = xmlSchemaGetPropNode(node, "name");
9415 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009416 xmlSchemaPMissingAttrErr(ctxt,
9417 XML_SCHEMAP_S4S_ATTR_MISSING,
9418 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009419 "name", NULL);
9420 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009421 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9423 return (NULL);
9424 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009425 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9426 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009427 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009429 /*
9430 * Check for illegal attributes.
9431 */
9432 attr = node->properties;
9433 while (attr != NULL) {
9434 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009435 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009436 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009437 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009438 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009440 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009441 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009442 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009443 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009444 attr = attr->next;
9445 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009446 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009447 /*
9448 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009449 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009450 child = node->children;
9451 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009452 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009453 child = child->next;
9454 }
9455 if (IS_SCHEMA(child, "all")) {
9456 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9457 XML_SCHEMA_TYPE_ALL, 0);
9458 child = child->next;
9459 } else if (IS_SCHEMA(child, "choice")) {
9460 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9461 XML_SCHEMA_TYPE_CHOICE, 0);
9462 child = child->next;
9463 } else if (IS_SCHEMA(child, "sequence")) {
9464 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9465 XML_SCHEMA_TYPE_SEQUENCE, 0);
9466 child = child->next;
9467 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009468
9469
9470
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009471 if (child != NULL) {
9472 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009473 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009474 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009475 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009477 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009478}
9479
9480/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009481 * xmlSchemaCleanupDoc:
9482 * @ctxt: a schema validation context
9483 * @node: the root of the document.
9484 *
9485 * removes unwanted nodes in a schemas document tree
9486 */
9487static void
9488xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9489{
9490 xmlNodePtr delete, cur;
9491
9492 if ((ctxt == NULL) || (root == NULL)) return;
9493
9494 /*
9495 * Remove all the blank text nodes
9496 */
9497 delete = NULL;
9498 cur = root;
9499 while (cur != NULL) {
9500 if (delete != NULL) {
9501 xmlUnlinkNode(delete);
9502 xmlFreeNode(delete);
9503 delete = NULL;
9504 }
9505 if (cur->type == XML_TEXT_NODE) {
9506 if (IS_BLANK_NODE(cur)) {
9507 if (xmlNodeGetSpacePreserve(cur) != 1) {
9508 delete = cur;
9509 }
9510 }
9511 } else if ((cur->type != XML_ELEMENT_NODE) &&
9512 (cur->type != XML_CDATA_SECTION_NODE)) {
9513 delete = cur;
9514 goto skip_children;
9515 }
9516
9517 /*
9518 * Skip to next node
9519 */
9520 if (cur->children != NULL) {
9521 if ((cur->children->type != XML_ENTITY_DECL) &&
9522 (cur->children->type != XML_ENTITY_REF_NODE) &&
9523 (cur->children->type != XML_ENTITY_NODE)) {
9524 cur = cur->children;
9525 continue;
9526 }
9527 }
9528 skip_children:
9529 if (cur->next != NULL) {
9530 cur = cur->next;
9531 continue;
9532 }
9533
9534 do {
9535 cur = cur->parent;
9536 if (cur == NULL)
9537 break;
9538 if (cur == root) {
9539 cur = NULL;
9540 break;
9541 }
9542 if (cur->next != NULL) {
9543 cur = cur->next;
9544 break;
9545 }
9546 } while (cur != NULL);
9547 }
9548 if (delete != NULL) {
9549 xmlUnlinkNode(delete);
9550 xmlFreeNode(delete);
9551 delete = NULL;
9552 }
9553}
9554
William M. Brack2f2a6632004-08-20 23:09:47 +00009555
William M. Brack2f2a6632004-08-20 23:09:47 +00009556static void
9557xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9558{
9559 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9560 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9561
9562 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9563 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9564
9565 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9566 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9567 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9568 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9569 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9570 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9571 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9572 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9573
9574 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9575 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9576 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9577 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9578 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9579 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9580}
9581
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009582static int
9583xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009584 xmlSchemaPtr schema,
9585 xmlNodePtr node)
9586{
9587 xmlAttrPtr attr;
9588 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009589 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009590
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009591 /*
9592 * Those flags should be moved to the parser context flags,
9593 * since they are not visible at the component level. I.e.
9594 * they are used if processing schema *documents* only.
9595 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009596 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009597 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009598
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009599 /*
9600 * Since the version is of type xs:token, we won't bother to
9601 * check it.
9602 */
9603 /* REMOVED:
9604 attr = xmlSchemaGetPropNode(node, "version");
9605 if (attr != NULL) {
9606 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9607 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9608 HFAILURE;
9609 }
9610 */
9611 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9612 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009613 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009614 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9615 HFAILURE;
9616 if (res != 0) {
9617 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9618 goto exit;
9619 }
9620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009621 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 if (attr != NULL) {
9623 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009624 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9625 XML_SCHEMAS_QUALIF_ELEM);
9626 HFAILURE;
9627 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009628 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009629 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009630 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009631 "(qualified | unqualified)", val, NULL, NULL, NULL);
9632 }
9633 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009634 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009635 if (attr != NULL) {
9636 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009637 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9638 XML_SCHEMAS_QUALIF_ATTR);
9639 HFAILURE;
9640 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 "(qualified | unqualified)", val, NULL, NULL, NULL);
9645 }
9646 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009647 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009648 if (attr != NULL) {
9649 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009650 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9652 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9653 -1,
9654 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009655 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9656 HFAILURE;
9657 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009658 xmlSchemaPSimpleTypeErr(ctxt,
9659 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009660 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009661 "(#all | List of (extension | restriction | list | union))",
9662 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009663 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009665 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009666 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009667 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9668 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009669 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9670 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009671 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9672 HFAILURE;
9673 if (res != 0) {
9674 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009675 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009676 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009677 "(#all | List of (extension | restriction | substitution))",
9678 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009679 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009680 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009681
9682exit:
9683 if (oldErrs != ctxt->nberrors)
9684 res = ctxt->err;
9685 return(res);
9686exit_failure:
9687 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009688}
9689
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009690/**
9691 * xmlSchemaParseSchemaTopLevel:
9692 * @ctxt: a schema validation context
9693 * @schema: the schemas
9694 * @nodes: the list of top level nodes
9695 *
9696 * Returns the internal XML Schema structure built from the resource or
9697 * NULL in case of error
9698 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009699static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009700xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9701 xmlSchemaPtr schema, xmlNodePtr nodes)
9702{
9703 xmlNodePtr child;
9704 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009705 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009706
9707 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009708 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009709
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009710 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009711 child = nodes;
9712 while ((IS_SCHEMA(child, "include")) ||
9713 (IS_SCHEMA(child, "import")) ||
9714 (IS_SCHEMA(child, "redefine")) ||
9715 (IS_SCHEMA(child, "annotation"))) {
9716 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009717 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009718 if (schema->annot == NULL)
9719 schema->annot = annot;
9720 else
9721 xmlSchemaFreeAnnot(annot);
9722 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009723 tmpOldErrs = ctxt->nberrors;
9724 res = xmlSchemaParseImport(ctxt, schema, child);
9725 HFAILURE;
9726 HSTOP(ctxt);
9727 if (tmpOldErrs != ctxt->nberrors)
9728 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009729 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009730 tmpOldErrs = ctxt->nberrors;
9731 res = xmlSchemaParseInclude(ctxt, schema, child);
9732 HFAILURE;
9733 HSTOP(ctxt);
9734 if (tmpOldErrs != ctxt->nberrors)
9735 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009736 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009737 tmpOldErrs = ctxt->nberrors;
9738 res = xmlSchemaParseRedefine(ctxt, schema, child);
9739 HFAILURE;
9740 HSTOP(ctxt);
9741 if (tmpOldErrs != ctxt->nberrors)
9742 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009743 }
9744 child = child->next;
9745 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009746 /*
9747 * URGENT TODO: Change the functions to return int results.
9748 * We need especially to catch internal errors.
9749 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009750 while (child != NULL) {
9751 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009752 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009753 child = child->next;
9754 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009755 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009756 child = child->next;
9757 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009758 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009759 child = child->next;
9760 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009761 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009762 child = child->next;
9763 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009764 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009765 child = child->next;
9766 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009767 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009768 child = child->next;
9769 } else if (IS_SCHEMA(child, "notation")) {
9770 xmlSchemaParseNotation(ctxt, schema, child);
9771 child = child->next;
9772 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009773 xmlSchemaPContentErr(ctxt,
9774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009775 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009776 NULL, "((include | import | redefine | annotation)*, "
9777 "(((simpleType | complexType | group | attributeGroup) "
9778 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009779 child = child->next;
9780 }
9781 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009782 /*
9783 * TODO: We should add all annotations.
9784 */
9785 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009786 if (schema->annot == NULL)
9787 schema->annot = annot;
9788 else
9789 xmlSchemaFreeAnnot(annot);
9790 child = child->next;
9791 }
9792 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009793exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009794 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009795 if (oldErrs != ctxt->nberrors)
9796 res = ctxt->err;
9797 return(res);
9798exit_failure:
9799 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009800}
9801
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009802static xmlSchemaSchemaRelationPtr
9803xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009804{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009805 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009806
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009807 ret = (xmlSchemaSchemaRelationPtr)
9808 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009809 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009811 return(NULL);
9812 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009813 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009814 return(ret);
9815}
9816
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009817#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009818static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009819xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009820{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009821 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009822}
9823#endif
9824
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009825static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009826xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9827{
9828 xmlSchemaRedefPtr prev;
9829
9830 while (redef != NULL) {
9831 prev = redef;
9832 redef = redef->next;
9833 xmlFree(prev);
9834 }
9835}
9836
9837static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009838xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9839{
9840 /*
9841 * After the construction context has been freed, there will be
9842 * no schema graph available any more. Only the schema buckets
9843 * will stay alive, which are put into the "schemasImports" and
9844 * "includes" slots of the xmlSchema.
9845 */
9846 if (con->buckets != NULL)
9847 xmlSchemaItemListFree(con->buckets);
9848 if (con->pending != NULL)
9849 xmlSchemaItemListFree(con->pending);
9850 if (con->substGroups != NULL)
9851 xmlHashFree(con->substGroups,
9852 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009853 if (con->redefs != NULL)
9854 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009855 if (con->dict != NULL)
9856 xmlDictFree(con->dict);
9857 xmlFree(con);
9858}
9859
9860static xmlSchemaConstructionCtxtPtr
9861xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9862{
9863 xmlSchemaConstructionCtxtPtr ret;
9864
9865 ret = (xmlSchemaConstructionCtxtPtr)
9866 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9867 if (ret == NULL) {
9868 xmlSchemaPErrMemory(NULL,
9869 "allocating schema construction context", NULL);
9870 return (NULL);
9871 }
9872 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9873
9874 ret->buckets = xmlSchemaItemListCreate();
9875 if (ret->buckets == NULL) {
9876 xmlSchemaPErrMemory(NULL,
9877 "allocating list of schema buckets", NULL);
9878 xmlFree(ret);
9879 return (NULL);
9880 }
9881 ret->pending = xmlSchemaItemListCreate();
9882 if (ret->pending == NULL) {
9883 xmlSchemaPErrMemory(NULL,
9884 "allocating list of pending global components", NULL);
9885 xmlSchemaConstructionCtxtFree(ret);
9886 return (NULL);
9887 }
9888 ret->dict = dict;
9889 xmlDictReference(dict);
9890 return(ret);
9891}
9892
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009893static xmlSchemaParserCtxtPtr
9894xmlSchemaParserCtxtCreate(void)
9895{
9896 xmlSchemaParserCtxtPtr ret;
9897
9898 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9899 if (ret == NULL) {
9900 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9901 NULL);
9902 return (NULL);
9903 }
9904 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9905 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009906 ret->attrProhibs = xmlSchemaItemListCreate();
9907 if (ret->attrProhibs == NULL) {
9908 xmlFree(ret);
9909 return(NULL);
9910 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009911 return(ret);
9912}
9913
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914/**
9915 * xmlSchemaNewParserCtxtUseDict:
9916 * @URL: the location of the schema
9917 * @dict: the dictionary to be used
9918 *
9919 * Create an XML Schemas parse context for that file/resource expected
9920 * to contain an XML Schemas file.
9921 *
9922 * Returns the parser context or NULL in case of error
9923 */
9924static xmlSchemaParserCtxtPtr
9925xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9926{
9927 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009928
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009929 ret = xmlSchemaParserCtxtCreate();
9930 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009931 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009932 ret->dict = dict;
9933 xmlDictReference(dict);
9934 if (URL != NULL)
9935 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009936 return (ret);
9937}
9938
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009939static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009940xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9941{
9942 if (vctxt->pctxt == NULL) {
9943 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009944 vctxt->pctxt =
9945 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009946 else
9947 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9948 if (vctxt->pctxt == NULL) {
9949 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9950 "failed to create a temp. parser context");
9951 return (-1);
9952 }
9953 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009954 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00009955 vctxt->warning, vctxt->errCtxt);
9956 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9957 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 }
9959 return (0);
9960}
9961
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009962/**
9963 * xmlSchemaGetSchemaBucket:
9964 * @pctxt: the schema parser context
9965 * @schemaLocation: the URI of the schema document
9966 *
9967 * Returns a schema bucket if it was already parsed.
9968 *
9969 * Returns a schema bucket if it was already parsed from
9970 * @schemaLocation, NULL otherwise.
9971 */
9972static xmlSchemaBucketPtr
9973xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9974 const xmlChar *schemaLocation)
9975{
9976 xmlSchemaBucketPtr cur;
9977 xmlSchemaItemListPtr list;
9978
9979 list = pctxt->constructor->buckets;
9980 if (list->nbItems == 0)
9981 return(NULL);
9982 else {
9983 int i;
9984 for (i = 0; i < list->nbItems; i++) {
9985 cur = (xmlSchemaBucketPtr) list->items[i];
9986 /* Pointer comparison! */
9987 if (cur->schemaLocation == schemaLocation)
9988 return(cur);
9989 }
9990 }
9991 return(NULL);
9992}
9993
9994static xmlSchemaBucketPtr
9995xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9996 const xmlChar *schemaLocation,
9997 const xmlChar *targetNamespace)
9998{
9999 xmlSchemaBucketPtr cur;
10000 xmlSchemaItemListPtr list;
10001
10002 list = pctxt->constructor->buckets;
10003 if (list->nbItems == 0)
10004 return(NULL);
10005 else {
10006 int i;
10007 for (i = 0; i < list->nbItems; i++) {
10008 cur = (xmlSchemaBucketPtr) list->items[i];
10009 /* Pointer comparison! */
10010 if ((cur->origTargetNamespace == NULL) &&
10011 (cur->schemaLocation == schemaLocation) &&
10012 (cur->targetNamespace == targetNamespace))
10013 return(cur);
10014 }
10015 }
10016 return(NULL);
10017}
10018
10019
10020#define IS_BAD_SCHEMA_DOC(b) \
10021 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10022
10023static xmlSchemaBucketPtr
10024xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10025 const xmlChar *targetNamespace,
10026 int imported)
10027{
10028 xmlSchemaBucketPtr cur;
10029 xmlSchemaItemListPtr list;
10030
10031 list = pctxt->constructor->buckets;
10032 if (list->nbItems == 0)
10033 return(NULL);
10034 else {
10035 int i;
10036 for (i = 0; i < list->nbItems; i++) {
10037 cur = (xmlSchemaBucketPtr) list->items[i];
10038 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10039 (cur->origTargetNamespace == targetNamespace) &&
10040 ((imported && cur->imported) ||
10041 ((!imported) && (!cur->imported))))
10042 return(cur);
10043 }
10044 }
10045 return(NULL);
10046}
10047
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010048static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010049xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10050 xmlSchemaPtr schema,
10051 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010052{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010053 int oldFlags;
10054 xmlDocPtr oldDoc;
10055 xmlNodePtr node;
10056 int ret, oldErrs;
10057 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10058
10059 /*
10060 * Save old values; reset the *main* schema.
10061 * URGENT TODO: This is not good; move the per-document information
10062 * to the parser.
10063 */
10064 oldFlags = schema->flags;
10065 oldDoc = schema->doc;
10066 if (schema->flags != 0)
10067 xmlSchemaClearSchemaDefaults(schema);
10068 schema->doc = bucket->doc;
10069 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
10070 pctxt->schema = schema;
10071 /*
10072 * Keep the current target namespace on the parser *not* on the
10073 * main schema.
10074 */
10075 pctxt->targetNamespace = bucket->targetNamespace;
10076 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010077
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010078 if ((bucket->targetNamespace != NULL) &&
10079 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010080 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010081 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010082 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010083 pctxt->isS4S = 1;
10084 }
10085 /* Mark it as parsed, even if parsing fails. */
10086 bucket->parsed++;
10087 /* Compile the schema doc. */
10088 node = xmlDocGetRootElement(bucket->doc);
10089 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10090 if (ret != 0)
10091 goto exit;
10092 /* An empty schema; just get out. */
10093 if (node->children == NULL)
10094 goto exit;
10095 oldErrs = pctxt->nberrors;
10096 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10097 if (ret != 0)
10098 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010099 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010100 * TODO: Not nice, but I'm not 100% sure we will get always an error
10101 * as a result of the obove functions; so better rely on pctxt->err
10102 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010103 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010104 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10105 ret = pctxt->err;
10106 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010107 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010108
10109exit:
10110 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10111 /* Restore schema values. */
10112 schema->doc = oldDoc;
10113 schema->flags = oldFlags;
10114 return(ret);
10115}
10116
10117static int
10118xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10119 xmlSchemaPtr schema,
10120 xmlSchemaBucketPtr bucket)
10121{
10122 xmlSchemaParserCtxtPtr newpctxt;
10123 int res = 0;
10124
10125 if (bucket == NULL)
10126 return(0);
10127 if (bucket->parsed) {
10128 PERROR_INT("xmlSchemaParseNewDoc",
10129 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010130 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010131 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010132 if (bucket->doc == NULL) {
10133 PERROR_INT("xmlSchemaParseNewDoc",
10134 "parsing a schema doc, but there's no doc");
10135 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010136 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010137 if (pctxt->constructor == NULL) {
10138 PERROR_INT("xmlSchemaParseNewDoc",
10139 "no constructor");
10140 return(-1);
10141 }
10142 /* Create and init the temporary parser context. */
10143 newpctxt = xmlSchemaNewParserCtxtUseDict(
10144 (const char *) bucket->schemaLocation, pctxt->dict);
10145 if (newpctxt == NULL)
10146 return(-1);
10147 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010148 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010149 * TODO: Can we avoid that the parser knows about the main schema?
10150 * It would be better if he knows about the current schema bucket
10151 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010152 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010153 newpctxt->schema = schema;
10154 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010155 pctxt->errCtxt);
10156 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10157 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010158 newpctxt->counter = pctxt->counter;
10159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010160
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010161 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10162
10163 /* Channel back errors and cleanup the temporary parser context. */
10164 if (res != 0)
10165 pctxt->err = res;
10166 pctxt->nberrors += newpctxt->nberrors;
10167 pctxt->counter = newpctxt->counter;
10168 newpctxt->constructor = NULL;
10169 /* Free the parser context. */
10170 xmlSchemaFreeParserCtxt(newpctxt);
10171 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010172}
William M. Brack2f2a6632004-08-20 23:09:47 +000010173
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010174static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010175xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10176 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010177{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010178 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010179
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010180 if (cur == NULL) {
10181 bucket->relations = rel;
10182 return;
10183 }
10184 while (cur->next != NULL)
10185 cur = cur->next;
10186 cur->next = rel;
10187}
10188
10189
10190static const xmlChar *
10191xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10192 xmlNodePtr ctxtNode)
10193{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010194 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010195 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010196 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010197 if (location != NULL) {
10198 if (ctxtNode == NULL)
10199 return(location);
10200 else {
10201 xmlChar *base, *URI;
10202 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010203
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010204 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10205 if (base == NULL) {
10206 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10207 } else {
10208 URI = xmlBuildURI(location, base);
10209 xmlFree(base);
10210 }
10211 if (URI != NULL) {
10212 ret = xmlDictLookup(dict, URI, -1);
10213 xmlFree(URI);
10214 return(ret);
10215 }
10216 }
10217 }
10218 return(NULL);
10219}
10220
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010221
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010222
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010223/**
10224 * xmlSchemaAddSchemaDoc:
10225 * @pctxt: a schema validation context
10226 * @schema: the schema being built
10227 * @node: a subtree containing XML Schema informations
10228 *
10229 * Parse an included (and to-be-redefined) XML schema document.
10230 *
10231 * Returns 0 on success, a positive error code on errors and
10232 * -1 in case of an internal or API error.
10233 */
10234
10235static int
10236xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10237 int type, /* import or include or redefine */
10238 const xmlChar *schemaLocation,
10239 xmlDocPtr schemaDoc,
10240 const char *schemaBuffer,
10241 int schemaBufferLen,
10242 xmlNodePtr invokingNode,
10243 const xmlChar *sourceTargetNamespace,
10244 const xmlChar *importNamespace,
10245 xmlSchemaBucketPtr *bucket)
10246{
10247 const xmlChar *targetNamespace = NULL;
10248 xmlSchemaSchemaRelationPtr relation = NULL;
10249 xmlDocPtr doc = NULL;
10250 int res = 0, err = 0, located = 0, preserveDoc = 0;
10251 xmlSchemaBucketPtr bkt = NULL;
10252
10253 if (bucket != NULL)
10254 *bucket = NULL;
10255
10256 switch (type) {
10257 case XML_SCHEMA_SCHEMA_IMPORT:
10258 case XML_SCHEMA_SCHEMA_MAIN:
10259 err = XML_SCHEMAP_SRC_IMPORT;
10260 break;
10261 case XML_SCHEMA_SCHEMA_INCLUDE:
10262 err = XML_SCHEMAP_SRC_INCLUDE;
10263 break;
10264 case XML_SCHEMA_SCHEMA_REDEFINE:
10265 err = XML_SCHEMAP_SRC_REDEFINE;
10266 break;
10267 }
10268
10269
10270 /* Special handling for the main schema:
10271 * skip the location and relation logic and just parse the doc.
10272 * We need just a bucket to be returned in this case.
10273 */
10274 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10275 goto doc_load;
10276
10277 /* Note that we expect the location to be an absulute URI. */
10278 if (schemaLocation != NULL) {
10279 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10280 if ((bkt != NULL) &&
10281 (pctxt->constructor->bucket == bkt)) {
10282 /* Report self-imports/inclusions/redefinitions. */
10283
10284 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10285 invokingNode, NULL,
10286 "The schema must not import/include/redefine itself",
10287 NULL, NULL);
10288 goto exit;
10289 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010290 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010291 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010292 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010293 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010294 relation = xmlSchemaSchemaRelationCreate();
10295 if (relation == NULL)
10296 return(-1);
10297 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10298 relation);
10299 relation->type = type;
10300
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010301 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010302 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010303 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010304 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010305 relation->importNamespace = importNamespace;
10306 if (schemaLocation == NULL) {
10307 /*
10308 * No location; this is just an import of the namespace.
10309 * Note that we don't assign a bucket to the relation
10310 * in this case.
10311 */
10312 goto exit;
10313 }
10314 targetNamespace = importNamespace;
10315 }
10316
10317 /* Did we already fetch the doc? */
10318 if (bkt != NULL) {
10319 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010320 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010321 /* We included/redefined and then try to import a schema. */
10322 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10323 invokingNode, NULL,
10324 "The schema document '%s' cannot be imported, since "
10325 "it was already included or redefined",
10326 schemaLocation, NULL);
10327 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010328 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010329 /* We imported and then try to include/redefine a schema. */
10330 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10331 invokingNode, NULL,
10332 "The schema document '%s' cannot be included or "
10333 "redefined, since it was already imported",
10334 schemaLocation, NULL);
10335 goto exit;
10336 }
10337 }
10338
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010339 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010340 /*
10341 * Given that the schemaLocation [attribute] is only a hint, it is open
10342 * to applications to ignore all but the first <import> for a given
10343 * namespace, regardless of the ·actual value· of schemaLocation, but
10344 * such a strategy risks missing useful information when new
10345 * schemaLocations are offered.
10346 *
10347 * We will use the first <import> that comes with a location.
10348 * Further <import>s *with* a location, will result in an error.
10349 * TODO: Better would be to just report a warning here, but
10350 * we'll try it this way until someone complains.
10351 *
10352 * Schema Document Location Strategy:
10353 * 3 Based on the namespace name, identify an existing schema document,
10354 * either as a resource which is an XML document or a <schema> element
10355 * information item, in some local schema repository;
10356 * 5 Attempt to resolve the namespace name to locate such a resource.
10357 *
10358 * NOTE: (3) and (5) are not supported.
10359 */
10360 if (bkt != NULL) {
10361 relation->bucket = bkt;
10362 goto exit;
10363 }
10364 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10365 importNamespace, 1);
10366
10367 if (bkt != NULL) {
10368 relation->bucket = bkt;
10369 if (bkt->schemaLocation == NULL) {
10370 /* First given location of the schema; load the doc. */
10371 bkt->schemaLocation = schemaLocation;
10372 } else {
10373 if (!xmlStrEqual(schemaLocation,
10374 bkt->schemaLocation)) {
10375 /*
10376 * Additional location given; just skip it.
10377 * URGENT TODO: We should report a warning here.
10378 * res = XML_SCHEMAP_SRC_IMPORT;
10379 */
10380 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10381 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10382 invokingNode, NULL,
10383 "Skipping import of schema located at '%s' for the "
10384 "namespace '%s', since this namespace was already "
10385 "imported with the schema located at '%s'",
10386 schemaLocation, importNamespace, bkt->schemaLocation);
10387 }
10388 goto exit;
10389 }
10390 }
10391 /*
10392 * No bucket + first location: load the doc and create a
10393 * bucket.
10394 */
10395 } else {
10396 /* <include> and <redefine> */
10397 if (bkt != NULL) {
10398
10399 if ((bkt->origTargetNamespace == NULL) &&
10400 (bkt->targetNamespace != sourceTargetNamespace)) {
10401 xmlSchemaBucketPtr chamel;
10402
10403 /*
10404 * Chameleon include/redefine: skip loading only if it was
10405 * aleady build for the targetNamespace of the including
10406 * schema.
10407 */
10408 /*
10409 * URGENT TODO: If the schema is a chameleon-include then copy
10410 * the components into the including schema and modify the
10411 * targetNamespace of those components, do nothing otherwise.
10412 * NOTE: This is currently worked-around by compiling the
10413 * chameleon for every destinct including targetNamespace; thus
10414 * not performant at the moment.
10415 * TODO: Check when the namespace in wildcards for chameleons
10416 * needs to be converted: before we built wildcard intersections
10417 * or after.
10418 * Answer: after!
10419 */
10420 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10421 schemaLocation, sourceTargetNamespace);
10422 if (chamel != NULL) {
10423 /* A fitting chameleon was already parsed; NOP. */
10424 relation->bucket = chamel;
10425 goto exit;
10426 }
10427 /*
10428 * We need to parse the chameleon again for a different
10429 * targetNamespace.
10430 * CHAMELEON TODO: Optimize this by only parsing the
10431 * chameleon once, and then copying the components to
10432 * the new targetNamespace.
10433 */
10434 bkt = NULL;
10435 } else {
10436 relation->bucket = bkt;
10437 goto exit;
10438 }
10439 }
10440 }
10441 if ((bkt != NULL) && (bkt->doc != NULL)) {
10442 PERROR_INT("xmlSchemaAddSchemaDoc",
10443 "trying to load a schema doc, but a doc is already "
10444 "assigned to the schema bucket");
10445 goto exit_failure;
10446 }
10447
10448doc_load:
10449 /*
10450 * Load the document.
10451 */
10452 if (schemaDoc != NULL) {
10453 doc = schemaDoc;
10454 /* Don' free this one, since it was provided by the caller. */
10455 preserveDoc = 1;
10456 /* TODO: Does the context or the doc hold the location? */
10457 if (schemaDoc->URL != NULL)
10458 schemaLocation = xmlDictLookup(pctxt->dict,
10459 schemaDoc->URL, -1);
10460
10461 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10462 xmlParserCtxtPtr parserCtxt;
10463
10464 parserCtxt = xmlNewParserCtxt();
10465 if (parserCtxt == NULL) {
10466 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10467 "allocating a parser context", NULL);
10468 goto exit_failure;
10469 }
10470 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10471 /*
10472 * TODO: Do we have to burden the schema parser dict with all
10473 * the content of the schema doc?
10474 */
10475 xmlDictFree(parserCtxt->dict);
10476 parserCtxt->dict = pctxt->dict;
10477 xmlDictReference(parserCtxt->dict);
10478 }
10479 if (schemaLocation != NULL) {
10480 /* Parse from file. */
10481 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10482 NULL, SCHEMAS_PARSE_OPTIONS);
10483 } else if (schemaBuffer != NULL) {
10484 /* Parse from memory buffer. */
10485 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10486 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10487 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10488 if (doc != NULL)
10489 doc->URL = schemaLocation;
10490 }
10491 /*
10492 * For <import>:
10493 * 2.1 The referent is (a fragment of) a resource which is an
10494 * XML document (see clause 1.1), which in turn corresponds to
10495 * a <schema> element information item in a well-formed information
10496 * set, which in turn corresponds to a valid schema.
10497 * TODO: (2.1) fragments of XML documents are not supported.
10498 *
10499 * 2.2 The referent is a <schema> element information item in
10500 * a well-formed information set, which in turn corresponds
10501 * to a valid schema.
10502 * TODO: (2.2) is not supported.
10503 */
10504 if (doc == NULL) {
10505 xmlErrorPtr lerr;
10506 lerr = xmlGetLastError();
10507 /*
10508 * Check if this a parser error, or if the document could
10509 * just not be located.
10510 * TODO: Try to find specific error codes to react only on
10511 * localisation failures.
10512 */
10513 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10514 /*
10515 * We assume a parser error here.
10516 */
10517 located = 1;
10518 /* TODO: Error code ?? */
10519 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10520 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10521 invokingNode, NULL,
10522 "Failed to parse the XML resource '%s'",
10523 schemaLocation, NULL);
10524 }
10525 }
10526 xmlFreeParserCtxt(parserCtxt);
10527 if ((doc == NULL) && located)
10528 goto exit_error;
10529 } else {
10530 xmlSchemaPErr(pctxt, NULL,
10531 XML_SCHEMAP_NOTHING_TO_PARSE,
10532 "No information for parsing was provided with the "
10533 "given schema parser context.\n",
10534 NULL, NULL);
10535 goto exit_failure;
10536 }
10537 /*
10538 * Preprocess the document.
10539 */
10540 if (doc != NULL) {
10541 xmlNodePtr docElem = NULL;
10542
10543 located = 1;
10544 docElem = xmlDocGetRootElement(doc);
10545 if (docElem == NULL) {
10546 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10547 invokingNode, NULL,
10548 "The document '%s' has no document element",
10549 schemaLocation, NULL);
10550 xmlFreeDoc(doc);
10551 doc = NULL;
10552 goto exit_error;
10553 }
10554 /*
10555 * Remove all the blank text nodes.
10556 */
10557 xmlSchemaCleanupDoc(pctxt, docElem);
10558 /*
10559 * Check the schema's top level element.
10560 */
10561 if (!IS_SCHEMA(docElem, "schema")) {
10562 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10563 invokingNode, NULL,
10564 "The XML document '%s' is not a schema document",
10565 schemaLocation, NULL);
10566 xmlFreeDoc(doc);
10567 doc = NULL;
10568 goto exit_error;
10569 }
10570 /*
10571 * Note that we don't apply a type check for the
10572 * targetNamespace value here.
10573 */
10574 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10575 "targetNamespace");
10576 }
10577
10578/* after_doc_loading: */
10579 if ((bkt == NULL) && located) {
10580 /* Only create a bucket if the schema was located. */
10581 bkt = xmlSchemaBucketCreate(pctxt, type,
10582 targetNamespace);
10583 if (bkt == NULL)
10584 goto exit_failure;
10585 }
10586 if (bkt != NULL) {
10587 bkt->schemaLocation = schemaLocation;
10588 bkt->located = located;
10589 if (doc != NULL) {
10590 bkt->doc = doc;
10591 bkt->targetNamespace = targetNamespace;
10592 bkt->origTargetNamespace = targetNamespace;
10593 if (preserveDoc)
10594 bkt->preserveDoc = 1;
10595 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010596 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010597 bkt->imported++;
10598 /*
10599 * Add it to the graph of schemas.
10600 */
10601 if (relation != NULL)
10602 relation->bucket = bkt;
10603 }
10604
10605exit:
10606 /*
10607 * Return the bucket explicitely; this is needed for the
10608 * main schema.
10609 */
10610 if (bucket != NULL)
10611 *bucket = bkt;
10612 return (0);
10613
10614exit_error:
10615 if ((doc != NULL) && (! preserveDoc)) {
10616 xmlFreeDoc(doc);
10617 if (bkt != NULL)
10618 bkt->doc = NULL;
10619 }
10620 return(pctxt->err);
10621
10622exit_failure:
10623 if ((doc != NULL) && (! preserveDoc)) {
10624 xmlFreeDoc(doc);
10625 if (bkt != NULL)
10626 bkt->doc = NULL;
10627 }
10628 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010629}
10630
William M. Brack2f2a6632004-08-20 23:09:47 +000010631/**
10632 * xmlSchemaParseImport:
10633 * @ctxt: a schema validation context
10634 * @schema: the schema being built
10635 * @node: a subtree containing XML Schema informations
10636 *
10637 * parse a XML schema Import definition
10638 * *WARNING* this interface is highly subject to change
10639 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010640 * Returns 0 in case of success, a positive error code if
10641 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010642 */
10643static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010644xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010645 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010646{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010647 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010648 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10649 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010650 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010651 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010652 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010653
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010654 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010655 return (-1);
10656
10657 /*
10658 * Check for illegal attributes.
10659 */
10660 attr = node->properties;
10661 while (attr != NULL) {
10662 if (attr->ns == NULL) {
10663 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10664 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10665 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010666 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010667 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010668 }
10669 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010670 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010671 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010672 }
10673 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010674 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010675 /*
10676 * Extract and validate attributes.
10677 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010678 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010679 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010680 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010681 xmlSchemaPSimpleTypeErr(pctxt,
10682 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010683 NULL, node,
10684 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010685 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010686 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010687 }
10688
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010689 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010690 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010691 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010692 xmlSchemaPSimpleTypeErr(pctxt,
10693 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010694 NULL, node,
10695 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010696 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010697 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010698 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010699 /*
10700 * And now for the children...
10701 */
10702 child = node->children;
10703 if (IS_SCHEMA(child, "annotation")) {
10704 /*
10705 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010706 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010707 */
10708 child = child->next;
10709 }
10710 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010711 xmlSchemaPContentErr(pctxt,
10712 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010713 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010714 "(annotation?)");
10715 }
10716 /*
10717 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010718 *
10719 * Note that it is important to use the original @targetNamespace
10720 * (or none at all), to rule out imports of schemas _with_ a
10721 * @targetNamespace if the importing schema is a chameleon schema
10722 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010723 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010724 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010725 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010727 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10728 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010729 * targetNamespace [attribute].
10730 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010731 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010732 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010733 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010734 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010735 "The value of the attribute 'namespace' must not match "
10736 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010737 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010738 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010739 }
10740 } else {
10741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010742 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010743 * <schema> must have a targetNamespace [attribute].
10744 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010745 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010746 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010747 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010748 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010749 "The attribute 'namespace' must be existent if "
10750 "the importing schema has no target namespace",
10751 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010752 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010753 }
10754 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010755 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010756 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010757 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010758 if (schemaLocation != NULL)
10759 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10760 schemaLocation, node);
10761 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010762 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010763 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010764
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010765 if (ret != 0)
10766 return(ret);
10767
10768 /*
10769 * For <import>: "It is *not* an error for the application
10770 * schema reference strategy to fail."
10771 * So just don't parse if no schema document was found.
10772 * Note that we will get no bucket if the schema could not be
10773 * located or if there was no schemaLocation.
10774 */
10775 if ((bucket == NULL) && (schemaLocation != NULL)) {
10776 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10777 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10778 node, NULL,
10779 "Failed to locate a schema at location '%s'. "
10780 "Skipping the import", schemaLocation, NULL, NULL);
10781 }
10782
10783 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10784 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10785 }
10786
10787 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010788}
10789
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010790static int
10791xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10792 xmlSchemaPtr schema,
10793 xmlNodePtr node,
10794 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010795 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010796{
10797 xmlAttrPtr attr;
10798
10799 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10800 (schemaLocation == NULL))
10801 return (-1);
10802
10803 *schemaLocation = NULL;
10804 /*
10805 * Check for illegal attributes.
10806 * Applies for both <include> and <redefine>.
10807 */
10808 attr = node->properties;
10809 while (attr != NULL) {
10810 if (attr->ns == NULL) {
10811 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10812 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10813 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010814 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010815 }
10816 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10817 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010818 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010819 }
10820 attr = attr->next;
10821 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010822 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010823 /*
10824 * Preliminary step, extract the URI-Reference and make an URI
10825 * from the base.
10826 */
10827 /*
10828 * Attribute "schemaLocation" is mandatory.
10829 */
10830 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10831 if (attr != NULL) {
10832 xmlChar *base = NULL;
10833 xmlChar *uri = NULL;
10834
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010835 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010836 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10837 (const xmlChar **) schemaLocation) != 0)
10838 goto exit_error;
10839 base = xmlNodeGetBase(node->doc, node);
10840 if (base == NULL) {
10841 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10842 } else {
10843 uri = xmlBuildURI(*schemaLocation, base);
10844 xmlFree(base);
10845 }
10846 if (uri == NULL) {
10847 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10848 "could not build an URI from the schemaLocation")
10849 goto exit_failure;
10850 }
10851 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10852 xmlFree(uri);
10853 } else {
10854 xmlSchemaPMissingAttrErr(pctxt,
10855 XML_SCHEMAP_S4S_ATTR_MISSING,
10856 NULL, node, "schemaLocation", NULL);
10857 goto exit_error;
10858 }
10859 /*
10860 * Report self-inclusion and self-redefinition.
10861 */
10862 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010863 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010864 xmlSchemaPCustomErr(pctxt,
10865 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010866 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010867 "The schema document '%s' cannot redefine itself.",
10868 *schemaLocation);
10869 } else {
10870 xmlSchemaPCustomErr(pctxt,
10871 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010872 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010873 "The schema document '%s' cannot include itself.",
10874 *schemaLocation);
10875 }
10876 goto exit_error;
10877 }
10878
10879 return(0);
10880exit_error:
10881 return(pctxt->err);
10882exit_failure:
10883 return(-1);
10884}
10885
10886static int
10887xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10888 xmlSchemaPtr schema,
10889 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010890 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010891{
10892 xmlNodePtr child = NULL;
10893 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010894 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010895 int isChameleon = 0, wasChameleon = 0;
10896 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010897
10898 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10899 return (-1);
10900
10901 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010902 * Parse attributes. Note that the returned schemaLocation will
10903 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010904 */
10905 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010906 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010907 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010908 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010909 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010910 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010911 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010912 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10913 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010914 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010915 return(res);
10916 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010917 * If we get no schema bucket back, then this means that the schema
10918 * document could not be located or was broken XML or was not
10919 * a schema document.
10920 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010921 if ((bucket == NULL) || (bucket->doc == NULL)) {
10922 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10923 /*
10924 * WARNING for <include>:
10925 * We will raise an error if the schema cannot be located
10926 * for inclusions, since the that was the feedback from the
10927 * schema people. I.e. the following spec piece will *not* be
10928 * satisfied:
10929 * SPEC src-include: "It is not an error for the ·actual value· of the
10930 * schemaLocation [attribute] to fail to resolve it all, in which
10931 * case no corresponding inclusion is performed.
10932 * So do we need a warning report here?"
10933 */
10934 res = XML_SCHEMAP_SRC_INCLUDE;
10935 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10936 node, NULL,
10937 "Failed to load the document '%s' for inclusion",
10938 schemaLocation, NULL);
10939 } else {
10940 /*
10941 * NOTE: This was changed to raise an error even if no redefinitions
10942 * are specified.
10943 *
10944 * SPEC src-redefine (1)
10945 * "If there are any element information items among the [children]
10946 * other than <annotation> then the ·actual value· of the
10947 * schemaLocation [attribute] must successfully resolve."
10948 * TODO: Ask the WG if a the location has always to resolve
10949 * here as well!
10950 */
10951 res = XML_SCHEMAP_SRC_REDEFINE;
10952 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10953 node, NULL,
10954 "Failed to load the document '%s' for redefinition",
10955 schemaLocation, NULL);
10956 }
10957 } else {
10958 /*
10959 * Check targetNamespace sanity before parsing the new schema.
10960 * TODO: Note that we won't check further content if the
10961 * targetNamespace was bad.
10962 */
10963 if (bucket->origTargetNamespace != NULL) {
10964 /*
10965 * SPEC src-include (2.1)
10966 * "SII has a targetNamespace [attribute], and its ·actual
10967 * value· is identical to the ·actual value· of the targetNamespace
10968 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10969 */
10970 if (pctxt->targetNamespace == NULL) {
10971 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10972 XML_SCHEMAP_SRC_INCLUDE,
10973 node, NULL,
10974 "The target namespace of the included/redefined schema "
10975 "'%s' has to be absent, since the including/redefining "
10976 "schema has no target namespace",
10977 schemaLocation, NULL);
10978 goto exit_error;
10979 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10980 pctxt->targetNamespace)) {
10981 /* TODO: Change error function. */
10982 xmlSchemaPCustomErrExt(pctxt,
10983 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010984 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010985 "The target namespace '%s' of the included/redefined "
10986 "schema '%s' differs from '%s' of the "
10987 "including/redefining schema",
10988 bucket->origTargetNamespace, schemaLocation,
10989 pctxt->targetNamespace);
10990 goto exit_error;
10991 }
10992 } else if (pctxt->targetNamespace != NULL) {
10993 /*
10994 * Chameleons: the original target namespace will
10995 * differ from the resulting namespace.
10996 */
10997 isChameleon = 1;
10998 if (bucket->parsed &&
10999 (bucket->targetNamespace != pctxt->targetNamespace)) {
11000 /*
11001 * This is a sanity check, I dunno yet if this can happen.
11002 */
11003 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11004 "trying to use an already parsed schema for a "
11005 "different targetNamespace");
11006 return(-1);
11007 }
11008 bucket->targetNamespace = pctxt->targetNamespace;
11009 }
11010 }
11011 /*
11012 * Parse the schema.
11013 */
11014 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11015 if (isChameleon) {
11016 /* TODO: Get rid of this flag on the schema itself. */
11017 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11018 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11019 } else
11020 wasChameleon = 1;
11021 }
11022 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11023 /* Restore chameleon flag. */
11024 if (isChameleon && (!wasChameleon))
11025 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11026 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011027 /*
11028 * And now for the children...
11029 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011030 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011031 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011032 /*
11033 * Parse (simpleType | complexType | group | attributeGroup))*
11034 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011035 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011036 /*
11037 * How to proceed if the redefined schema was not located?
11038 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011039 pctxt->isRedefine = 1;
11040 while (IS_SCHEMA(child, "annotation") ||
11041 IS_SCHEMA(child, "simpleType") ||
11042 IS_SCHEMA(child, "complexType") ||
11043 IS_SCHEMA(child, "group") ||
11044 IS_SCHEMA(child, "attributeGroup")) {
11045 if (IS_SCHEMA(child, "annotation")) {
11046 /*
11047 * TODO: discard or not?
11048 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011049 } else if (IS_SCHEMA(child, "simpleType")) {
11050 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11051 } else if (IS_SCHEMA(child, "complexType")) {
11052 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011053 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011054 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011055 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011056 xmlSchemaParseModelGroupDefinition(pctxt,
11057 schema, child);
11058 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011059 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011060 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11061 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011062 }
11063 child = child->next;
11064 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011065 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011066 pctxt->isRedefine = 0;
11067 } else {
11068 if (IS_SCHEMA(child, "annotation")) {
11069 /*
11070 * TODO: discard or not?
11071 */
11072 child = child->next;
11073 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011074 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011075 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011076 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011077 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11078 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011079 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011080 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11081 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011082 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011083 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011084 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011085 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011086 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011087 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011088
11089exit_error:
11090 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011091}
11092
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011093static int
11094xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11095 xmlNodePtr node)
11096{
11097 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011098#ifndef ENABLE_REDEFINE
11099 TODO
11100 return(0);
11101#endif
11102 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11103 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011104 if (res != 0)
11105 return(res);
11106 return(0);
11107}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011108
11109static int
11110xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11111 xmlNodePtr node)
11112{
11113 int res;
11114
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011115 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11116 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011117 if (res != 0)
11118 return(res);
11119 return(0);
11120}
11121
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011122/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011123 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011124 * @ctxt: a schema validation context
11125 * @schema: the schema being built
11126 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011127 * @type: the "compositor" type
11128 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011129 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011130 * parse a XML schema Sequence definition.
11131 * Applies parts of:
11132 * Schema Representation Constraint:
11133 * Redefinition Constraints and Semantics (src-redefine)
11134 * (6.1), (6.1.1), (6.1.2)
11135 *
11136 * Schema Component Constraint:
11137 * All Group Limited (cos-all-limited) (2)
11138 * TODO: Actually this should go to component-level checks,
11139 * but is done here due to performance. Move it to an other layer
11140 * is schema construction via an API is implemented.
11141 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011142 * *WARNING* this interface is highly subject to change
11143 *
William M. Bracke7091952004-05-11 15:09:58 +000011144 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011145 * 1 in case of success.
11146 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147static xmlSchemaTreeItemPtr
11148xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11149 xmlNodePtr node, xmlSchemaTypeType type,
11150 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011151{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 xmlSchemaModelGroupPtr item;
11153 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011154 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011155 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011156 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011157
11158 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011159 return (NULL);
11160 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011162 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011163 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 if (item == NULL)
11165 return (NULL);
11166
11167 if (withParticle) {
11168 if (type == XML_SCHEMA_TYPE_ALL) {
11169 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011170 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011171 } else {
11172 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011173 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11174 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11175 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011176 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011177 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11178 /*
11179 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 */
11181 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11182 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011183 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011184 particle->children = (xmlSchemaTreeItemPtr) item;
11185 /*
11186 * Check for illegal attributes.
11187 */
11188 attr = node->properties;
11189 while (attr != NULL) {
11190 if (attr->ns == NULL) {
11191 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11192 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11193 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011194 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 }
11197 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011198 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011199 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011200 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011201 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011202 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 } else {
11204 /*
11205 * Check for illegal attributes.
11206 */
11207 attr = node->properties;
11208 while (attr != NULL) {
11209 if (attr->ns == NULL) {
11210 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011211 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011212 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 }
11214 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011215 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011216 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011217 }
11218 attr = attr->next;
11219 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011220 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011221
William M. Brack2f2a6632004-08-20 23:09:47 +000011222 /*
11223 * Extract and validate attributes.
11224 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011225 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011226 /*
11227 * And now for the children...
11228 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011229 child = node->children;
11230 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011231 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011233 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011234 if (type == XML_SCHEMA_TYPE_ALL) {
11235 xmlSchemaParticlePtr part, last = NULL;
11236
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011237 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011239 schema, child, &isElemRef, 0);
11240 /*
11241 * SPEC cos-all-limited (2)
11242 * "The {max occurs} of all the particles in the {particles}
11243 * of the ('all') group must be 0 or 1.
11244 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011245 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011246 if (isElemRef)
11247 hasRefs++;
11248 if (part->minOccurs > 1) {
11249 xmlSchemaPCustomErr(ctxt,
11250 XML_SCHEMAP_COS_ALL_LIMITED,
11251 NULL, child,
11252 "Invalid value for minOccurs (must be 0 or 1)",
11253 NULL);
11254 /* Reset to 1. */
11255 part->minOccurs = 1;
11256 }
11257 if (part->maxOccurs > 1) {
11258 xmlSchemaPCustomErr(ctxt,
11259 XML_SCHEMAP_COS_ALL_LIMITED,
11260 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011261 "Invalid value for maxOccurs (must be 0 or 1)",
11262 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011263 /* Reset to 1. */
11264 part->maxOccurs = 1;
11265 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 if (last == NULL)
11267 item->children = (xmlSchemaTreeItemPtr) part;
11268 else
11269 last->next = (xmlSchemaTreeItemPtr) part;
11270 last = part;
11271 }
11272 child = child->next;
11273 }
11274 if (child != NULL) {
11275 xmlSchemaPContentErr(ctxt,
11276 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011277 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 "(annotation?, (annotation?, element*)");
11279 }
11280 } else {
11281 /* choice + sequence */
11282 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11283
11284 while ((IS_SCHEMA(child, "element")) ||
11285 (IS_SCHEMA(child, "group")) ||
11286 (IS_SCHEMA(child, "any")) ||
11287 (IS_SCHEMA(child, "choice")) ||
11288 (IS_SCHEMA(child, "sequence"))) {
11289
11290 if (IS_SCHEMA(child, "element")) {
11291 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011292 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11293 if (part && isElemRef)
11294 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011296 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011298 if (part != NULL)
11299 hasRefs++;
11300 /*
11301 * Handle redefinitions.
11302 */
11303 if (ctxt->isRedefine && ctxt->redef &&
11304 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11305 part && part->children)
11306 {
11307 if ((xmlSchemaGetQNameRefName(part->children) ==
11308 ctxt->redef->refName) &&
11309 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11310 ctxt->redef->refTargetNs))
11311 {
11312 /*
11313 * SPEC src-redefine:
11314 * (6.1) "If it has a <group> among its contents at
11315 * some level the ·actual value· of whose ref
11316 * [attribute] is the same as the ·actual value· of
11317 * its own name attribute plus target namespace, then
11318 * all of the following must be true:"
11319 * (6.1.1) "It must have exactly one such group."
11320 */
11321 if (ctxt->redefCounter != 0) {
11322 xmlChar *str = NULL;
11323
11324 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11325 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11326 "The redefining model group definition "
11327 "'%s' must not contain more than one "
11328 "reference to the redefined definition",
11329 xmlSchemaFormatQName(&str,
11330 ctxt->redef->refTargetNs,
11331 ctxt->redef->refName),
11332 NULL);
11333 FREE_AND_NULL(str)
11334 part = NULL;
11335 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11336 ((WXS_PARTICLE(part))->maxOccurs != 1))
11337 {
11338 xmlChar *str = NULL;
11339 /*
11340 * SPEC src-redefine:
11341 * (6.1.2) "The ·actual value· of both that
11342 * group's minOccurs and maxOccurs [attribute]
11343 * must be 1 (or ·absent·).
11344 */
11345 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11346 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11347 "The redefining model group definition "
11348 "'%s' must not contain a reference to the "
11349 "redefined definition with a "
11350 "maxOccurs/minOccurs other than 1",
11351 xmlSchemaFormatQName(&str,
11352 ctxt->redef->refTargetNs,
11353 ctxt->redef->refName),
11354 NULL);
11355 FREE_AND_NULL(str)
11356 part = NULL;
11357 }
11358 ctxt->redef->reference = WXS_BASIC_CAST part;
11359 ctxt->redefCounter++;
11360 }
11361 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011363 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011364 xmlSchemaParseAny(ctxt, schema, child);
11365 } else if (IS_SCHEMA(child, "choice")) {
11366 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11367 XML_SCHEMA_TYPE_CHOICE, 1);
11368 } else if (IS_SCHEMA(child, "sequence")) {
11369 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11370 XML_SCHEMA_TYPE_SEQUENCE, 1);
11371 }
11372 if (part != NULL) {
11373 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011374 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011375 else
11376 last->next = part;
11377 last = part;
11378 }
11379 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011380 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011381 if (child != NULL) {
11382 xmlSchemaPContentErr(ctxt,
11383 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011384 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011385 "(annotation?, (element | group | choice | sequence | any)*)");
11386 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011387 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011388 if ((max == 0) && (min == 0))
11389 return (NULL);
11390 if (hasRefs) {
11391 /*
11392 * We need to resolve references.
11393 */
11394 WXS_ADD_PENDING(ctxt, item);
11395 }
11396 if (withParticle)
11397 return ((xmlSchemaTreeItemPtr) particle);
11398 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011399 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011400}
11401
11402/**
11403 * xmlSchemaParseRestriction:
11404 * @ctxt: a schema validation context
11405 * @schema: the schema being built
11406 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011407 *
11408 * parse a XML schema Restriction definition
11409 * *WARNING* this interface is highly subject to change
11410 *
11411 * Returns the type definition or NULL in case of error
11412 */
11413static xmlSchemaTypePtr
11414xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011415 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011416{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011417 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011418 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011419 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011420
11421 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11422 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011423 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011424 type = ctxt->ctxtType;
11425 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011426
11427 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011428 * Check for illegal attributes.
11429 */
11430 attr = node->properties;
11431 while (attr != NULL) {
11432 if (attr->ns == NULL) {
11433 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11434 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011436 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 }
11438 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011439 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011440 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011441 }
11442 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011443 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011444 /*
11445 * Extract and validate attributes.
11446 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011447 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011448 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011449 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011450 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011451 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011452 * Extract the base type. The "base" attribute is mandatory if inside
11453 * a complex type or if redefining.
11454 *
11455 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011456 * among its [children]), the simple type definition which is
11457 * the {content type} of the type definition ·resolved· to by
11458 * the ·actual value· of the base [attribute]"
11459 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011460 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011461 &(type->baseNs), &(type->base)) == 0)
11462 {
11463 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11464 xmlSchemaPMissingAttrErr(ctxt,
11465 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011466 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011467 } else if ((ctxt->isRedefine) &&
11468 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11469 {
11470 if (type->base == NULL) {
11471 xmlSchemaPMissingAttrErr(ctxt,
11472 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011473 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011474 } else if ((! xmlStrEqual(type->base, type->name)) ||
11475 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11476 {
11477 xmlChar *str1 = NULL, *str2 = NULL;
11478 /*
11479 * REDEFINE: SPEC src-redefine (5)
11480 * "Within the [children], each <simpleType> must have a
11481 * <restriction> among its [children] ... the ·actual value· of
11482 * whose base [attribute] must be the same as the ·actual value·
11483 * of its own name attribute plus target namespace;"
11484 */
11485 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011486 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011487 "value '%s' of the 'base' attribute does not match the "
11488 "type's designation '%s'",
11489 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11490 xmlSchemaFormatQName(&str1, type->targetNamespace,
11491 type->name), NULL);
11492 FREE_AND_NULL(str1);
11493 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011494 /* Avoid confusion and erase the values. */
11495 type->base = NULL;
11496 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011497 }
11498 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011499 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011500 /*
11501 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011502 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011503 child = node->children;
11504 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011505 /*
11506 * Add the annotation to the simple type ancestor.
11507 */
11508 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011509 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011510 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011511 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011512 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11513 /*
11514 * Corresponds to <simpleType><restriction><simpleType>.
11515 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011516 if (IS_SCHEMA(child, "simpleType")) {
11517 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011519 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011520 * Either the base [attribute] or the simpleType [child] of the
11521 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011522 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011524 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011525 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011526 "The attribute 'base' and the <simpleType> child are "
11527 "mutually exclusive", NULL);
11528 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011529 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011530 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011531 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011532 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011533 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011534 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011536 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011537 "Either the attribute 'base' or a <simpleType> child "
11538 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011539 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11541 /*
11542 * Corresponds to <complexType><complexContent><restriction>...
11543 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011544 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 * Model groups <all>, <choice> and <sequence>.
11546 */
11547 if (IS_SCHEMA(child, "all")) {
11548 type->subtypes = (xmlSchemaTypePtr)
11549 xmlSchemaParseModelGroup(ctxt, schema, child,
11550 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011551 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011552 } else if (IS_SCHEMA(child, "choice")) {
11553 type->subtypes = (xmlSchemaTypePtr)
11554 xmlSchemaParseModelGroup(ctxt,
11555 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11556 child = child->next;
11557 } else if (IS_SCHEMA(child, "sequence")) {
11558 type->subtypes = (xmlSchemaTypePtr)
11559 xmlSchemaParseModelGroup(ctxt, schema, child,
11560 XML_SCHEMA_TYPE_SEQUENCE, 1);
11561 child = child->next;
11562 /*
11563 * Model group reference <group>.
11564 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011565 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011566 type->subtypes = (xmlSchemaTypePtr)
11567 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011568 /*
11569 * Note that the reference will be resolved in
11570 * xmlSchemaResolveTypeReferences();
11571 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011572 child = child->next;
11573 }
11574 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 /*
11576 * Corresponds to <complexType><simpleContent><restriction>...
11577 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011578 * "1.1 the simple type definition corresponding to the <simpleType>
11579 * among the [children] of <restriction> if there is one;"
11580 */
11581 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011582 /*
11583 * We will store the to-be-restricted simple type in
11584 * type->contentTypeDef *temporarily*.
11585 */
11586 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 if ( type->contentTypeDef == NULL)
11589 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011590 child = child->next;
11591 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011592 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593
11594 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011597 /*
11598 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011600 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011601
Daniel Veillard01fa6152004-06-29 17:04:39 +000011602 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011603 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011604 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011605 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011606 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11607 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011608 * *Single Facet Value*
11609 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011610 while ((IS_SCHEMA(child, "minInclusive")) ||
11611 (IS_SCHEMA(child, "minExclusive")) ||
11612 (IS_SCHEMA(child, "maxInclusive")) ||
11613 (IS_SCHEMA(child, "maxExclusive")) ||
11614 (IS_SCHEMA(child, "totalDigits")) ||
11615 (IS_SCHEMA(child, "fractionDigits")) ||
11616 (IS_SCHEMA(child, "pattern")) ||
11617 (IS_SCHEMA(child, "enumeration")) ||
11618 (IS_SCHEMA(child, "whiteSpace")) ||
11619 (IS_SCHEMA(child, "length")) ||
11620 (IS_SCHEMA(child, "maxLength")) ||
11621 (IS_SCHEMA(child, "minLength"))) {
11622 facet = xmlSchemaParseFacet(ctxt, schema, child);
11623 if (facet != NULL) {
11624 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011625 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011626 else
11627 lastfacet->next = facet;
11628 lastfacet = facet;
11629 lastfacet->next = NULL;
11630 }
11631 child = child->next;
11632 }
11633 /*
11634 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011635 */
11636 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011637 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11638
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011639 facet = type->facets;
11640 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011641 facetLink = (xmlSchemaFacetLinkPtr)
11642 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011644 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011645 xmlFree(facetLink);
11646 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011647 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 facetLink->facet = facet;
11649 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011650 if (lastFacetLink == NULL)
11651 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652 else
11653 lastFacetLink->next = facetLink;
11654 lastFacetLink = facetLink;
11655 facet = facet->next;
11656 } while (facet != NULL);
11657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011658 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011659 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11660 /*
11661 * Attribute uses/declarations.
11662 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011663 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11664 (xmlSchemaItemListPtr *) &(type->attrUses),
11665 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11666 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011667 /*
11668 * Attribute wildcard.
11669 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011670 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011671 type->attributeWildcard =
11672 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011673 child = child->next;
11674 }
11675 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011676 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011677 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11678 xmlSchemaPContentErr(ctxt,
11679 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011680 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011681 "annotation?, (group | all | choice | sequence)?, "
11682 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011683 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011684 xmlSchemaPContentErr(ctxt,
11685 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011686 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011687 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11688 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11689 "length | minLength | maxLength | enumeration | whiteSpace | "
11690 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11691 } else {
11692 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693 xmlSchemaPContentErr(ctxt,
11694 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011695 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011696 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11697 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11698 "length | minLength | maxLength | enumeration | whiteSpace | "
11699 "pattern)*))");
11700 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011701 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011702 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011703}
11704
11705/**
11706 * xmlSchemaParseExtension:
11707 * @ctxt: a schema validation context
11708 * @schema: the schema being built
11709 * @node: a subtree containing XML Schema informations
11710 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011711 * Parses an <extension>, which is found inside a
11712 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011713 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011714 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011715 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011716 */
11717static xmlSchemaTypePtr
11718xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011719 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011720{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011722 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011723 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011724
11725 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11726 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011727 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011728 type = ctxt->ctxtType;
11729 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011730
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011731 /*
11732 * Check for illegal attributes.
11733 */
11734 attr = node->properties;
11735 while (attr != NULL) {
11736 if (attr->ns == NULL) {
11737 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11738 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011739 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011740 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011741 }
11742 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011743 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 }
11746 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011747 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011748
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011749 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011750
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011751 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011752 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011753 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011754 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11755 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011756 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011757 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011758 XML_SCHEMAP_S4S_ATTR_MISSING,
11759 NULL, node, "base", NULL);
11760 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011761 /*
11762 * And now for the children...
11763 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011764 child = node->children;
11765 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011766 /*
11767 * Add the annotation to the type ancestor.
11768 */
11769 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011770 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011771 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011772 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011773 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11774 /*
11775 * Corresponds to <complexType><complexContent><extension>... and:
11776 *
11777 * Model groups <all>, <choice>, <sequence> and <group>.
11778 */
11779 if (IS_SCHEMA(child, "all")) {
11780 type->subtypes = (xmlSchemaTypePtr)
11781 xmlSchemaParseModelGroup(ctxt, schema,
11782 child, XML_SCHEMA_TYPE_ALL, 1);
11783 child = child->next;
11784 } else if (IS_SCHEMA(child, "choice")) {
11785 type->subtypes = (xmlSchemaTypePtr)
11786 xmlSchemaParseModelGroup(ctxt, schema,
11787 child, XML_SCHEMA_TYPE_CHOICE, 1);
11788 child = child->next;
11789 } else if (IS_SCHEMA(child, "sequence")) {
11790 type->subtypes = (xmlSchemaTypePtr)
11791 xmlSchemaParseModelGroup(ctxt, schema,
11792 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11793 child = child->next;
11794 } else if (IS_SCHEMA(child, "group")) {
11795 type->subtypes = (xmlSchemaTypePtr)
11796 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011797 /*
11798 * Note that the reference will be resolved in
11799 * xmlSchemaResolveTypeReferences();
11800 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011801 child = child->next;
11802 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011803 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011804 if (child != NULL) {
11805 /*
11806 * Attribute uses/declarations.
11807 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011808 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11809 (xmlSchemaItemListPtr *) &(type->attrUses),
11810 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11811 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011812 /*
11813 * Attribute wildcard.
11814 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011815 if (IS_SCHEMA(child, "anyAttribute")) {
11816 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011817 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11818 child = child->next;
11819 }
11820 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011821 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011822 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11823 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824 xmlSchemaPContentErr(ctxt,
11825 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011826 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011827 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011828 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011829 } else {
11830 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011831 xmlSchemaPContentErr(ctxt,
11832 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011833 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011834 "(annotation?, ((attribute | attributeGroup)*, "
11835 "anyAttribute?))");
11836 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011837 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011838 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011839}
11840
11841/**
11842 * xmlSchemaParseSimpleContent:
11843 * @ctxt: a schema validation context
11844 * @schema: the schema being built
11845 * @node: a subtree containing XML Schema informations
11846 *
11847 * parse a XML schema SimpleContent definition
11848 * *WARNING* this interface is highly subject to change
11849 *
11850 * Returns the type definition or NULL in case of error
11851 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011852static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011853xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011854 xmlSchemaPtr schema, xmlNodePtr node,
11855 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011856{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011857 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011858 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011859 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011860
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011861 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11862 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011863 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011864 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011865 /* Not a component, don't create it. */
11866 type = ctxt->ctxtType;
11867 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11868 /*
11869 * Check for illegal attributes.
11870 */
11871 attr = node->properties;
11872 while (attr != NULL) {
11873 if (attr->ns == NULL) {
11874 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011875 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011876 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011877 }
11878 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011879 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011880 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011881 }
11882 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011883 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011884
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011885 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011886
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011887 /*
11888 * And now for the children...
11889 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011890 child = node->children;
11891 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011892 /*
11893 * Add the annotation to the complex type ancestor.
11894 */
11895 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011896 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011897 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011898 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011899 if (child == NULL) {
11900 xmlSchemaPContentErr(ctxt,
11901 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011902 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011903 "(annotation?, (restriction | extension))");
11904 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011905 if (child == NULL) {
11906 xmlSchemaPContentErr(ctxt,
11907 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011908 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011909 "(annotation?, (restriction | extension))");
11910 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011911 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011912 xmlSchemaParseRestriction(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 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011917 xmlSchemaParseExtension(ctxt, schema, child,
11918 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011919 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011920 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011921 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011922 if (child != NULL) {
11923 xmlSchemaPContentErr(ctxt,
11924 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011925 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011926 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011927 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011928 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011929}
11930
11931/**
11932 * xmlSchemaParseComplexContent:
11933 * @ctxt: a schema validation context
11934 * @schema: the schema being built
11935 * @node: a subtree containing XML Schema informations
11936 *
11937 * parse a XML schema ComplexContent definition
11938 * *WARNING* this interface is highly subject to change
11939 *
11940 * Returns the type definition or NULL in case of error
11941 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011942static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011943xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011944 xmlSchemaPtr schema, xmlNodePtr node,
11945 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011946{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011947 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011948 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011949 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011950
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011951 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11952 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011953 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011954 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011955 /* Not a component, don't create it. */
11956 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011957 /*
11958 * Check for illegal attributes.
11959 */
11960 attr = node->properties;
11961 while (attr != NULL) {
11962 if (attr->ns == NULL) {
11963 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011965 {
11966 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011967 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011968 }
11969 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11970 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011971 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011972 }
11973 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011974 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011975
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011976 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011977
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011978 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011979 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011980 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011981 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011982 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11983 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011984 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011985 child = node->children;
11986 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011987 /*
11988 * Add the annotation to the complex type ancestor.
11989 */
11990 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011991 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011992 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011993 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011994 if (child == NULL) {
11995 xmlSchemaPContentErr(ctxt,
11996 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011997 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011998 NULL, "(annotation?, (restriction | extension))");
11999 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012000 if (child == NULL) {
12001 xmlSchemaPContentErr(ctxt,
12002 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012003 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012004 NULL, "(annotation?, (restriction | extension))");
12005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012006 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012007 xmlSchemaParseRestriction(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 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012012 xmlSchemaParseExtension(ctxt, schema, child,
12013 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012014 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012015 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012016 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012017 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012018 xmlSchemaPContentErr(ctxt,
12019 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012020 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012021 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012022 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012023 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012024}
12025
12026/**
12027 * xmlSchemaParseComplexType:
12028 * @ctxt: a schema validation context
12029 * @schema: the schema being built
12030 * @node: a subtree containing XML Schema informations
12031 *
12032 * parse a XML schema Complex Type definition
12033 * *WARNING* this interface is highly subject to change
12034 *
12035 * Returns the type definition or NULL in case of error
12036 */
12037static xmlSchemaTypePtr
12038xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012039 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012040{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012041 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012042 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012043 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012044 xmlAttrPtr attr;
12045 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012046#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012047 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012048#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012049 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012050
Daniel Veillard4255d502002-04-16 15:50:10 +000012051
12052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12053 return (NULL);
12054
Daniel Veillard01fa6152004-06-29 17:04:39 +000012055 ctxtType = ctxt->ctxtType;
12056
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012057 if (topLevel) {
12058 attr = xmlSchemaGetPropNode(node, "name");
12059 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012060 xmlSchemaPMissingAttrErr(ctxt,
12061 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012062 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012063 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012064 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12065 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012066 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012068
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012069 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012070 /*
12071 * Parse as local complex type definition.
12072 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012073#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012074 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012075 type = xmlSchemaAddType(ctxt, schema,
12076 XML_SCHEMA_TYPE_COMPLEX,
12077 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012078 ctxt->targetNamespace, node, 0);
12079#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012080 type = xmlSchemaAddType(ctxt, schema,
12081 XML_SCHEMA_TYPE_COMPLEX,
12082 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012083#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012084 if (type == NULL)
12085 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012086 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012087 type->node = node;
12088 type->type = XML_SCHEMA_TYPE_COMPLEX;
12089 /*
12090 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012091 */
12092 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012093 /*
12094 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012095 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012096 type = xmlSchemaAddType(ctxt, schema,
12097 XML_SCHEMA_TYPE_COMPLEX,
12098 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012099 if (type == NULL)
12100 return (NULL);
12101 type->node = node;
12102 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012103 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012104 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012105 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012106 /*
12107 * Handle attributes.
12108 */
12109 attr = node->properties;
12110 while (attr != NULL) {
12111 if (attr->ns == NULL) {
12112 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12113 /*
12114 * Attribute "id".
12115 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012116 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012117 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12118 /*
12119 * Attribute "mixed".
12120 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012121 if (xmlSchemaPGetBoolNodeValue(ctxt,
12122 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12124 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012125 /*
12126 * Attributes of global complex type definitions.
12127 */
12128 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12129 /* Pass. */
12130 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12131 /*
12132 * Attribute "abstract".
12133 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012134 if (xmlSchemaPGetBoolNodeValue(ctxt,
12135 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012136 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12137 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12138 /*
12139 * Attribute "final".
12140 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012141 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012142 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012143 if (xmlSchemaPValAttrBlockFinal(attrValue,
12144 &(type->flags),
12145 -1,
12146 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12147 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12148 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012149 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012150 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012152 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012154 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155 } else
12156 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012157 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12158 /*
12159 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012160 */
12161 attrValue = xmlSchemaGetNodeContent(ctxt,
12162 (xmlNodePtr) attr);
12163 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012164 -1,
12165 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012167 -1, -1, -1) != 0) {
12168 xmlSchemaPSimpleTypeErr(ctxt,
12169 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012170 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012171 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012172 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012173 } else
12174 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012175 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012176 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012178 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012179 } else {
12180 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012181 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012182 }
12183 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012184 xmlSchemaPIllegalAttrErr(ctxt,
12185 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012186 }
12187 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012188 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012190 /*
12191 * Apply default "block" values.
12192 */
12193 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12194 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12195 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12196 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12197 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012198 if (! final) {
12199 /*
12200 * Apply default "block" values.
12201 */
12202 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12203 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12204 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12205 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12206 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012207 /*
12208 * And now for the children...
12209 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012210 child = node->children;
12211 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012212 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012214 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012215 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012216 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012218 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012219 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012220 * Specifying mixed='true' when the <simpleContent>
12221 * alternative is chosen has no effect
12222 */
William M. Bracke7091952004-05-11 15:09:58 +000012223 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12224 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012225 xmlSchemaParseSimpleContent(ctxt, schema, child,
12226 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012227 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012228 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012229 /*
12230 * <complexType><complexContent>...
12231 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012232 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012233 xmlSchemaParseComplexContent(ctxt, schema, child,
12234 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012235 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012236 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012237 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012238 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12239 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012240 * SPEC
12241 * "...the third alternative (neither <simpleContent> nor
12242 * <complexContent>) is chosen. This case is understood as shorthand
12243 * for complex content restricting the ·ur-type definition·, and the
12244 * details of the mappings should be modified as necessary.
12245 */
12246 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12247 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012248 /*
12249 * Parse model groups.
12250 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012251 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012252 type->subtypes = (xmlSchemaTypePtr)
12253 xmlSchemaParseModelGroup(ctxt, schema, child,
12254 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012255 child = child->next;
12256 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012257 type->subtypes = (xmlSchemaTypePtr)
12258 xmlSchemaParseModelGroup(ctxt, schema, child,
12259 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012260 child = child->next;
12261 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012262 type->subtypes = (xmlSchemaTypePtr)
12263 xmlSchemaParseModelGroup(ctxt, schema, child,
12264 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012265 child = child->next;
12266 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012267 type->subtypes = (xmlSchemaTypePtr)
12268 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012269 /*
12270 * Note that the reference will be resolved in
12271 * xmlSchemaResolveTypeReferences();
12272 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012273 child = child->next;
12274 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012275 /*
12276 * Parse attribute decls/refs.
12277 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012278 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12279 (xmlSchemaItemListPtr *) &(type->attrUses),
12280 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12281 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012282 /*
12283 * Parse attribute wildcard.
12284 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012286 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12287 child = child->next;
12288 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012289 }
12290 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012291 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012293 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012294 NULL, "(annotation?, (simpleContent | complexContent | "
12295 "((group | all | choice | sequence)?, ((attribute | "
12296 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012297 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012298 /*
12299 * REDEFINE: SPEC src-redefine (5)
12300 */
12301 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12302 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012303 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012304 "<complexType> must have a <restriction> or <extension> "
12305 "grand-child", NULL);
12306 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012307 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012308 return (type);
12309}
12310
Daniel Veillard4255d502002-04-16 15:50:10 +000012311/************************************************************************
12312 * *
12313 * Validating using Schemas *
12314 * *
12315 ************************************************************************/
12316
12317/************************************************************************
12318 * *
12319 * Reading/Writing Schemas *
12320 * *
12321 ************************************************************************/
12322
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012323#if 0 /* Will be enabled if it is clear what options are needed. */
12324/**
12325 * xmlSchemaParserCtxtSetOptions:
12326 * @ctxt: a schema parser context
12327 * @options: a combination of xmlSchemaParserOption
12328 *
12329 * Sets the options to be used during the parse.
12330 *
12331 * Returns 0 in case of success, -1 in case of an
12332 * API error.
12333 */
12334static int
12335xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12336 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012337
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012338{
12339 int i;
12340
12341 if (ctxt == NULL)
12342 return (-1);
12343 /*
12344 * WARNING: Change the start value if adding to the
12345 * xmlSchemaParseOption.
12346 */
12347 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12348 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012349 return (-1);
12350 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012351 }
12352 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012353 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012354}
12355
12356/**
12357 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012358 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012359 *
12360 * Returns the option combination of the parser context.
12361 */
12362static int
12363xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012364
12365{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012366 if (ctxt == NULL)
12367 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012368 else
12369 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012370}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012371#endif
12372
Daniel Veillard4255d502002-04-16 15:50:10 +000012373/**
12374 * xmlSchemaNewParserCtxt:
12375 * @URL: the location of the schema
12376 *
12377 * Create an XML Schemas parse context for that file/resource expected
12378 * to contain an XML Schemas file.
12379 *
12380 * Returns the parser context or NULL in case of error
12381 */
12382xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012383xmlSchemaNewParserCtxt(const char *URL)
12384{
Daniel Veillard4255d502002-04-16 15:50:10 +000012385 xmlSchemaParserCtxtPtr ret;
12386
12387 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012388 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012389
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012390 ret = xmlSchemaParserCtxtCreate();
12391 if (ret == NULL)
12392 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012393 ret->dict = xmlDictCreate();
12394 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012395 return (ret);
12396}
12397
12398/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012399 * xmlSchemaNewMemParserCtxt:
12400 * @buffer: a pointer to a char array containing the schemas
12401 * @size: the size of the array
12402 *
12403 * Create an XML Schemas parse context for that memory buffer expected
12404 * to contain an XML Schemas file.
12405 *
12406 * Returns the parser context or NULL in case of error
12407 */
12408xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012409xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12410{
Daniel Veillard6045c902002-10-09 21:13:59 +000012411 xmlSchemaParserCtxtPtr ret;
12412
12413 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012414 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012415 ret = xmlSchemaParserCtxtCreate();
12416 if (ret == NULL)
12417 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012418 ret->buffer = buffer;
12419 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012420 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012421 return (ret);
12422}
12423
12424/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012425 * xmlSchemaNewDocParserCtxt:
12426 * @doc: a preparsed document tree
12427 *
12428 * Create an XML Schemas parse context for that document.
12429 * NB. The document may be modified during the parsing process.
12430 *
12431 * Returns the parser context or NULL in case of error
12432 */
12433xmlSchemaParserCtxtPtr
12434xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12435{
12436 xmlSchemaParserCtxtPtr ret;
12437
12438 if (doc == NULL)
12439 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012440 ret = xmlSchemaParserCtxtCreate();
12441 if (ret == NULL)
12442 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012443 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012444 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012445 /* The application has responsibility for the document */
12446 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012447
12448 return (ret);
12449}
12450
12451/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012452 * xmlSchemaFreeParserCtxt:
12453 * @ctxt: the schema parser context
12454 *
12455 * Free the resources associated to the schema parser context
12456 */
12457void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012458xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12459{
Daniel Veillard4255d502002-04-16 15:50:10 +000012460 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012461 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012462 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012463 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012464 if (ctxt->vctxt != NULL) {
12465 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12466 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012467 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12468 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12469 ctxt->constructor = NULL;
12470 ctxt->ownsConstructor = 0;
12471 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012472 if (ctxt->attrProhibs != NULL)
12473 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012474 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012475 xmlFree(ctxt);
12476}
12477
12478/************************************************************************
12479 * *
12480 * Building the content models *
12481 * *
12482 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012483
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012484static void
12485xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012486 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012487{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012488 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012489 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012490 xmlSchemaSubstGroupPtr substGroup;
12491 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012492
12493 elemDecl = (xmlSchemaElementPtr) particle->children;
12494 /*
12495 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012496 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012497 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012498 if (end == NULL)
12499 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012500 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012501 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012502 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012503 XML_SCHEMAP_INTERNAL,
12504 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12505 "declaration is marked having a subst. group but none "
12506 "available.\n", elemDecl->name, NULL);
12507 return;
12508 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012509 if (counter >= 0) {
12510 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012511 * NOTE that we put the declaration in, even if it's abstract.
12512 * However, an error will be raised during *validation* if an element
12513 * information item shall be validated against an abstract element
12514 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012515 */
12516 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12517 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12518 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12519 /*
12520 * Add subst. group members.
12521 */
12522 for (i = 0; i < substGroup->members->nbItems; i++) {
12523 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12524 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12525 member->name, member->targetNamespace, member);
12526 }
12527 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012528 /*
12529 * NOTE that we put the declaration in, even if it's abstract,
12530 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012531 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012532 xmlAutomataNewTransition2(pctxt->am,
12533 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012534 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12535 /*
12536 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012537 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012538 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012539 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012540 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12541 member->name, member->targetNamespace,
12542 1, 1, member);
12543 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012544 }
12545 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012546 xmlAutomataStatePtr hop;
12547 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12548 UNBOUNDED : particle->maxOccurs - 1;
12549 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12550
12551 counter =
12552 xmlAutomataNewCounter(pctxt->am, minOccurs,
12553 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012555
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012557 xmlAutomataNewTransition2(pctxt->am,
12558 start, NULL,
12559 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012560 hop);
12561 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012562 * Add subst. group members.
12563 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012564 for (i = 0; i < substGroup->members->nbItems; i++) {
12565 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12566 xmlAutomataNewEpsilon(pctxt->am,
12567 xmlAutomataNewTransition2(pctxt->am,
12568 start, NULL,
12569 member->name, member->targetNamespace, member),
12570 hop);
12571 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012572 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12573 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12574 }
12575 if (particle->minOccurs == 0)
12576 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012577 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012578}
12579
12580static void
12581xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12582 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012584 if (((xmlSchemaElementPtr) particle->children)->flags &
12585 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012586 /*
12587 * Substitution groups.
12588 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012589 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012590 } else {
12591 xmlSchemaElementPtr elemDecl;
12592 xmlAutomataStatePtr start;
12593
12594 elemDecl = (xmlSchemaElementPtr) particle->children;
12595
12596 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012597 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012598 if (particle->maxOccurs == 1) {
12599 start = ctxt->state;
12600 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012601 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12602 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12603 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012604 /* Special case. */
12605 start = ctxt->state;
12606 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12607 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012609 } else {
12610 int counter;
12611 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12612 UNBOUNDED : particle->maxOccurs - 1;
12613 int minOccurs = particle->minOccurs < 1 ?
12614 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012615
12616 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012617 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12618 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12619 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12620 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12621 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12622 NULL, counter);
12623 }
12624 if (particle->minOccurs == 0)
12625 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12626 }
12627}
12628
Daniel Veillard4255d502002-04-16 15:50:10 +000012629/**
12630 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012631 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012632 * @particle: the particle component
12633 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012634 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012635 * Create the automaton for the {content type} of a complex type.
12636 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012637 */
12638static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012639xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012640 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012641{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012642 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012643 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012644 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012645 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012646 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012647 /*
12648 * Just return in this case. A missing "term" of the particle
12649 * might arise due to an invalid "term" component.
12650 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012651 return;
12652 }
12653
12654 switch (particle->children->type) {
12655 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012656 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012657 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012658 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012659
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012660 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012661
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012662 start = pctxt->state;
12663 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012664
12665 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012666 if (wild->any == 1) {
12667 /*
12668 * We need to add both transitions:
12669 *
12670 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012671 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012672 pctxt->state =
12673 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012674 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012675 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 /*
12677 * 2. the {"*"} for elements in no namespace.
12678 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012679 pctxt->state =
12680 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012681 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012682 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012683
12684 } else if (wild->nsSet != NULL) {
12685 ns = wild->nsSet;
12686 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012687 pctxt->state = start;
12688 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12689 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12690 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012691 ns = ns->next;
12692 } while (ns != NULL);
12693
12694 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012695 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12696 start, end, BAD_CAST "*", wild->negNsSet->value,
12697 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012698 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699 } else {
12700 int counter;
12701 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012703 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012704 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012705 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012706
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012707 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12708 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012709 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012710 pctxt->state =
12711 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012712 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012713 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12714 pctxt->state =
12715 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012716 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012717 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012719 ns = wild->nsSet;
12720 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012721 pctxt->state =
12722 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012723 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012724 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012725 ns = ns->next;
12726 } while (ns != NULL);
12727
12728 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012729 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012730 start, hop, BAD_CAST "*", wild->negNsSet->value,
12731 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012732 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012733 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12734 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012735 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012736 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012738 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012739 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012740 break;
12741 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012742 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012743 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012744 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012745 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012746 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012747
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012748 /*
12749 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012750 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012751 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012752 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12753 sub = particle->children->children;
12754 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012755 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012756 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012757 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012758 }
12759 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012760 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012761
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012762 if (particle->maxOccurs >= UNBOUNDED) {
12763 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012764 xmlAutomataStatePtr tmp;
12765 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012766
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012767 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012768 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012769 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012770
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012771 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012772 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012773
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012774 sub = particle->children->children;
12775 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012776 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012777 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012778 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012779 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012780 tmp = pctxt->state;
12781 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012782 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012783 pctxt->state =
12784 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012785 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012786
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012787 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012788 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012789 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012790 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012791
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012792 sub = particle->children->children;
12793 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012794 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012795 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012796 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012797 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012798 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012799 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012800 /*
12801 * epsilon needed to block previous trans from
12802 * being allowed to enter back from another
12803 * construct
12804 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012805 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12806 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012807 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012808 xmlAutomataNewEpsilon(pctxt->am,
12809 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012810 }
12811 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012812 } else if ((particle->maxOccurs > 1)
12813 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012814 xmlAutomataStatePtr tmp;
12815 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012816
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012817 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012818 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012819 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012820
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012821 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012822 particle->minOccurs - 1,
12823 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012824
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012825 sub = particle->children->children;
12826 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012827 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012828 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012829 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012830 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012831 tmp = pctxt->state;
12832 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012833 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012834 pctxt->state =
12835 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012836 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012837 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012838 xmlAutomataNewEpsilon(pctxt->am,
12839 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012840 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012841 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012842 sub = particle->children->children;
12843 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012844 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012845 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012846 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012847 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012848 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012849 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12850 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012851 }
12852 }
12853 }
12854 break;
12855 }
12856 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012857 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012858 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012859
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012860 start = pctxt->state;
12861 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012862
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012863 /*
12864 * iterate over the subtypes and remerge the end with an
12865 * epsilon transition
12866 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012867 if (particle->maxOccurs == 1) {
12868 sub = particle->children->children;
12869 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012870 pctxt->state = start;
12871 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012872 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012873 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012874 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012875 }
12876 } else {
12877 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012878 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012879 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12880 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012881 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012882 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012883
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012884 /*
12885 * use a counter to keep track of the number of transtions
12886 * which went through the choice.
12887 */
12888 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012889 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12890 hop = xmlAutomataNewState(pctxt->am);
12891 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012892
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012893 sub = particle->children->children;
12894 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012895 pctxt->state = base;
12896 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012897 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012898 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012899 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012900 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012901 xmlAutomataNewEpsilon(pctxt->am, start, base);
12902 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12903 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012904 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012905 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012906 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012907 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012908 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012909 break;
12910 }
12911 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012912 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012913 xmlSchemaParticlePtr sub;
12914 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012915 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012916
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012917 sub = (xmlSchemaParticlePtr) particle->children->children;
12918 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012919 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012920 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012922 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012923
12924 elemDecl = (xmlSchemaElementPtr) sub->children;
12925 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012926 PERROR_INT("xmlSchemaBuildAContentModel",
12927 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012928 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012929 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012930 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012932 * {particles} of the group must be 0 or 1; this is
12933 * already ensured during the parse of the content of
12934 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012935 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012936 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12937 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012938
Daniel Veillarda980bef2005-07-18 21:34:03 +000012939 /*
12940 * This is an abstract group, we need to share
12941 * the same counter for all the element transitions
12942 * derived from the group
12943 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012944 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012945 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012946 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12947 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012948 } else {
12949 if ((sub->minOccurs == 1) &&
12950 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012951 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12952 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012953 elemDecl->name,
12954 elemDecl->targetNamespace,
12955 1, 1, elemDecl);
12956 } else if ((sub->minOccurs == 0) &&
12957 (sub->maxOccurs == 1)) {
12958
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012959 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12960 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012961 elemDecl->name,
12962 elemDecl->targetNamespace,
12963 0,
12964 1,
12965 elemDecl);
12966 }
12967 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012968 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012969 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012970 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012971 pctxt->state =
12972 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012973 break;
12974 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012975 case XML_SCHEMA_TYPE_GROUP:
12976 /*
12977 * If we hit a model group definition, then this means that
12978 * it was empty, thus was not substituted for the containing
12979 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012980 * TODO: But the group should be substituted and not occur at
12981 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012982 */
12983 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012984 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012985 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12986 "xmlSchemaBuildAContentModel",
12987 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012988 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012989 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012990 }
12991}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012992
Daniel Veillard4255d502002-04-16 15:50:10 +000012993/**
12994 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012995 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012996 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012997 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012998 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012999 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013000 */
13001static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013002xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013003 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013004{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013005 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13006 (type->contModel != NULL) ||
13007 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13008 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013009 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013010
13011#ifdef DEBUG_CONTENT
13012 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013013 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013014#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013015 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013016 ctxt->am = xmlNewAutomata();
13017 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013018 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013019 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013020 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013021 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013022 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013023 /*
13024 * Build the automaton.
13025 */
13026 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013027 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013028 type->contModel = xmlAutomataCompile(ctxt->am);
13029 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013030 xmlSchemaPCustomErr(ctxt,
13031 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013032 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013033 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013034 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013035 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013036 XML_SCHEMAP_NOT_DETERMINISTIC,
13037 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013038 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013039 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013040 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013041#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013042 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013043 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013044 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013045#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013046 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013047 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013048 xmlFreeAutomata(ctxt->am);
13049 ctxt->am = NULL;
13050}
13051
13052/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013053 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013054 * @elem: the schema element context
13055 * @ctxt: the schema parser context
13056 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013057 * Resolves the references of an element declaration
13058 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013059 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013060 */
13061static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013062xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13063 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013064{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013065 if ((ctxt == NULL) || (elemDecl == NULL) ||
13066 ((elemDecl != NULL) &&
13067 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013068 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013069 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013071 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013072 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013073
13074 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013075 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013076 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013077 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013078 elemDecl->namedTypeNs);
13079 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013080 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013081 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013082 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013083 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013084 XML_SCHEMA_TYPE_BASIC, "type definition");
13085 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013086 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013087 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013088 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013090
Daniel Veillardc0826a72004-08-10 14:17:33 +000013091 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013092 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013093 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013094 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013095 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13096 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 if (substHead == NULL) {
13098 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013099 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013100 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013101 "substitutionGroup", elemDecl->substGroup,
13102 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013104 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013105 /*
13106 * Set the "substitution group affiliation".
13107 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013108 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013109 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013110 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013111 * The type definitions is set to:
13112 * SPEC "...the {type definition} of the element
13113 * declaration ·resolved· to by the ·actual value·
13114 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013115 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013116 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013117 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013118 }
13119 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013120 /*
13121 * SPEC "The definition of anyType serves as the default type definition
13122 * for element declarations whose XML representation does not specify one."
13123 */
13124 if ((elemDecl->subtypes == NULL) &&
13125 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013126 (elemDecl->substGroup == NULL))
13127 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013128}
13129
13130/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013131 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013132 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013133 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013134 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013135 * Checks and builds the "member type definitions" property of the union
13136 * simple type. This handles part (1), part (2) is done in
13137 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13138 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013139 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013140 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013142xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13143 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013144{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013145
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013146 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013147 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013148
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013149 /*
13150 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13151 * define the explicit members as the type definitions ·resolved·
13152 * to by the items in the ·actual value· of the memberTypes [attribute],
13153 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013154 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013155 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013156 /*
13157 * Resolve references.
13158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013160 lastLink = NULL;
13161 while (link != NULL) {
13162 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013163
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13165 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13166
13167 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013168 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013169 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013170 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013171 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13172 /*
13173 * Remove the member type link.
13174 */
13175 if (lastLink == NULL)
13176 type->memberTypes = link->next;
13177 else
13178 lastLink->next = link->next;
13179 newLink = link;
13180 link = link->next;
13181 xmlFree(newLink);
13182 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013183 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013184 lastLink = link;
13185 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013186 }
13187 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 /*
13189 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013190 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013191 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013192 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013193 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13194 if (link == NULL) {
13195 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13196 return (-1);
13197 }
13198 link->type = memberType;
13199 link->next = NULL;
13200 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201 type->memberTypes = link;
13202 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013203 lastLink->next = link;
13204 lastLink = link;
13205 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013208}
13209
Daniel Veillard4255d502002-04-16 15:50:10 +000013210/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013211 * xmlSchemaIsDerivedFromBuiltInType:
13212 * @ctxt: the schema parser context
13213 * @type: the type definition
13214 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013216 *
13217 * Returns 1 if the type has the given value type, or
13218 * is derived from such a type.
13219 */
William M. Brack803812b2004-06-03 02:11:24 +000013220static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013221xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013222{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223 if (type == NULL)
13224 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013225 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013226 return (0);
13227 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13228 if (type->builtInType == valType)
13229 return(1);
13230 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13231 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13232 return (0);
13233 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13234 } else
13235 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013236
13237 return (0);
13238}
13239
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013240#if 0
13241/**
13242 * xmlSchemaIsDerivedFromBuiltInType:
13243 * @ctxt: the schema parser context
13244 * @type: the type definition
13245 * @valType: the value type
13246 *
13247 *
13248 * Returns 1 if the type has the given value type, or
13249 * is derived from such a type.
13250 */
13251static int
13252xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13253{
13254 if (type == NULL)
13255 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013256 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013257 return (0);
13258 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13259 if (type->builtInType == valType)
13260 return(1);
13261 return (0);
13262 } else
13263 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13264
13265 return (0);
13266}
13267#endif
13268
13269static xmlSchemaTypePtr
13270xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13271{
13272 if (type == NULL)
13273 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013274 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013275 return (NULL);
13276 if (type->type == XML_SCHEMA_TYPE_BASIC)
13277 return(type);
13278 else
13279 return(xmlSchemaQueryBuiltInType(type->subtypes));
13280
13281 return (NULL);
13282}
13283
Daniel Veillard3646d642004-06-02 19:19:14 +000013284/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013285 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 * @type: the simpleType definition
13287 *
13288 * Returns the primitive type of the given type or
13289 * NULL in case of error.
13290 */
13291static xmlSchemaTypePtr
13292xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13293{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013294
Daniel Veillard01fa6152004-06-29 17:04:39 +000013295 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013296 /*
13297 * Note that anySimpleType is actually not a primitive type
13298 * but we need that here.
13299 */
13300 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13301 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013302 return (type);
13303 type = type->baseType;
13304 }
13305
13306 return (NULL);
13307}
13308
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013309#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013310/**
13311 * xmlSchemaGetBuiltInTypeAncestor:
13312 * @type: the simpleType definition
13313 *
13314 * Returns the primitive type of the given type or
13315 * NULL in case of error.
13316 */
13317static xmlSchemaTypePtr
13318xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13319{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013320 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013321 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013322 while (type != NULL) {
13323 if (type->type == XML_SCHEMA_TYPE_BASIC)
13324 return (type);
13325 type = type->baseType;
13326 }
13327
13328 return (NULL);
13329}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013330#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013331
Daniel Veillard01fa6152004-06-29 17:04:39 +000013332/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013333 * xmlSchemaCloneWildcardNsConstraints:
13334 * @ctxt: the schema parser context
13335 * @dest: the destination wildcard
13336 * @source: the source wildcard
13337 *
13338 * Clones the namespace constraints of source
13339 * and assignes them to dest.
13340 * Returns -1 on internal error, 0 otherwise.
13341 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013342static int
13343xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013344 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013345 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013346{
13347 xmlSchemaWildcardNsPtr cur, tmp, last;
13348
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013349 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013350 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013351 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013352 cur = source->nsSet;
13353 last = NULL;
13354 while (cur != NULL) {
13355 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13356 if (tmp == NULL)
13357 return(-1);
13358 tmp->value = cur->value;
13359 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013360 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013361 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013362 last->next = tmp;
13363 last = tmp;
13364 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013365 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013366 if (dest->negNsSet != NULL)
13367 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013368 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013369 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13370 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013371 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013372 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013373 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013374 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013375 return(0);
13376}
13377
Daniel Veillard50355f02004-06-08 17:52:16 +000013378/**
13379 * xmlSchemaUnionWildcards:
13380 * @ctxt: the schema parser context
13381 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013383 *
13384 * Unions the namespace constraints of the given wildcards.
13385 * @completeWild will hold the resulting union.
13386 * Returns a positive error code on failure, -1 in case of an
13387 * internal error, 0 otherwise.
13388 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013389static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013390xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013391 xmlSchemaWildcardPtr completeWild,
13392 xmlSchemaWildcardPtr curWild)
13393{
13394 xmlSchemaWildcardNsPtr cur, curB, tmp;
13395
13396 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013397 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013398 * value.
13399 */
13400 if ((completeWild->any == curWild->any) &&
13401 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13402 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013403
Daniel Veillard3646d642004-06-02 19:19:14 +000013404 if ((completeWild->negNsSet == NULL) ||
13405 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013406
Daniel Veillard3646d642004-06-02 19:19:14 +000013407 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013408 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013409
13410 /*
13411 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013412 */
13413 cur = completeWild->nsSet;
13414 while (cur != NULL) {
13415 found = 0;
13416 curB = curWild->nsSet;
13417 while (curB != NULL) {
13418 if (cur->value == curB->value) {
13419 found = 1;
13420 break;
13421 }
13422 curB = curB->next;
13423 }
13424 if (!found)
13425 break;
13426 cur = cur->next;
13427 }
13428 if (found)
13429 return(0);
13430 } else
13431 return(0);
13432 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013433 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013434 /*
13435 * 2 If either O1 or O2 is any, then any must be the value
13436 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013437 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013438 if (completeWild->any == 0) {
13439 completeWild->any = 1;
13440 if (completeWild->nsSet != NULL) {
13441 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13442 completeWild->nsSet = NULL;
13443 }
13444 if (completeWild->negNsSet != NULL) {
13445 xmlFree(completeWild->negNsSet);
13446 completeWild->negNsSet = NULL;
13447 }
13448 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013449 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013450 }
13451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013453 * then the union of those sets must be the value.
13454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013456 int found;
13457 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458
Daniel Veillard3646d642004-06-02 19:19:14 +000013459 cur = curWild->nsSet;
13460 start = completeWild->nsSet;
13461 while (cur != NULL) {
13462 found = 0;
13463 curB = start;
13464 while (curB != NULL) {
13465 if (cur->value == curB->value) {
13466 found = 1;
13467 break;
13468 }
13469 curB = curB->next;
13470 }
13471 if (!found) {
13472 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013473 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013474 return (-1);
13475 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013477 completeWild->nsSet = tmp;
13478 }
13479 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013480 }
13481
Daniel Veillard3646d642004-06-02 19:19:14 +000013482 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013483 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013484 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013486 * or ·absent·), then a pair of not and ·absent· must be the value.
13487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013489 (curWild->negNsSet != NULL) &&
13490 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13491 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013492
13493 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013494 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013496 * 5.
13497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013499 (completeWild->negNsSet->value != NULL) &&
13500 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013502 (curWild->negNsSet->value != NULL) &&
13503 (completeWild->nsSet != NULL))) {
13504
13505 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506
Daniel Veillard3646d642004-06-02 19:19:14 +000013507 if (completeWild->nsSet != NULL) {
13508 cur = completeWild->nsSet;
13509 curB = curWild->negNsSet;
13510 } else {
13511 cur = curWild->nsSet;
13512 curB = completeWild->negNsSet;
13513 }
13514 nsFound = 0;
13515 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013517 absentFound = 1;
13518 else if (cur->value == curB->value)
13519 nsFound = 1;
13520 if (nsFound && absentFound)
13521 break;
13522 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013524
13525 if (nsFound && absentFound) {
13526 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013527 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013528 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013530 completeWild->any = 1;
13531 if (completeWild->nsSet != NULL) {
13532 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13533 completeWild->nsSet = NULL;
13534 }
13535 if (completeWild->negNsSet != NULL) {
13536 xmlFree(completeWild->negNsSet);
13537 completeWild->negNsSet = NULL;
13538 }
13539 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 /*
13541 * 5.2 If the set S includes the negated namespace name
13542 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013543 * be the value.
13544 */
13545 if (completeWild->nsSet != NULL) {
13546 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13547 completeWild->nsSet = NULL;
13548 }
13549 if (completeWild->negNsSet == NULL) {
13550 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13551 if (completeWild->negNsSet == NULL)
13552 return (-1);
13553 }
13554 completeWild->negNsSet->value = NULL;
13555 } else if ((!nsFound) && absentFound) {
13556 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013558 * namespace name, then the union is not expressible.
13559 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013560 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013561 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013562 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013563 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013564 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013565 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013566 /*
13567 * 5.4 If the set S does not include either the negated namespace
13568 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013569 * and a namespace name must be the value.
13570 */
13571 if (completeWild->negNsSet == NULL) {
13572 if (completeWild->nsSet != NULL) {
13573 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13574 completeWild->nsSet = NULL;
13575 }
13576 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13577 if (completeWild->negNsSet == NULL)
13578 return (-1);
13579 completeWild->negNsSet->value = curWild->negNsSet->value;
13580 }
13581 }
13582 return (0);
13583 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013584 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013585 * 6.
13586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013588 (completeWild->negNsSet->value == NULL) &&
13589 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013591 (curWild->negNsSet->value == NULL) &&
13592 (completeWild->nsSet != NULL))) {
13593
13594 if (completeWild->nsSet != NULL) {
13595 cur = completeWild->nsSet;
13596 } else {
13597 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013598 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013599 while (cur != NULL) {
13600 if (cur->value == NULL) {
13601 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013602 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013603 * value.
13604 */
13605 completeWild->any = 1;
13606 if (completeWild->nsSet != NULL) {
13607 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13608 completeWild->nsSet = NULL;
13609 }
13610 if (completeWild->negNsSet != NULL) {
13611 xmlFree(completeWild->negNsSet);
13612 completeWild->negNsSet = NULL;
13613 }
13614 return (0);
13615 }
13616 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013618 if (completeWild->negNsSet == NULL) {
13619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013620 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013621 * and ·absent· must be the value.
13622 */
13623 if (completeWild->nsSet != NULL) {
13624 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13625 completeWild->nsSet = NULL;
13626 }
13627 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13628 if (completeWild->negNsSet == NULL)
13629 return (-1);
13630 completeWild->negNsSet->value = NULL;
13631 }
13632 return (0);
13633 }
13634 return (0);
13635
13636}
13637
Daniel Veillard50355f02004-06-08 17:52:16 +000013638/**
13639 * xmlSchemaIntersectWildcards:
13640 * @ctxt: the schema parser context
13641 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013642 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013643 *
13644 * Intersects the namespace constraints of the given wildcards.
13645 * @completeWild will hold the resulting intersection.
13646 * Returns a positive error code on failure, -1 in case of an
13647 * internal error, 0 otherwise.
13648 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013649static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013651 xmlSchemaWildcardPtr completeWild,
13652 xmlSchemaWildcardPtr curWild)
13653{
William M. Brack803812b2004-06-03 02:11:24 +000013654 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013655
13656 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013657 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013658 * value.
13659 */
13660 if ((completeWild->any == curWild->any) &&
13661 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13662 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663
Daniel Veillard3646d642004-06-02 19:19:14 +000013664 if ((completeWild->negNsSet == NULL) ||
13665 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666
Daniel Veillard3646d642004-06-02 19:19:14 +000013667 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013668 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013669
13670 /*
13671 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013672 */
13673 cur = completeWild->nsSet;
13674 while (cur != NULL) {
13675 found = 0;
13676 curB = curWild->nsSet;
13677 while (curB != NULL) {
13678 if (cur->value == curB->value) {
13679 found = 1;
13680 break;
13681 }
13682 curB = curB->next;
13683 }
13684 if (!found)
13685 break;
13686 cur = cur->next;
13687 }
13688 if (found)
13689 return(0);
13690 } else
13691 return(0);
13692 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013693 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013694 /*
13695 * 2 If either O1 or O2 is any, then the other must be the value.
13696 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013698 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013700 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013701 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013702 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013703 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13704 * name or ·absent·) and the other is a set of (namespace names or
13705 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013706 * the set, minus ·absent· if it was in the set, must be the value.
13707 */
13708 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13709 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13710 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711
Daniel Veillard3646d642004-06-02 19:19:14 +000013712 if (completeWild->nsSet == NULL) {
13713 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013714 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013715 return(-1);
13716 } else
13717 neg = curWild->negNsSet->value;
13718 /*
13719 * Remove absent and negated.
13720 */
13721 prev = NULL;
13722 cur = completeWild->nsSet;
13723 while (cur != NULL) {
13724 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013725 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013726 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013728 prev->next = cur->next;
13729 xmlFree(cur);
13730 break;
13731 }
13732 prev = cur;
13733 cur = cur->next;
13734 }
13735 if (neg != NULL) {
13736 prev = NULL;
13737 cur = completeWild->nsSet;
13738 while (cur != NULL) {
13739 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013741 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013742 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013743 prev->next = cur->next;
13744 xmlFree(cur);
13745 break;
13746 }
13747 prev = cur;
13748 cur = cur->next;
13749 }
13750 }
13751
13752 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013754 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013755 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013756 * then the intersection of those sets must be the value.
13757 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013758 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013759 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 cur = completeWild->nsSet;
13762 prev = NULL;
13763 while (cur != NULL) {
13764 found = 0;
13765 curB = curWild->nsSet;
13766 while (curB != NULL) {
13767 if (cur->value == curB->value) {
13768 found = 1;
13769 break;
13770 }
13771 curB = curB->next;
13772 }
13773 if (!found) {
13774 if (prev == NULL)
13775 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013776 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013777 prev->next = cur->next;
13778 tmp = cur->next;
13779 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013781 continue;
13782 }
13783 prev = cur;
13784 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013785 }
13786
Daniel Veillard3646d642004-06-02 19:19:14 +000013787 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013788 }
13789 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013790 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 */
13792 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013793 (curWild->negNsSet != NULL) &&
13794 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013796 (curWild->negNsSet->value != NULL)) {
13797
13798 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013799 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013801 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013802 }
13803 /*
13804 * 6 If the one is a negation of a namespace name and the other
13805 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013806 * of a namespace name must be the value.
13807 */
13808 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13809 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 (completeWild->negNsSet->value == NULL)) {
13811 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013812 }
13813 return(0);
13814}
13815
Daniel Veillard50355f02004-06-08 17:52:16 +000013816/**
13817 * xmlSchemaIsWildcardNsConstraintSubset:
13818 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013819 * @sub: the first wildcard
13820 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013821 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013822 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13823 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013825 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013826 */
13827static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013828xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13829 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830{
Daniel Veillard50355f02004-06-08 17:52:16 +000013831 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013832 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013833 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013834 if (super->any)
13835 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013836 /*
13837 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13838 * 2.2 super must be a pair of not and the same value.
13839 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013840 if ((sub->negNsSet != NULL) &&
13841 (super->negNsSet != NULL) &&
13842 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843 return (0);
13844 /*
13845 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013846 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013847 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013848 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013849 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013850 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013851 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013852 xmlSchemaWildcardNsPtr cur, curB;
13853 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013855 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013856 while (cur != NULL) {
13857 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013858 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013859 while (curB != NULL) {
13860 if (cur->value == curB->value) {
13861 found = 1;
13862 break;
13863 }
13864 curB = curB->next;
13865 }
13866 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013867 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013868 cur = cur->next;
13869 }
13870 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013871 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013872 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013873 xmlSchemaWildcardNsPtr cur;
13874 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013875 * 3.2.2 super must be a pair of not and a namespace name or
13876 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013877 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013878 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013879 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013880 if (cur->value == super->negNsSet->value)
13881 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013882 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013883 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013884 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013885 }
13886 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013887 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013888}
13889
Daniel Veillard50355f02004-06-08 17:52:16 +000013890static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013891xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013892 int *fixed,
13893 const xmlChar **value,
13894 xmlSchemaValPtr *val)
13895{
13896 *fixed = 0;
13897 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013898 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013899 *val = NULL;
13900
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013901 if (attruse->defValue != NULL) {
13902 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013903 if (val != NULL)
13904 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013905 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013906 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013907 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000013908 } else if ((attruse->attrDecl != NULL) &&
13909 (attruse->attrDecl->defValue != NULL)) {
13910 *value = attruse->attrDecl->defValue;
13911 if (val != NULL)
13912 *val = attruse->attrDecl->defVal;
13913 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013914 *fixed = 1;
13915 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013916 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013917 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013918}
Daniel Veillard3646d642004-06-02 19:19:14 +000013919/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013921 * @wild: the wildcard
13922 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 *
13924 * Validation Rule: Wildcard allows Namespace Name
13925 * (cvc-wildcard-namespace)
13926 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013927 * Returns 0 if the given namespace matches the wildcard,
13928 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013929 */
13930static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13932 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013933{
13934 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013935 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013936
13937 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013938 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013939 else if (wild->nsSet != NULL) {
13940 xmlSchemaWildcardNsPtr cur;
13941
13942 cur = wild->nsSet;
13943 while (cur != NULL) {
13944 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013945 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013946 cur = cur->next;
13947 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013949 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013950 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013951
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013952 return(1);
13953}
13954
13955#define XML_SCHEMA_ACTION_DERIVE 0
13956#define XML_SCHEMA_ACTION_REDEFINE 1
13957
13958#define WXS_ACTION_STR(a) \
13959((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13960
13961/*
13962* Schema Component Constraint:
13963* Derivation Valid (Restriction, Complex)
13964* derivation-ok-restriction (2) - (4)
13965*
13966* ATTENTION:
13967* In XML Schema 1.1 this will be:
13968* Validation Rule:
13969* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13970*
13971*/
13972static int
13973xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13974 int action,
13975 xmlSchemaBasicItemPtr item,
13976 xmlSchemaBasicItemPtr baseItem,
13977 xmlSchemaItemListPtr uses,
13978 xmlSchemaItemListPtr baseUses,
13979 xmlSchemaWildcardPtr wild,
13980 xmlSchemaWildcardPtr baseWild)
13981{
13982 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013983 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013984 const xmlChar *bEffValue;
13985 int effFixed;
13986
13987 if (uses != NULL) {
13988 for (i = 0; i < uses->nbItems; i++) {
13989 cur = uses->items[i];
13990 found = 0;
13991 if (baseUses == NULL)
13992 goto not_found;
13993 for (j = 0; j < baseUses->nbItems; j++) {
13994 bcur = baseUses->items[j];
13995 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13996 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13997 (WXS_ATTRUSE_DECL_TNS(cur) ==
13998 WXS_ATTRUSE_DECL_TNS(bcur)))
13999 {
14000 /*
14001 * (2.1) "If there is an attribute use in the {attribute
14002 * uses} of the {base type definition} (call this B) whose
14003 * {attribute declaration} has the same {name} and {target
14004 * namespace}, then all of the following must be true:"
14005 */
14006 found = 1;
14007
14008 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14009 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14010 {
14011 xmlChar *str = NULL;
14012 /*
14013 * (2.1.1) "one of the following must be true:"
14014 * (2.1.1.1) "B's {required} is false."
14015 * (2.1.1.2) "R's {required} is true."
14016 */
14017 xmlSchemaPAttrUseErr4(pctxt,
14018 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14019 WXS_ITEM_NODE(item), item, cur,
14020 "The 'optional' attribute use is inconsistent "
14021 "with the corresponding 'required' attribute use of "
14022 "the %s %s",
14023 WXS_ACTION_STR(action),
14024 xmlSchemaGetComponentDesignation(&str, baseItem),
14025 NULL, NULL);
14026 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014027 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014028 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014029 WXS_ATTRUSE_TYPEDEF(cur),
14030 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14031 {
14032 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14033
14034 /*
14035 * SPEC (2.1.2) "R's {attribute declaration}'s
14036 * {type definition} must be validly derived from
14037 * B's {type definition} given the empty set as
14038 * defined in Type Derivation OK (Simple) (§3.14.6)."
14039 */
14040 xmlSchemaPAttrUseErr4(pctxt,
14041 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14042 WXS_ITEM_NODE(item), item, cur,
14043 "The attribute declaration's %s "
14044 "is not validly derived from "
14045 "the corresponding %s of the "
14046 "attribute declaration in the %s %s",
14047 xmlSchemaGetComponentDesignation(&strA,
14048 WXS_ATTRUSE_TYPEDEF(cur)),
14049 xmlSchemaGetComponentDesignation(&strB,
14050 WXS_ATTRUSE_TYPEDEF(bcur)),
14051 WXS_ACTION_STR(action),
14052 xmlSchemaGetComponentDesignation(&strC, baseItem));
14053 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14054 FREE_AND_NULL(strA);
14055 FREE_AND_NULL(strB);
14056 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014057 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014058 } else {
14059 /*
14060 * 2.1.3 [Definition:] Let the effective value
14061 * constraint of an attribute use be its {value
14062 * constraint}, if present, otherwise its {attribute
14063 * declaration}'s {value constraint} .
14064 */
14065 xmlSchemaGetEffectiveValueConstraint(bcur,
14066 &effFixed, &bEffValue, NULL);
14067 /*
14068 * 2.1.3 ... one of the following must be true
14069 *
14070 * 2.1.3.1 B's ·effective value constraint· is
14071 * ·absent· or default.
14072 */
14073 if ((bEffValue != NULL) &&
14074 (effFixed == 1)) {
14075 const xmlChar *rEffValue = NULL;
14076
14077 xmlSchemaGetEffectiveValueConstraint(bcur,
14078 &effFixed, &rEffValue, NULL);
14079 /*
14080 * 2.1.3.2 R's ·effective value constraint· is
14081 * fixed with the same string as B's.
14082 * MAYBE TODO: Compare the computed values.
14083 * Hmm, it says "same string" so
14084 * string-equality might really be sufficient.
14085 */
14086 if ((effFixed == 0) ||
14087 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14088 {
14089 xmlChar *str = NULL;
14090
14091 xmlSchemaPAttrUseErr4(pctxt,
14092 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14093 WXS_ITEM_NODE(item), item, cur,
14094 "The effective value constraint of the "
14095 "attribute use is inconsistent with "
14096 "its correspondent in the %s %s",
14097 WXS_ACTION_STR(action),
14098 xmlSchemaGetComponentDesignation(&str,
14099 baseItem),
14100 NULL, NULL);
14101 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014102 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014103 }
14104 }
14105 }
14106 break;
14107 }
14108 }
14109not_found:
14110 if (!found) {
14111 /*
14112 * (2.2) "otherwise the {base type definition} must have an
14113 * {attribute wildcard} and the {target namespace} of the
14114 * R's {attribute declaration} must be ·valid· with respect
14115 * to that wildcard, as defined in Wildcard allows Namespace
14116 * Name (§3.10.4)."
14117 */
14118 if ((baseWild == NULL) ||
14119 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14120 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14121 {
14122 xmlChar *str = NULL;
14123
14124 xmlSchemaPAttrUseErr4(pctxt,
14125 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14126 WXS_ITEM_NODE(item), item, cur,
14127 "Neither a matching attribute use, "
14128 "nor a matching wildcard exists in the %s %s",
14129 WXS_ACTION_STR(action),
14130 xmlSchemaGetComponentDesignation(&str, baseItem),
14131 NULL, NULL);
14132 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014133 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014134 }
14135 }
14136 }
14137 }
14138 /*
14139 * SPEC derivation-ok-restriction (3):
14140 * (3) "For each attribute use in the {attribute uses} of the {base type
14141 * definition} whose {required} is true, there must be an attribute
14142 * use with an {attribute declaration} with the same {name} and
14143 * {target namespace} as its {attribute declaration} in the {attribute
14144 * uses} of the complex type definition itself whose {required} is true.
14145 */
14146 if (baseUses != NULL) {
14147 for (j = 0; j < baseUses->nbItems; j++) {
14148 bcur = baseUses->items[j];
14149 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14150 continue;
14151 found = 0;
14152 if (uses != NULL) {
14153 for (i = 0; i < uses->nbItems; i++) {
14154 cur = uses->items[i];
14155 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14156 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14157 (WXS_ATTRUSE_DECL_TNS(cur) ==
14158 WXS_ATTRUSE_DECL_TNS(bcur))) {
14159 found = 1;
14160 break;
14161 }
14162 }
14163 }
14164 if (!found) {
14165 xmlChar *strA = NULL, *strB = NULL;
14166
14167 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14168 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14169 NULL, item,
14170 "A matching attribute use for the "
14171 "'required' %s of the %s %s is missing",
14172 xmlSchemaGetComponentDesignation(&strA, bcur),
14173 WXS_ACTION_STR(action),
14174 xmlSchemaGetComponentDesignation(&strB, baseItem),
14175 NULL);
14176 FREE_AND_NULL(strA);
14177 FREE_AND_NULL(strB);
14178 }
14179 }
14180 }
14181 /*
14182 * derivation-ok-restriction (4)
14183 */
14184 if (wild != NULL) {
14185 /*
14186 * (4) "If there is an {attribute wildcard}, all of the
14187 * following must be true:"
14188 */
14189 if (baseWild == NULL) {
14190 xmlChar *str = NULL;
14191
14192 /*
14193 * (4.1) "The {base type definition} must also have one."
14194 */
14195 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14196 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14197 NULL, item,
14198 "The %s has an attribute wildcard, "
14199 "but the %s %s '%s' does not have one",
14200 WXS_ITEM_TYPE_NAME(item),
14201 WXS_ACTION_STR(action),
14202 WXS_ITEM_TYPE_NAME(baseItem),
14203 xmlSchemaGetComponentQName(&str, baseItem));
14204 FREE_AND_NULL(str);
14205 return(pctxt->err);
14206 } else if ((baseWild->any == 0) &&
14207 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14208 {
14209 xmlChar *str = NULL;
14210 /*
14211 * (4.2) "The complex type definition's {attribute wildcard}'s
14212 * {namespace constraint} must be a subset of the {base type
14213 * definition}'s {attribute wildcard}'s {namespace constraint},
14214 * as defined by Wildcard Subset (§3.10.6)."
14215 */
14216 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14217 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14218 NULL, item,
14219 "The attribute wildcard is not a valid "
14220 "subset of the wildcard in the %s %s '%s'",
14221 WXS_ACTION_STR(action),
14222 WXS_ITEM_TYPE_NAME(baseItem),
14223 xmlSchemaGetComponentQName(&str, baseItem),
14224 NULL);
14225 FREE_AND_NULL(str);
14226 return(pctxt->err);
14227 }
14228 /* 4.3 Unless the {base type definition} is the ·ur-type
14229 * definition·, the complex type definition's {attribute
14230 * wildcard}'s {process contents} must be identical to or
14231 * stronger than the {base type definition}'s {attribute
14232 * wildcard}'s {process contents}, where strict is stronger
14233 * than lax is stronger than skip.
14234 */
14235 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14236 (wild->processContents < baseWild->processContents)) {
14237 xmlChar *str = NULL;
14238 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14239 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14240 NULL, baseItem,
14241 "The {process contents} of the attribute wildcard is "
14242 "weaker than the one in the %s %s '%s'",
14243 WXS_ACTION_STR(action),
14244 WXS_ITEM_TYPE_NAME(baseItem),
14245 xmlSchemaGetComponentQName(&str, baseItem),
14246 NULL);
14247 FREE_AND_NULL(str)
14248 return(pctxt->err);
14249 }
14250 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014251 return(0);
14252}
14253
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014254
14255static int
14256xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14257 xmlSchemaBasicItemPtr item,
14258 xmlSchemaWildcardPtr *completeWild,
14259 xmlSchemaItemListPtr list,
14260 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014261/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014262 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014263 * @ctxt: the schema parser context
14264 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014265 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014266 *
14267 * Builds the wildcard and the attribute uses on the given complex type.
14268 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014269 *
14270 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14271 * strings, so recheck this if we start to hardcode some schemata, since
14272 * they might not be in the same dict.
14273 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014274 */
14275static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014276xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014277 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014278{
14279 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014280 xmlSchemaAttributeUsePtr use;
14281 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014282
Daniel Veillard01fa6152004-06-29 17:04:39 +000014283 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014284 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014285 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014286 return (-1);
14287 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014288 baseType = type->baseType;
14289 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014290 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014291 return(-1);
14292
14293 uses = type->attrUses;
14294 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014295 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014296 * Expand attribute group references. And build the 'complete'
14297 * wildcard, i.e. intersect multiple wildcards.
14298 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014299 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014300 if (uses != NULL) {
14301 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014302 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014303 * This one will transfer all attr. prohibitions
14304 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014305 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014306 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14307 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14308 pctxt->attrProhibs) == -1)
14309 {
14310 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14311 "failed to expand attributes");
14312 }
14313 if (pctxt->attrProhibs->nbItems != 0)
14314 prohibs = pctxt->attrProhibs;
14315 } else {
14316 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14317 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14318 NULL) == -1)
14319 {
14320 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14321 "failed to expand attributes");
14322 }
14323 }
14324 }
14325 /*
14326 * Inherit the attribute uses of the base type.
14327 */
14328 if (baseUses != NULL) {
14329 int i, j;
14330 xmlSchemaAttributeUseProhibPtr pro;
14331
14332 if (WXS_IS_RESTRICTION(type)) {
14333 int usesCount;
14334 xmlSchemaAttributeUsePtr tmp;
14335
14336 if (uses != NULL)
14337 usesCount = uses->nbItems;
14338 else
14339 usesCount = 0;
14340
14341 /* Restriction. */
14342 for (i = 0; i < baseUses->nbItems; i++) {
14343 use = baseUses->items[i];
14344 if (prohibs) {
14345 /*
14346 * Filter out prohibited uses.
14347 */
14348 for (j = 0; j < prohibs->nbItems; j++) {
14349 pro = prohibs->items[j];
14350 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14351 (WXS_ATTRUSE_DECL_TNS(use) ==
14352 pro->targetNamespace))
14353 {
14354 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014355 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014356 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014357 }
14358 if (usesCount) {
14359 /*
14360 * Filter out existing uses.
14361 */
14362 for (j = 0; j < usesCount; j++) {
14363 tmp = uses->items[j];
14364 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14365 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14366 (WXS_ATTRUSE_DECL_TNS(use) ==
14367 WXS_ATTRUSE_DECL_TNS(tmp)))
14368 {
14369 goto inherit_next;
14370 }
14371 }
14372 }
14373 if (uses == NULL) {
14374 type->attrUses = xmlSchemaItemListCreate();
14375 if (type->attrUses == NULL)
14376 goto exit_failure;
14377 uses = type->attrUses;
14378 }
14379 xmlSchemaItemListAddSize(uses, 2, use);
14380inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014381 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014382 } else {
14383 /* Extension. */
14384 for (i = 0; i < baseUses->nbItems; i++) {
14385 use = baseUses->items[i];
14386 if (uses == NULL) {
14387 type->attrUses = xmlSchemaItemListCreate();
14388 if (type->attrUses == NULL)
14389 goto exit_failure;
14390 uses = type->attrUses;
14391 }
14392 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14393 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014394 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014395 }
14396 /*
14397 * Shrink attr. uses.
14398 */
14399 if (uses) {
14400 if (uses->nbItems == 0) {
14401 xmlSchemaItemListFree(uses);
14402 type->attrUses = NULL;
14403 }
14404 /*
14405 * TODO: We could shrink the size of the array
14406 * to fit the actual number of items.
14407 */
14408 }
14409 /*
14410 * Compute the complete wildcard.
14411 */
14412 if (WXS_IS_EXTENSION(type)) {
14413 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014414 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014415 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14416 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014417 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014418 if (type->attributeWildcard != NULL) {
14419 /*
14420 * Union the complete wildcard with the base wildcard.
14421 * SPEC {attribute wildcard}
14422 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14423 * and {annotation} are those of the ·complete wildcard·,
14424 * and whose {namespace constraint} is the intensional union
14425 * of the {namespace constraint} of the ·complete wildcard·
14426 * and of the ·base wildcard·, as defined in Attribute
14427 * Wildcard Union (§3.10.6)."
14428 */
14429 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14430 baseType->attributeWildcard) == -1)
14431 goto exit_failure;
14432 } else {
14433 /*
14434 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14435 * then the ·base wildcard·."
14436 */
14437 type->attributeWildcard = baseType->attributeWildcard;
14438 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014439 } else {
14440 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014441 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14442 * ·complete wildcard"
14443 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014444 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014445 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014446 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014447 /*
14448 * SPEC {attribute wildcard}
14449 * (3.1) "If the <restriction> alternative is chosen, then the
14450 * ·complete wildcard·;"
14451 * NOOP
14452 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014453 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014454
Daniel Veillard3646d642004-06-02 19:19:14 +000014455 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014456
14457exit_failure:
14458 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014459}
14460
14461/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014462 * xmlSchemaTypeFinalContains:
14463 * @schema: the schema
14464 * @type: the type definition
14465 * @final: the final
14466 *
14467 * Evaluates if a type definition contains the given "final".
14468 * This does take "finalDefault" into account as well.
14469 *
14470 * Returns 1 if the type does containt the given "final",
14471 * 0 otherwise.
14472 */
14473static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014474xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014475{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014476 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014477 return (0);
14478 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014479 return (1);
14480 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014481 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014482}
14483
14484/**
14485 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14486 * @type: the Union Simple Type
14487 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014488 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014489 * returns NULL otherwise.
14490 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014491static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014492xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14493{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014494 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014495 if (type->memberTypes != NULL)
14496 return (type->memberTypes);
14497 else
14498 type = type->baseType;
14499 }
14500 return (NULL);
14501}
14502
14503/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014504 * xmlSchemaGetParticleTotalRangeMin:
14505 * @particle: the particle
14506 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014507 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014508 * (all and sequence) + (choice)
14509 *
14510 * Returns the minimun Effective Total Range.
14511 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014512static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014513xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014514{
14515 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014516 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517 return (0);
14518 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014519 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014520 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014521 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014522
14523 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014524 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014525 while (part != NULL) {
14526 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14527 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014528 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014529 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014530 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014531 if (cur == 0)
14532 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014533 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014534 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014535 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014536 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014537 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014538 } else {
14539 /* <all> and <sequence> */
14540 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014541 xmlSchemaParticlePtr part =
14542 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014543
14544 if (part == NULL)
14545 return (0);
14546 do {
14547 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14548 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014549 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014550 else
14551 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014552 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014553 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014554 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014555 }
14556}
14557
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014558/**
14559 * xmlSchemaGetParticleTotalRangeMax:
14560 * @particle: the particle
14561 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014562 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014563 * (all and sequence) + (choice)
14564 *
14565 * Returns the maximum Effective Total Range.
14566 */
14567static int
14568xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14569{
14570 if ((particle->children == NULL) ||
14571 (particle->children->children == NULL))
14572 return (0);
14573 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14574 int max = -1, cur;
14575 xmlSchemaParticlePtr part =
14576 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014577
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014578 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14579 if (part->children == NULL)
14580 continue;
14581 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14582 (part->children->type == XML_SCHEMA_TYPE_ANY))
14583 cur = part->maxOccurs;
14584 else
14585 cur = xmlSchemaGetParticleTotalRangeMax(part);
14586 if (cur == UNBOUNDED)
14587 return (UNBOUNDED);
14588 if ((max < cur) || (max == -1))
14589 max = cur;
14590 }
14591 /* TODO: Handle overflows? */
14592 return (particle->maxOccurs * max);
14593 } else {
14594 /* <all> and <sequence> */
14595 int sum = 0, cur;
14596 xmlSchemaParticlePtr part =
14597 (xmlSchemaParticlePtr) particle->children->children;
14598
14599 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14600 if (part->children == NULL)
14601 continue;
14602 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14603 (part->children->type == XML_SCHEMA_TYPE_ANY))
14604 cur = part->maxOccurs;
14605 else
14606 cur = xmlSchemaGetParticleTotalRangeMax(part);
14607 if (cur == UNBOUNDED)
14608 return (UNBOUNDED);
14609 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14610 return (UNBOUNDED);
14611 sum += cur;
14612 }
14613 /* TODO: Handle overflows? */
14614 return (particle->maxOccurs * sum);
14615 }
14616}
14617
14618/**
14619 * xmlSchemaIsParticleEmptiable:
14620 * @particle: the particle
14621 *
14622 * Schema Component Constraint: Particle Emptiable
14623 * Checks whether the given particle is emptiable.
14624 *
14625 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014626 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014627static int
14628xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14629{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014630 /*
14631 * SPEC (1) "Its {min occurs} is 0."
14632 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014633 if ((particle == NULL) || (particle->minOccurs == 0) ||
14634 (particle->children == NULL))
14635 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014636 /*
14637 * SPEC (2) "Its {term} is a group and the minimum part of the
14638 * effective total range of that group, [...] is 0."
14639 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014640 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014641 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014642 return (1);
14643 }
14644 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014645}
14646
14647/**
14648 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014649 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650 * @type: the derived simple type definition
14651 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014652 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014653 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014654 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014655 * Type Derivation OK (Simple) (cos-st-derived-OK)
14656 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014657 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 * derived from @baseType.
14659 *
14660 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014661 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014662static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014663xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014664 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014665 xmlSchemaTypePtr baseType,
14666 int subset)
14667{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014668 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014669 * 1 They are the same type definition.
14670 * TODO: The identy check might have to be more complex than this.
14671 */
14672 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014673 return (0);
14674 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014675 * 2.1 restriction is not in the subset, or in the {final}
14676 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014677 *
14678 * NOTE that this will be used also via "xsi:type".
14679 *
14680 * TODO: Revise this, it looks strange. How can the "type"
14681 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014683 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014684 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014685 return(-1);
14686 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014687 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014688 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014689 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014690 (xmlSchemaTypeFinalContains(type->baseType,
14691 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14692 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014693 }
14694 /* 2.2 */
14695 if (type->baseType == baseType) {
14696 /*
14697 * 2.2.1 D's ·base type definition· is B.
14698 */
14699 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014700 }
14701 /*
14702 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14703 * and is validly derived from B given the subset, as defined by this
14704 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014705 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014706 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014707 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014708 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014709 return (0);
14710 }
14711 /*
14712 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014713 * definition·.
14714 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014715 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14716 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014717 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014718 }
14719 /*
14720 * 2.2.4 B's {variety} is union and D is validly derived from a type
14721 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014722 * defined by this constraint.
14723 *
14724 * NOTE: This seems not to involve built-in types, since there is no
14725 * built-in Union Simple Type.
14726 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014727 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014728 xmlSchemaTypeLinkPtr cur;
14729
14730 cur = baseType->memberTypes;
14731 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014732 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014733 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014734 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014735 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014736 type, cur->type, subset) == 0)
14737 {
14738 /*
14739 * It just has to be validly derived from at least one
14740 * member-type.
14741 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014742 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014743 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014744 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014745 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014746 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014747 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14748}
14749
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014750/**
14751 * xmlSchemaCheckTypeDefCircularInternal:
14752 * @pctxt: the schema parser context
14753 * @ctxtType: the type definition
14754 * @ancestor: an ancestor of @ctxtType
14755 *
14756 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014757 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014758 *
14759 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14760 * circular, 0 otherwise.
14761 */
14762static int
14763xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14764 xmlSchemaTypePtr ctxtType,
14765 xmlSchemaTypePtr ancestor)
14766{
14767 int ret;
14768
14769 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14770 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014771
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 if (ctxtType == ancestor) {
14773 xmlSchemaPCustomErr(pctxt,
14774 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014775 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014776 "The definition is circular", NULL);
14777 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14778 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014779 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14780 /*
14781 * Avoid inifinite recursion on circular types not yet checked.
14782 */
14783 return (0);
14784 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014785 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14786 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14787 ancestor->baseType);
14788 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14789 return (ret);
14790}
14791
14792/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014793 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014794 * @item: the complex/simple type definition
14795 * @ctxt: the parser context
14796 * @name: the name
14797 *
14798 * Checks for circular type definitions.
14799 */
14800static void
14801xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014802 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014803{
14804 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014805 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14806 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014807 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014808 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14809 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014811
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014812/*
14813* Simple Type Definition Representation OK (src-simple-type) 4
14814*
14815* "4 Circular union type definition is disallowed. That is, if the
14816* <union> alternative is chosen, there must not be any entries in the
14817* memberTypes [attribute] at any depth which resolve to the component
14818* corresponding to the <simpleType>."
14819*
14820* Note that this should work on the *representation* of a component,
14821* thus assumes any union types in the member types not being yet
14822* substituted. At this stage we need the variety of the types
14823* to be already computed.
14824*/
14825static int
14826xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14827 xmlSchemaTypePtr ctxType,
14828 xmlSchemaTypeLinkPtr members)
14829{
14830 xmlSchemaTypeLinkPtr member;
14831 xmlSchemaTypePtr memberType;
14832
14833 member = members;
14834 while (member != NULL) {
14835 memberType = member->type;
14836 while ((memberType != NULL) &&
14837 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14838 if (memberType == ctxType) {
14839 xmlSchemaPCustomErr(pctxt,
14840 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014841 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014842 "The union type definition is circular", NULL);
14843 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14844 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014845 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014846 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14847 {
14848 int res;
14849 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14850 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14851 ctxType,
14852 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14853 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14854 if (res != 0)
14855 return(res);
14856 }
14857 memberType = memberType->baseType;
14858 }
14859 member = member->next;
14860 }
14861 return(0);
14862}
14863
14864static int
14865xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14866 xmlSchemaTypePtr type)
14867{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014868 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014869 return(0);
14870 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14871 type->memberTypes));
14872}
14873
Daniel Veillard01fa6152004-06-29 17:04:39 +000014874/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014875 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014876 * @item: the complex/simple type definition
14877 * @ctxt: the parser context
14878 * @name: the name
14879 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014880 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014881 */
14882static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014883xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014884 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014885{
14886 if (typeDef == NULL)
14887 return;
14888
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014889 /*
14890 * Resolve the base type.
14891 */
14892 if (typeDef->baseType == NULL) {
14893 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14894 typeDef->base, typeDef->baseNs);
14895 if (typeDef->baseType == NULL) {
14896 xmlSchemaPResCompAttrErr(ctxt,
14897 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014898 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014899 "base", typeDef->base, typeDef->baseNs,
14900 XML_SCHEMA_TYPE_SIMPLE, NULL);
14901 return;
14902 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014903 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014904 if (WXS_IS_SIMPLE(typeDef)) {
14905 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014906 /*
14907 * Resolve the memberTypes.
14908 */
14909 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14910 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014911 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014912 /*
14913 * Resolve the itemType.
14914 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014915 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14916
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014918 typeDef->base, typeDef->baseNs);
14919
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014920 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014921 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14922 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014923 typeDef->subtypes = NULL;
14924 xmlSchemaPResCompAttrErr(ctxt,
14925 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014926 WXS_BASIC_CAST typeDef, typeDef->node,
14927 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014928 XML_SCHEMA_TYPE_SIMPLE, NULL);
14929 }
14930 }
14931 return;
14932 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014933 }
14934 /*
14935 * The ball of letters below means, that if we have a particle
14936 * which has a QName-helper component as its {term}, we want
14937 * to resolve it...
14938 */
14939 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14940 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14941 XML_SCHEMA_TYPE_PARTICLE) &&
14942 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14943 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14944 XML_SCHEMA_EXTRA_QNAMEREF))
14945 {
14946 xmlSchemaQNameRefPtr ref =
14947 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14948 xmlSchemaModelGroupDefPtr groupDef;
14949
14950 /*
14951 * URGENT TODO: Test this.
14952 */
14953 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14954 /*
14955 * Resolve the MG definition reference.
14956 */
14957 groupDef =
14958 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14959 ref->itemType, ref->name, ref->targetNamespace);
14960 if (groupDef == NULL) {
14961 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14962 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14963 "ref", ref->name, ref->targetNamespace, ref->itemType,
14964 NULL);
14965 /* Remove the particle. */
14966 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14967 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14968 /* Remove the particle. */
14969 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14970 else {
14971 /*
14972 * Assign the MG definition's {model group} to the
14973 * particle's {term}.
14974 */
14975 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14976
14977 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14978 /*
14979 * SPEC cos-all-limited (1.2)
14980 * "1.2 the {term} property of a particle with
14981 * {max occurs}=1 which is part of a pair which constitutes
14982 * the {content type} of a complex type definition."
14983 */
14984 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14985 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14986 /* TODO: error code */
14987 XML_SCHEMAP_COS_ALL_LIMITED,
14988 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14989 "The particle's {max occurs} must be 1, since the "
14990 "reference resolves to an 'all' model group",
14991 NULL, NULL);
14992 }
14993 }
14994 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014995 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014996}
14997
14998
14999
15000/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015001 * xmlSchemaCheckSTPropsCorrect:
15002 * @ctxt: the schema parser context
15003 * @type: the simple type definition
15004 *
15005 * Checks st-props-correct.
15006 *
15007 * Returns 0 if the properties are correct,
15008 * if not, a positive error code and -1 on internal
15009 * errors.
15010 */
15011static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015012xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015013 xmlSchemaTypePtr type)
15014{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015015 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015016 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015017
Daniel Veillardc0826a72004-08-10 14:17:33 +000015018 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015019 /*
15020 * Schema Component Constraint: Simple Type Definition Properties Correct
15021 *
15022 * NOTE: This is somehow redundant, since we actually built a simple type
15023 * to have all the needed information; this acts as an self test.
15024 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015025 /* Base type: If the datatype has been ·derived· by ·restriction·
15026 * then the Simple Type Definition component from which it is ·derived·,
15027 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015028 */
15029 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015030 /*
15031 * TODO: Think about: "modulo the impact of Missing
15032 * Sub-components (§5.3)."
15033 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015034 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015035 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015036 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015037 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015038 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015039
Daniel Veillard01fa6152004-06-29 17:04:39 +000015040 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015041 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015042 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015044 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015045 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015046 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015047 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015048 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15049 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015050 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015051 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015052 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015053 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015054 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015055 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015056 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015057 "the simple ur-type definition as base type, not '%s'",
15058 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015059 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015060 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015062 /*
15063 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015064 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015065 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15066 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015067 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015068 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015069 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015070 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015071 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15072 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015073 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015074
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015075 /*
15076 * 3 The {final} of the {base type definition} must not contain restriction.
15077 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015078 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015079 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15080 xmlSchemaPCustomErr(ctxt,
15081 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015082 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015083 "The 'final' of its base type '%s' must not contain "
15084 "'restriction'",
15085 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015086 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015087 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015088 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015089
15090 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015091 * 2 All simple type definitions must be derived ultimately from the ·simple
15092 * ur-type definition (so· circular definitions are disallowed). That is, it
15093 * must be possible to reach a built-in primitive datatype or the ·simple
15094 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015095 *
15096 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015097 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015098 return (0);
15099}
15100
15101/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015102 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015103 * @ctxt: the schema parser context
15104 * @type: the simple type definition
15105 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015106 * Schema Component Constraint:
15107 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15108
15109 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015110 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015111 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015112 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015113 * a positive error code otherwise.
15114 */
15115static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015116xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015117 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015118{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015119 xmlChar *str = NULL;
15120
Daniel Veillard01fa6152004-06-29 17:04:39 +000015121 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015122 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15123 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015124 return (-1);
15125 }
15126
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015127 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015128 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 /*
15130 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015131 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015132 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015133 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015134 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015135 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015136 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015137 "The base type '%s' is not an atomic simple type",
15138 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015139 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015140 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15141 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015143 * restriction.
15144 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015145 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015146 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015147 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015148 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015149 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015150 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015151 "The final of its base type '%s' must not contain 'restriction'",
15152 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015153 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015154 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15155 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015156
15157 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015159 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015160 * Primitive datatypes.
15161 */
15162 if (type->facets != NULL) {
15163 xmlSchemaFacetPtr facet;
15164 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015165
Daniel Veillard01fa6152004-06-29 17:04:39 +000015166 primitive = xmlSchemaGetPrimitiveType(type);
15167 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015168 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15169 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015170 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015172 facet = type->facets;
15173 do {
15174 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015175 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015176 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015178 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015179 }
15180 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015181 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015182 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015183 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015184 }
15185 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015186 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15187 * of the {base type definition} (call this BF),then the DF's {value}
15188 * must be a valid restriction of BF's {value} as defined in
15189 * [XML Schemas: Datatypes]."
15190 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015192 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015193 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015194 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015195 xmlSchemaTypePtr itemType = NULL;
15196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015197 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015198 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015199 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15200 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015201 return (-1);
15202 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015203 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015204 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015205 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015206 * 2.1 The {item type definition} must have a {variety} of atomic or
15207 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015208 * must be atomic).
15209 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015210 if ((! WXS_IS_ATOMIC(itemType)) &&
15211 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015212 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015213 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015214 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015215 "The item type '%s' does not have a variety of atomic or union",
15216 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015217 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015218 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015219 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015220 xmlSchemaTypeLinkPtr member;
15221
15222 member = itemType->memberTypes;
15223 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015224 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015225 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015226 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015227 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015228 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015229 "member type '%s' of this item type is not atomic",
15230 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015231 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015232 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15233 }
15234 member = member->next;
15235 }
15236 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015237
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015238 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015239 xmlSchemaFacetPtr facet;
15240 /*
15241 * This is the case if we have: <simpleType><list ..
15242 */
15243 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015244 * 2.3.1
15245 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015246 * contain list.
15247 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015248 if (xmlSchemaTypeFinalContains(itemType,
15249 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15250 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015251 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015252 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015253 "The final of its item type '%s' must not contain 'list'",
15254 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015255 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015256 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15257 }
15258 /*
15259 * 2.3.1.2 The {facets} must only contain the whiteSpace
15260 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015261 * OPTIMIZE TODO: the S4S already disallows any facet
15262 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015263 */
15264 if (type->facets != NULL) {
15265 facet = type->facets;
15266 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015267 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015268 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015269 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015270 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015271 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15272 }
15273 facet = facet->next;
15274 } while (facet != NULL);
15275 }
15276 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015277 * MAYBE TODO: (Hmm, not really) Datatypes states:
15278 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15279 * whose ·lexical space· allows space (such as string or anyURI)or
15280 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015281 * ·lexical space· allows space.
15282 */
15283 } else {
15284 /*
15285 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015286 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015287 */
15288 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015289 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015290 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15291 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015292 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015293 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015294 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015295 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015296 "The base type '%s' must be a list type",
15297 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015298 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015299 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15300 }
15301 /*
15302 * 2.3.2.2 The {final} of the {base type definition} must not
15303 * contain restriction.
15304 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015305 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015306 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015308 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015309 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015310 "The 'final' of the base type '%s' must not contain 'restriction'",
15311 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015312 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015313 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15314 }
15315 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015316 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015317 * from the {base type definition}'s {item type definition} given
15318 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15319 */
15320 {
15321 xmlSchemaTypePtr baseItemType;
15322
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015323 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015324 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015325 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15326 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015327 return (-1);
15328 }
15329 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015330 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015331 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015332 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015333 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015334 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015335 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336 "The item type '%s' is not validly derived from "
15337 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015338 xmlSchemaGetComponentQName(&str, itemType),
15339 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15340 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015341
15342 FREE_AND_NULL(str)
15343 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015345 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15346 }
15347 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015348
Daniel Veillard01fa6152004-06-29 17:04:39 +000015349 if (type->facets != NULL) {
15350 xmlSchemaFacetPtr facet;
15351 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 /*
15353 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015354 * and enumeration facet components are allowed among the {facets}.
15355 */
15356 facet = type->facets;
15357 do {
15358 switch (facet->type) {
15359 case XML_SCHEMA_FACET_LENGTH:
15360 case XML_SCHEMA_FACET_MINLENGTH:
15361 case XML_SCHEMA_FACET_MAXLENGTH:
15362 case XML_SCHEMA_FACET_WHITESPACE:
15363 /*
15364 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015365 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015366 */
15367 case XML_SCHEMA_FACET_PATTERN:
15368 case XML_SCHEMA_FACET_ENUMERATION:
15369 break;
15370 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015371 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015372 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015373 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015374 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015375 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015376 * invalid facets.
15377 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015378 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015379 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015380 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015381 facet = facet->next;
15382 } while (facet != NULL);
15383 if (ok == 0)
15384 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15385 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015386 * SPEC (2.3.2.5) (same as 1.3.2)
15387 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015388 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015389 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015390 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015391 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015392 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015393 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015394 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015395 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015396 * atomic or list.
15397 */
15398 xmlSchemaTypeLinkPtr member;
15399
15400 member = type->memberTypes;
15401 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015402 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015403 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015404
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015405 if ((! WXS_IS_ATOMIC(member->type)) &&
15406 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015407 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015408 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015409 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015410 "The member type '%s' is neither an atomic, nor a list type",
15411 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015412 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015413 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15414 }
15415 member = member->next;
15416 }
15417 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015418 * 3.3.1 If the {base type definition} is the ·simple ur-type
15419 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015420 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015421 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015422 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015423 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 * {final} which does not contain union.
15425 */
15426 member = type->memberTypes;
15427 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015428 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015429 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015430 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015431 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015432 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015433 "The 'final' of member type '%s' contains 'union'",
15434 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015436 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15437 }
15438 member = member->next;
15439 }
15440 /*
15441 * 3.3.1.2 The {facets} must be empty.
15442 */
15443 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015444 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015445 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015446 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015447 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015448 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15449 }
15450 } else {
15451 /*
15452 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015453 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015454 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015455 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015456 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015457 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015458 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015459 "The base type '%s' is not a union type",
15460 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015461 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015462 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15463 }
15464 /*
15465 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015468 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015469 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015470 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015471 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015472 "The 'final' of its base type '%s' must not contain 'restriction'",
15473 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015475 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15476 }
15477 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015478 * 3.3.2.3 The {member type definitions}, in order, must be validly
15479 * derived from the corresponding type definitions in the {base
15480 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015481 * as defined in Type Derivation OK (Simple) (§3.14.6).
15482 */
15483 {
15484 xmlSchemaTypeLinkPtr baseMember;
15485
15486 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015487 * OPTIMIZE: if the type is restricting, it has no local defined
15488 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015489 * thus a check for equality can be skipped.
15490 */
15491 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015492 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015493 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015494 * types of it's base type. This check seems not necessary with
15495 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015496 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015497 */
15498 if (type->memberTypes != NULL) {
15499 member = type->memberTypes;
15500 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015501 if ((member == NULL) && (baseMember != NULL)) {
15502 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15503 "different number of member types in base");
15504 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015505 while (member != NULL) {
15506 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015507 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15508 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015509 }
15510 if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015511 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015512 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015513 xmlChar *strBMT = NULL, *strBT = NULL;
15514
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015515 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015516 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015517 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015518 "The member type %s is not validly "
15519 "derived from its corresponding member "
15520 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015521 xmlSchemaGetComponentQName(&str, member->type),
15522 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15523 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015524 FREE_AND_NULL(str)
15525 FREE_AND_NULL(strBMT)
15526 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015527 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015528 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015529 member = member->next;
15530 baseMember = baseMember->next;
15531 }
15532 }
15533 }
15534 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015535 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015536 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015537 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015538 if (type->facets != NULL) {
15539 xmlSchemaFacetPtr facet;
15540 int ok = 1;
15541
15542 facet = type->facets;
15543 do {
15544 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15545 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015546 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015547 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015548 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015549 ok = 0;
15550 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015551 facet = facet->next;
15552 } while (facet != NULL);
15553 if (ok == 0)
15554 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015555
Daniel Veillard01fa6152004-06-29 17:04:39 +000015556 }
15557 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015558 * SPEC (3.3.2.5) (same as 1.3.2)
15559 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015560 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015561 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015562 */
15563 }
15564 }
15565
15566 return (0);
15567}
15568
15569/**
15570 * xmlSchemaCheckSRCSimpleType:
15571 * @ctxt: the schema parser context
15572 * @type: the simple type definition
15573 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015574 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015575 *
15576 * Returns 0 if the constraints are satisfied,
15577 * if not a positive error code and -1 on internal
15578 * errors.
15579 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015580#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015581static int
15582xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15583 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015584{
15585 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015586 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015587 * must satisfy the conditions set out in Constraints on Simple Type
15588 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015589 */
15590 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015591 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015592 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015593 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015594 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015595 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015596 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015597 /*
15598 *
15599 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015600 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015601 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015602 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015603 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015604 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015605 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015606 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015607 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015608 /*
15609 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015610 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015611 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015612 return (0);
15613}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015614#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015615
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015616static int
15617xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15618{
15619 if (ctxt->vctxt == NULL) {
15620 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15621 if (ctxt->vctxt == NULL) {
15622 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015623 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015624 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015625 "failed to create a temp. validation context.\n",
15626 NULL, NULL);
15627 return (-1);
15628 }
15629 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015630 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015631 ctxt->error, ctxt->warning, ctxt->errCtxt);
15632 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15633 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015634 }
15635 return (0);
15636}
15637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015638static int
15639xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15640 xmlNodePtr node,
15641 xmlSchemaTypePtr type,
15642 const xmlChar *value,
15643 xmlSchemaValPtr *retVal,
15644 int fireErrors,
15645 int normalize,
15646 int isNormalized);
15647
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015648/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015649 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015650 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015651 * @type: the simple type definition
15652 * @value: the default value
15653 * @node: an optional node (the holder of the value)
15654 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015655 * Schema Component Constraint: Element Default Valid (Immediate)
15656 * (cos-valid-default)
15657 * This will be used by the parser only. For the validator there's
15658 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015659 *
15660 * Returns 0 if the constraints are satisfied,
15661 * if not, a positive error code and -1 on internal
15662 * errors.
15663 */
15664static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015665xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15666 xmlNodePtr node,
15667 xmlSchemaTypePtr type,
15668 const xmlChar *value,
15669 xmlSchemaValPtr *val)
15670{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015671 int ret = 0;
15672
15673 /*
15674 * cos-valid-default:
15675 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015676 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015677 * definition the appropriate case among the following must be true:
15678 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015679 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015680 /*
15681 * Complex type.
15682 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015683 * SPEC (2.1) "its {content type} must be a simple type definition
15684 * or mixed."
15685 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015686 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015687 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015688 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015689 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15690 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015691 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015692 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015693 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015694 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015695 "For a string to be a valid default, the type definition "
15696 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015697 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015698 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15699 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015700 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015701 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015702 * 1 If the type definition is a simple type definition, then the string
15703 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015704 * Valid (§3.14.4).
15705 *
15706 * AND
15707 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015708 * 2.2.1 If the {content type} is a simple type definition, then the
15709 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015710 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015711 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015712 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015713 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015714 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015715 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015716 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015717 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015718 else
15719 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015720
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 if (ret < 0) {
15722 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15723 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015724 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015725
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015726 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015727}
15728
15729/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015730 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015731 * @ctxt: the schema parser context
15732 * @type: the complex type definition
15733 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 *.(4.6) Constraints on Complex Type Definition Schema Components
15735 * Schema Component Constraint:
15736 * Complex Type Definition Properties Correct (ct-props-correct)
15737 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015738 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015739 * Returns 0 if the constraints are satisfied, a positive
15740 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015741 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015742static int
15743xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15744 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015745{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 /*
15747 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15748 *
15749 * SPEC (1) "The values of the properties of a complex type definition must
15750 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015751 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752 * Sub-components (§5.3)."
15753 */
15754 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015755 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015756 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015757 /*
15758 * SPEC (2) "If the {base type definition} is a simple type definition,
15759 * the {derivation method} must be extension."
15760 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015761 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015763 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015764 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015765 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015766 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015767 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015768 /*
15769 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15770 * definition·. That is, it must be possible to reach the ·ur-type
15771 * definition by repeatedly following the {base type definition}."
15772 *
15773 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015775 /*
15776 * NOTE that (4) and (5) need the following:
15777 * - attribute uses need to be already inherited (apply attr. prohibitions)
15778 * - attribute group references need to be expanded already
15779 * - simple types need to be typefixed already
15780 */
15781 if (type->attrUses &&
15782 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15783 {
15784 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15785 xmlSchemaAttributeUsePtr use, tmp;
15786 int i, j, hasId = 0;
15787
15788 for (i = uses->nbItems -1; i >= 0; i--) {
15789 use = uses->items[i];
15790
15791 /*
15792 * SPEC ct-props-correct
15793 * (4) "Two distinct attribute declarations in the
15794 * {attribute uses} must not have identical {name}s and
15795 * {target namespace}s."
15796 */
15797 if (i > 0) {
15798 for (j = i -1; j >= 0; j--) {
15799 tmp = uses->items[j];
15800 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15801 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15802 (WXS_ATTRUSE_DECL_TNS(use) ==
15803 WXS_ATTRUSE_DECL_TNS(tmp)))
15804 {
15805 xmlChar *str = NULL;
15806
15807 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15808 XML_SCHEMAP_AG_PROPS_CORRECT,
15809 NULL, WXS_BASIC_CAST type,
15810 "Duplicate %s",
15811 xmlSchemaGetComponentDesignation(&str, use),
15812 NULL);
15813 FREE_AND_NULL(str);
15814 /*
15815 * Remove the duplicate.
15816 */
15817 if (xmlSchemaItemListRemove(uses, i) == -1)
15818 goto exit_failure;
15819 goto next_use;
15820 }
15821 }
15822 }
15823 /*
15824 * SPEC ct-props-correct
15825 * (5) "Two distinct attribute declarations in the
15826 * {attribute uses} must not have {type definition}s which
15827 * are or are derived from ID."
15828 */
15829 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15830 if (xmlSchemaIsDerivedFromBuiltInType(
15831 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15832 {
15833 if (hasId) {
15834 xmlChar *str = NULL;
15835
15836 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15837 XML_SCHEMAP_AG_PROPS_CORRECT,
15838 NULL, WXS_BASIC_CAST type,
15839 "There must not exist more than one attribute "
15840 "declaration of type 'xs:ID' "
15841 "(or derived from 'xs:ID'). The %s violates this "
15842 "constraint",
15843 xmlSchemaGetComponentDesignation(&str, use),
15844 NULL);
15845 FREE_AND_NULL(str);
15846 if (xmlSchemaItemListRemove(uses, i) == -1)
15847 goto exit_failure;
15848 }
15849
15850 hasId = 1;
15851 }
15852 }
15853next_use: {}
15854 }
15855 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015856 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015857exit_failure:
15858 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015859}
15860
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015861static int
15862xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15863 xmlSchemaTypePtr typeB)
15864{
15865 /*
15866 * TODO: This should implement component-identity
15867 * in the future.
15868 */
15869 if ((typeA == NULL) || (typeB == NULL))
15870 return (0);
15871 return (typeA == typeB);
15872}
15873
15874/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015875 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015876 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015877 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015878 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015879 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015880 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015881 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015882 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15883 *
15884 * STATUS: completed
15885 *
15886 * Returns 0 if the constraints are satisfied, or 1
15887 * if not.
15888 */
15889static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015890xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015891 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015892 xmlSchemaTypePtr baseType,
15893 int set)
15894{
15895 int equal = xmlSchemaAreEqualTypes(type, baseType);
15896 /* TODO: Error codes. */
15897 /*
15898 * SPEC "For a complex type definition (call it D, for derived)
15899 * to be validly derived from a type definition (call this
15900 * B, for base) given a subset of {extension, restriction}
15901 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015902 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015903 if (! equal) {
15904 /*
15905 * SPEC (1) "If B and D are not the same type definition, then the
15906 * {derivation method} of D must not be in the subset."
15907 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015908 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15909 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015910 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015911 } else {
15912 /*
15913 * SPEC (2.1) "B and D must be the same type definition."
15914 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015915 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015916 }
15917 /*
15918 * SPEC (2.2) "B must be D's {base type definition}."
15919 */
15920 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015921 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015922 /*
15923 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15924 * definition·."
15925 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015926 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015927 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015928
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015929 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015930 /*
15931 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15932 * must be validly derived from B given the subset as defined by this
15933 * constraint."
15934 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015935 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015936 baseType, set));
15937 } else {
15938 /*
15939 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15940 * must be validly derived from B given the subset as defined in Type
15941 * Derivation OK (Simple) (§3.14.6).
15942 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015943 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015944 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015945 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015946}
15947
15948/**
15949 * xmlSchemaCheckCOSDerivedOK:
15950 * @type: the derived simple type definition
15951 * @baseType: the base type definition
15952 *
15953 * Calls:
15954 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015955 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015956 * Checks wheter @type can be validly derived from @baseType.
15957 *
15958 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015959 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015960static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015961xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015962 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015963 xmlSchemaTypePtr baseType,
15964 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015965{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015966 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015967 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015968 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015969 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015970}
15971
William M. Brack2f2a6632004-08-20 23:09:47 +000015972/**
15973 * xmlSchemaCheckCOSCTExtends:
15974 * @ctxt: the schema parser context
15975 * @type: the complex type definition
15976 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015977 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015978 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015979 * Derivation Valid (Extension) (cos-ct-extends)
15980 *
15981 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015982 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015983 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015984 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015985 *
15986 * Returns 0 if the constraints are satisfied, a positive
15987 * error code if not and -1 if an internal error occured.
15988 */
15989static int
15990xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15991 xmlSchemaTypePtr type)
15992{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 xmlSchemaTypePtr base = type->baseType;
15994 /*
15995 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15996 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015997 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 /*
15999 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016000 * then all of the following must be true:"
16001 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016002 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016003 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016004 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016005 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016006 */
16007 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16008 xmlSchemaPCustomErr(ctxt,
16009 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016010 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016011 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016012 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016013 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16014 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016015
16016 /*
16017 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16018 * since they are automatically satisfied through the
16019 * inheriting mechanism.
16020 * Note that even if redefining components, the inheriting mechanism
16021 * is used.
16022 */
16023#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016024 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016025 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016026 * uses}
16027 * of the complex type definition itself, that is, for every attribute
16028 * use in the {attribute uses} of the {base type definition}, there
16029 * must be an attribute use in the {attribute uses} of the complex
16030 * type definition itself whose {attribute declaration} has the same
16031 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016032 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016033 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016034 if (base->attrUses != NULL) {
16035 int i, j, found;
16036 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016037
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016038 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16039 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16040 found = 0;
16041 if (type->attrUses != NULL) {
16042 use = (WXS_LIST_CAST type->attrUses)->items[j];
16043 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16044 {
16045 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16046 WXS_ATTRUSE_DECL_NAME(buse)) &&
16047 (WXS_ATTRUSE_DECL_TNS(use) ==
16048 WXS_ATTRUSE_DECL_TNS(buse)) &&
16049 (WXS_ATTRUSE_TYPEDEF(use) ==
16050 WXS_ATTRUSE_TYPEDEF(buse))
16051 {
16052 found = 1;
16053 break;
16054 }
16055 }
16056 }
16057 if (! found) {
16058 xmlChar *str = NULL;
16059
16060 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16061 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16062 NULL, WXS_BASIC_CAST type,
16063 /*
16064 * TODO: The report does not indicate that also the
16065 * type needs to be the same.
16066 */
16067 "This type is missing a matching correspondent "
16068 "for its {base type}'s %s in its {attribute uses}",
16069 xmlSchemaGetComponentDesignation(&str,
16070 buse->children),
16071 NULL);
16072 FREE_AND_NULL(str)
16073 }
16074 }
16075 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016076 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016077 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16078 * definition must also have one, and the base type definition's
16079 * {attribute wildcard}'s {namespace constraint} must be a subset
16080 * of the complex type definition's {attribute wildcard}'s {namespace
16081 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016082 */
16083
16084 /*
16085 * MAYBE TODO: Enable if ever needed. But this will be needed only
16086 * if created the type via a schema construction API.
16087 */
16088 if (base->attributeWildcard != NULL) {
16089 if (type->attributeWilcard == NULL) {
16090 xmlChar *str = NULL;
16091
16092 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16093 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16094 NULL, type,
16095 "The base %s has an attribute wildcard, "
16096 "but this type is missing an attribute wildcard",
16097 xmlSchemaGetComponentDesignation(&str, base));
16098 FREE_AND_NULL(str)
16099
16100 } else if (xmlSchemaCheckCOSNSSubset(
16101 base->attributeWildcard, type->attributeWildcard))
16102 {
16103 xmlChar *str = NULL;
16104
16105 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16106 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16107 NULL, type,
16108 "The attribute wildcard is not a valid "
16109 "superset of the one in the base %s",
16110 xmlSchemaGetComponentDesignation(&str, base));
16111 FREE_AND_NULL(str)
16112 }
16113 }
16114#endif
16115 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016117 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016118 if ((type->contentTypeDef != NULL) &&
16119 (type->contentTypeDef == base->contentTypeDef)) {
16120 /*
16121 * SPEC (1.4.1) "The {content type} of the {base type definition}
16122 * and the {content type} of the complex type definition itself
16123 * must be the same simple type definition"
16124 * PASS
16125 */
16126 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16127 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16128 /*
16129 * SPEC (1.4.2) "The {content type} of both the {base type
16130 * definition} and the complex type definition itself must
16131 * be empty."
16132 * PASS
16133 */
16134 } else {
16135 /*
16136 * SPEC (1.4.3) "All of the following must be true:"
16137 */
16138 if (type->subtypes == NULL) {
16139 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016140 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016141 * definition itself must specify a particle.
16142 */
16143 xmlSchemaPCustomErr(ctxt,
16144 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016145 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016146 "The content type must specify a particle", NULL);
16147 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16148 }
16149 /*
16150 * SPEC (1.4.3.2) "One of the following must be true:"
16151 */
16152 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16153 /*
16154 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16155 * definition} must be empty.
16156 * PASS
16157 */
16158 } else {
16159 /*
16160 * SPEC (1.4.3.2.2) "All of the following must be true:"
16161 */
16162 if ((type->contentType != base->contentType) ||
16163 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16164 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16165 /*
16166 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16167 * or both must be element-only."
16168 */
16169 xmlSchemaPCustomErr(ctxt,
16170 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016171 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016172 "The content type of both, the type and its base "
16173 "type, must either 'mixed' or 'element-only'", NULL);
16174 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016175 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016177 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 * complex type definition must be a ·valid extension·
16179 * of the {base type definition}'s particle, as defined
16180 * in Particle Valid (Extension) (§3.9.6)."
16181 *
16182 * NOTE that we won't check "Particle Valid (Extension)",
16183 * since it is ensured by the derivation process in
16184 * xmlSchemaTypeFixup(). We need to implement this when heading
16185 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016186 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016187 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016188 }
16189 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016190 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016191 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016193 } else {
16194 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016195 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016196 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016197 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016198 if (type->contentTypeDef != base) {
16199 /*
16200 * SPEC (2.1) "The {content type} must be the same simple type
16201 * definition."
16202 */
16203 xmlSchemaPCustomErr(ctxt,
16204 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016205 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016206 "The content type must be the simple base type", NULL);
16207 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16208 }
16209 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16210 /*
16211 * SPEC (2.2) "The {final} of the {base type definition} must not
16212 * contain extension"
16213 * NOTE that this is the same as (1.1).
16214 */
16215 xmlSchemaPCustomErr(ctxt,
16216 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016217 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016218 "The 'final' of the base type definition "
16219 "contains 'extension'", NULL);
16220 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016221 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016222 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016223 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016224}
16225
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226/**
16227 * xmlSchemaCheckDerivationOKRestriction:
16228 * @ctxt: the schema parser context
16229 * @type: the complex type definition
16230 *
16231 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016232 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016233 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16234 *
16235 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016237 * (5.4.2) ???
16238 *
16239 * ATTENTION:
16240 * In XML Schema 1.1 this will be:
16241 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 *
16243 * Returns 0 if the constraints are satisfied, a positive
16244 * error code if not and -1 if an internal error occured.
16245 */
16246static int
16247xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16248 xmlSchemaTypePtr type)
16249{
16250 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016251
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016253 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016254 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016255 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016256 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016257 if (! WXS_IS_COMPLEX(base)) {
16258 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16259 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16260 type->node, WXS_BASIC_CAST type,
16261 "The base type must be a complex type", NULL, NULL);
16262 return(ctxt->err);
16263 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16265 /*
16266 * SPEC (1) "The {base type definition} must be a complex type
16267 * definition whose {final} does not contain restriction."
16268 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016269 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16270 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16271 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016272 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016273 "contains 'restriction'", NULL, NULL);
16274 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016275 }
16276 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016277 * SPEC (2), (3) and (4)
16278 * Those are handled in a separate function, since the
16279 * same constraints are needed for redefinition of
16280 * attribute groups as well.
16281 */
16282 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16283 XML_SCHEMA_ACTION_DERIVE,
16284 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16285 type->attrUses, base->attrUses,
16286 type->attributeWildcard,
16287 base->attributeWildcard) == -1)
16288 {
16289 return(-1);
16290 }
16291 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016292 * SPEC (5) "One of the following must be true:"
16293 */
16294 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16295 /*
16296 * SPEC (5.1) "The {base type definition} must be the
16297 * ·ur-type definition·."
16298 * PASS
16299 */
16300 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16301 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16302 /*
16303 * SPEC (5.2.1) "The {content type} of the complex type definition
16304 * must be a simple type definition"
16305 *
16306 * SPEC (5.2.2) "One of the following must be true:"
16307 */
16308 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016309 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16310 {
16311 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016312 /*
16313 * SPEC (5.2.2.1) "The {content type} of the {base type
16314 * definition} must be a simple type definition from which
16315 * the {content type} is validly derived given the empty
16316 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016317 *
16318 * ATTENTION TODO: This seems not needed if the type implicitely
16319 * derived from the base type.
16320 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016321 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016322 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16323 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016324 if (err != 0) {
16325 xmlChar *strA = NULL, *strB = NULL;
16326
16327 if (err == -1)
16328 return(-1);
16329 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16330 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16331 NULL, WXS_BASIC_CAST type,
16332 "The {content type} %s is not validly derived from the "
16333 "base type's {content type} %s",
16334 xmlSchemaGetComponentDesignation(&strA,
16335 type->contentTypeDef),
16336 xmlSchemaGetComponentDesignation(&strB,
16337 base->contentTypeDef));
16338 FREE_AND_NULL(strA);
16339 FREE_AND_NULL(strB);
16340 return(ctxt->err);
16341 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16343 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016344 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016345 /*
16346 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16347 * and have a particle which is ·emptiable· as defined in
16348 * Particle Emptiable (§3.9.6)."
16349 * PASS
16350 */
16351 } else {
16352 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016353 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16354 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 "The content type of the base type must be either "
16356 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016357 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 }
16359 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16360 /*
16361 * SPEC (5.3.1) "The {content type} of the complex type itself must
16362 * be empty"
16363 */
16364 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16365 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016366 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016367 * definition} must also be empty."
16368 * PASS
16369 */
16370 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16371 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16372 xmlSchemaIsParticleEmptiable(
16373 (xmlSchemaParticlePtr) base->subtypes)) {
16374 /*
16375 * SPEC (5.3.2.2) "The {content type} of the {base type
16376 * definition} must be elementOnly or mixed and have a particle
16377 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16378 * PASS
16379 */
16380 } else {
16381 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016382 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16383 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 "The content type of the base type must be either "
16385 "empty or 'mixed' (or 'elements-only') and an emptiable "
16386 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016387 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 }
16389 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016390 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016391 /*
16392 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16393 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016394 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016395 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016396 /*
16397 * SPEC (5.4.1.2) "The {content type} of the complex type
16398 * definition itself and of the {base type definition} must be
16399 * mixed"
16400 */
16401 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016402 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16403 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 "If the content type is 'mixed', then the content type of the "
16405 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016406 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016407 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016408 /*
16409 * SPEC (5.4.2) "The particle of the complex type definition itself
16410 * must be a ·valid restriction· of the particle of the {content
16411 * type} of the {base type definition} as defined in Particle Valid
16412 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016413 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016414 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016416 } else {
16417 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016418 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16419 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016421 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016422 }
16423 return (0);
16424}
16425
16426/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016427 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016428 * @ctxt: the schema parser context
16429 * @type: the complex type definition
16430 *
16431 * (3.4.6) Constraints on Complex Type Definition Schema Components
16432 *
16433 * Returns 0 if the constraints are satisfied, a positive
16434 * error code if not and -1 if an internal error occured.
16435 */
16436static int
16437xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16438 xmlSchemaTypePtr type)
16439{
16440 int ret;
16441 /*
16442 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016444 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16445 if (ret != 0)
16446 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016447 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016448 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16449 else
16450 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16451 return (ret);
16452}
16453
16454/**
16455 * xmlSchemaCheckSRCCT:
16456 * @ctxt: the schema parser context
16457 * @type: the complex type definition
16458 *
16459 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016460 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016461 * Complex Type Definition Representation OK (src-ct)
16462 *
16463 * Returns 0 if the constraints are satisfied, a positive
16464 * error code if not and -1 if an internal error occured.
16465 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016466static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016467xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016468 xmlSchemaTypePtr type)
16469{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016470 xmlSchemaTypePtr base;
16471 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016472
16473 /*
16474 * TODO: Adjust the error codes here, as I used
16475 * XML_SCHEMAP_SRC_CT_1 only yet.
16476 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016477 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016478 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016479 /*
16480 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016482 * must be a complex type definition;
16483 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016484 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016485 xmlChar *str = NULL;
16486 xmlSchemaPCustomErr(ctxt,
16487 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016488 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016489 "If using <complexContent>, the base type is expected to be "
16490 "a complex type. The base type '%s' is a simple type",
16491 xmlSchemaFormatQName(&str, base->targetNamespace,
16492 base->name));
16493 FREE_AND_NULL(str)
16494 return (XML_SCHEMAP_SRC_CT_1);
16495 }
16496 } else {
16497 /*
16498 * SPEC
16499 * 2 If the <simpleContent> alternative is chosen, all of the
16500 * following must be true:
16501 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16502 * base [attribute] must be one of the following:
16503 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016504 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016505 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016506 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016507 /*
16508 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016509 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016510 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016511 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016512 xmlSchemaPCustomErr(ctxt,
16513 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016514 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016515 "If using <simpleContent> and <restriction>, the base "
16516 "type must be a complex type. The base type '%s' is "
16517 "a simple type",
16518 xmlSchemaFormatQName(&str, base->targetNamespace,
16519 base->name));
16520 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016521 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016523 } else {
16524 /* Base type is a complex type. */
16525 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16526 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16527 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016528 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016529 * simple type definition;
16530 * PASS
16531 */
16532 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016533 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016534 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016535 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016536 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016537 type->name);
16538 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016539 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016540 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016541 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016542
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016543 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016544 * 2.1.2 only if the <restriction> alternative is also
16545 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016546 * is mixed and a particle emptiable.
16547 */
16548 if (! xmlSchemaIsParticleEmptiable(
16549 (xmlSchemaParticlePtr) base->subtypes)) {
16550 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016551 } else
16552 /*
16553 * Attention: at this point the <simpleType> child is in
16554 * ->contentTypeDef (put there during parsing).
16555 */
16556 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016557 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016558 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016559 * 2.2 If clause 2.1.2 above is satisfied, then there
16560 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016561 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016562 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016563 /* TODO: Change error code to ..._SRC_CT_2_2. */
16564 xmlSchemaPCustomErr(ctxt,
16565 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016566 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016567 "A <simpleType> is expected among the children "
16568 "of <restriction>, if <simpleContent> is used and "
16569 "the base type '%s' is a complex type",
16570 xmlSchemaFormatQName(&str, base->targetNamespace,
16571 base->name));
16572 FREE_AND_NULL(str)
16573 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016574 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016575 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016576 ret = XML_SCHEMAP_SRC_CT_1;
16577 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016578 }
16579 if (ret > 0) {
16580 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016581 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016582 xmlSchemaPCustomErr(ctxt,
16583 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016584 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016585 "If <simpleContent> and <restriction> is used, the "
16586 "base type must be a simple type or a complex type with "
16587 "mixed content and particle emptiable. The base type "
16588 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016589 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016590 base->name));
16591 } else {
16592 xmlSchemaPCustomErr(ctxt,
16593 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016594 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016595 "If <simpleContent> and <extension> is used, the "
16596 "base type must be a simple type. The base type '%s' "
16597 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016598 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016599 base->name));
16600 }
16601 FREE_AND_NULL(str)
16602 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016603 }
16604 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016605 * SPEC (3) "The corresponding complex type definition component must
16606 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016607 * Definition Schema Components (§3.4.6);"
16608 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016609 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016610 /*
16611 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016612 * above for {attribute wildcard} is satisfied, the intensional
16613 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016614 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016615 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016616 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016617 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016618}
William M. Brack2f2a6632004-08-20 23:09:47 +000016619
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016620#ifdef ENABLE_PARTICLE_RESTRICTION
16621/**
16622 * xmlSchemaCheckParticleRangeOK:
16623 * @ctxt: the schema parser context
16624 * @type: the complex type definition
16625 *
16626 * (3.9.6) Constraints on Particle Schema Components
16627 * Schema Component Constraint:
16628 * Occurrence Range OK (range-ok)
16629 *
16630 * STATUS: complete
16631 *
16632 * Returns 0 if the constraints are satisfied, a positive
16633 * error code if not and -1 if an internal error occured.
16634 */
16635static int
16636xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16637 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016638{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016639 if (rmin < bmin)
16640 return (1);
16641 if ((bmax != UNBOUNDED) &&
16642 (rmax > bmax))
16643 return (1);
16644 return (0);
16645}
16646
16647/**
16648 * xmlSchemaCheckRCaseNameAndTypeOK:
16649 * @ctxt: the schema parser context
16650 * @r: the restricting element declaration particle
16651 * @b: the base element declaration particle
16652 *
16653 * (3.9.6) Constraints on Particle Schema Components
16654 * Schema Component Constraint:
16655 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16656 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016657 *
16658 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016659 * MISSING (3.2.3)
16660 * CLARIFY: (3.2.2)
16661 *
16662 * Returns 0 if the constraints are satisfied, a positive
16663 * error code if not and -1 if an internal error occured.
16664 */
16665static int
16666xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16667 xmlSchemaParticlePtr r,
16668 xmlSchemaParticlePtr b)
16669{
16670 xmlSchemaElementPtr elemR, elemB;
16671
16672 /* TODO: Error codes (rcase-NameAndTypeOK). */
16673 elemR = (xmlSchemaElementPtr) r->children;
16674 elemB = (xmlSchemaElementPtr) b->children;
16675 /*
16676 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16677 * the same."
16678 */
16679 if ((elemR != elemB) &&
16680 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16681 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16682 return (1);
16683 /*
16684 * SPEC (2) "R's occurrence range is a valid restriction of B's
16685 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16686 */
16687 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16688 b->minOccurs, b->maxOccurs) != 0)
16689 return (1);
16690 /*
16691 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16692 * {scope} are global."
16693 */
16694 if (elemR == elemB)
16695 return (0);
16696 /*
16697 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16698 */
16699 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16700 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16701 return (1);
16702 /*
16703 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16704 * or is not fixed, or R's declaration's {value constraint} is fixed
16705 * with the same value."
16706 */
16707 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16708 ((elemR->value == NULL) ||
16709 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16710 /* TODO: Equality of the initial value or normalized or canonical? */
16711 (! xmlStrEqual(elemR->value, elemB->value))))
16712 return (1);
16713 /*
16714 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16715 * definitions} is a subset of B's declaration's {identity-constraint
16716 * definitions}, if any."
16717 */
16718 if (elemB->idcs != NULL) {
16719 /* TODO */
16720 }
16721 /*
16722 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16723 * superset of B's declaration's {disallowed substitutions}."
16724 */
16725 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16726 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16727 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16728 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16729 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16730 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16731 return (1);
16732 /*
16733 * SPEC (3.2.5) "R's {type definition} is validly derived given
16734 * {extension, list, union} from B's {type definition}"
16735 *
16736 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16737 * set, if the corresponding constraints handle "restriction" and
16738 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016739 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016740 */
16741 {
16742 int set = 0;
16743
16744 set |= SUBSET_EXTENSION;
16745 set |= SUBSET_LIST;
16746 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016747 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016748 elemB->subtypes, set) != 0)
16749 return (1);
16750 }
16751 return (0);
16752}
16753
16754/**
16755 * xmlSchemaCheckRCaseNSCompat:
16756 * @ctxt: the schema parser context
16757 * @r: the restricting element declaration particle
16758 * @b: the base wildcard particle
16759 *
16760 * (3.9.6) Constraints on Particle Schema Components
16761 * Schema Component Constraint:
16762 * Particle Derivation OK (Elt:Any -- NSCompat)
16763 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016764 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016765 * STATUS: complete
16766 *
16767 * Returns 0 if the constraints are satisfied, a positive
16768 * error code if not and -1 if an internal error occured.
16769 */
16770static int
16771xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16772 xmlSchemaParticlePtr r,
16773 xmlSchemaParticlePtr b)
16774{
16775 /* TODO:Error codes (rcase-NSCompat). */
16776 /*
16777 * SPEC "For an element declaration particle to be a ·valid restriction·
16778 * of a wildcard particle all of the following must be true:"
16779 *
16780 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16781 * with respect to the wildcard's {namespace constraint} as defined by
16782 * Wildcard allows Namespace Name (§3.10.4)."
16783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016784 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016785 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16786 return (1);
16787 /*
16788 * SPEC (2) "R's occurrence range is a valid restriction of B's
16789 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16790 */
16791 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16792 b->minOccurs, b->maxOccurs) != 0)
16793 return (1);
16794
16795 return (0);
16796}
16797
16798/**
16799 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16800 * @ctxt: the schema parser context
16801 * @r: the restricting element declaration particle
16802 * @b: the base model group particle
16803 *
16804 * (3.9.6) Constraints on Particle Schema Components
16805 * Schema Component Constraint:
16806 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16807 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016808 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016809 * STATUS: TODO
16810 *
16811 * Returns 0 if the constraints are satisfied, a positive
16812 * error code if not and -1 if an internal error occured.
16813 */
16814static int
16815xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16816 xmlSchemaParticlePtr r,
16817 xmlSchemaParticlePtr b)
16818{
16819 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16820 TODO
16821 return (0);
16822}
16823
16824/**
16825 * xmlSchemaCheckRCaseNSSubset:
16826 * @ctxt: the schema parser context
16827 * @r: the restricting wildcard particle
16828 * @b: the base wildcard particle
16829 *
16830 * (3.9.6) Constraints on Particle Schema Components
16831 * Schema Component Constraint:
16832 * Particle Derivation OK (Any:Any -- NSSubset)
16833 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016835 * STATUS: complete
16836 *
16837 * Returns 0 if the constraints are satisfied, a positive
16838 * error code if not and -1 if an internal error occured.
16839 */
16840static int
16841xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16842 xmlSchemaParticlePtr r,
16843 xmlSchemaParticlePtr b,
16844 int isAnyTypeBase)
16845{
16846 /* TODO: Error codes (rcase-NSSubset). */
16847 /*
16848 * SPEC (1) "R's occurrence range is a valid restriction of B's
16849 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16850 */
16851 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16852 b->minOccurs, b->maxOccurs))
16853 return (1);
16854 /*
16855 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16856 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16857 */
16858 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16859 (xmlSchemaWildcardPtr) b->children))
16860 return (1);
16861 /*
16862 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16863 * definition·, R's {process contents} must be identical to or stronger
16864 * than B's {process contents}, where strict is stronger than lax is
16865 * stronger than skip."
16866 */
16867 if (! isAnyTypeBase) {
16868 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16869 ((xmlSchemaWildcardPtr) b->children)->processContents)
16870 return (1);
16871 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016873 return (0);
16874}
16875
16876/**
16877 * xmlSchemaCheckCOSParticleRestrict:
16878 * @ctxt: the schema parser context
16879 * @type: the complex type definition
16880 *
16881 * (3.9.6) Constraints on Particle Schema Components
16882 * Schema Component Constraint:
16883 * Particle Valid (Restriction) (cos-particle-restrict)
16884 *
16885 * STATUS: TODO
16886 *
16887 * Returns 0 if the constraints are satisfied, a positive
16888 * error code if not and -1 if an internal error occured.
16889 */
16890static int
16891xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16892 xmlSchemaParticlePtr r,
16893 xmlSchemaParticlePtr b)
16894{
16895 int ret = 0;
16896
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016897 /*part = WXS_TYPE_PARTICLE(type);
16898 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016899 */
16900
16901 TODO
16902
16903 /*
16904 * SPEC (1) "They are the same particle."
16905 */
16906 if (r == b)
16907 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016908
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016909
16910 return (0);
16911}
16912
16913/**
16914 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16915 * @ctxt: the schema parser context
16916 * @r: the model group particle
16917 * @b: the base wildcard particle
16918 *
16919 * (3.9.6) Constraints on Particle Schema Components
16920 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016921 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016922 * NSRecurseCheckCardinality)
16923 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016924 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016925 * STATUS: TODO: subst-groups
16926 *
16927 * Returns 0 if the constraints are satisfied, a positive
16928 * error code if not and -1 if an internal error occured.
16929 */
16930static int
16931xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16932 xmlSchemaParticlePtr r,
16933 xmlSchemaParticlePtr b)
16934{
16935 xmlSchemaParticlePtr part;
16936 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16937 if ((r->children == NULL) || (r->children->children == NULL))
16938 return (-1);
16939 /*
16940 * SPEC "For a group particle to be a ·valid restriction· of a
16941 * wildcard particle..."
16942 *
16943 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016944 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016945 * Particle Valid (Restriction) (§3.9.6)."
16946 */
16947 part = (xmlSchemaParticlePtr) r->children->children;
16948 do {
16949 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16950 return (1);
16951 part = (xmlSchemaParticlePtr) part->next;
16952 } while (part != NULL);
16953 /*
16954 * SPEC (2) "The effective total range of the group [...] is a
16955 * valid restriction of B's occurrence range as defined by
16956 * Occurrence Range OK (§3.9.6)."
16957 */
16958 if (xmlSchemaCheckParticleRangeOK(
16959 xmlSchemaGetParticleTotalRangeMin(r),
16960 xmlSchemaGetParticleTotalRangeMax(r),
16961 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016962 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016963 return (0);
16964}
16965
16966/**
16967 * xmlSchemaCheckRCaseRecurse:
16968 * @ctxt: the schema parser context
16969 * @r: the <all> or <sequence> model group particle
16970 * @b: the base <all> or <sequence> model group particle
16971 *
16972 * (3.9.6) Constraints on Particle Schema Components
16973 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016974 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016975 Recurse)
16976 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016977 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016978 * STATUS: ?
16979 * TODO: subst-groups
16980 *
16981 * Returns 0 if the constraints are satisfied, a positive
16982 * error code if not and -1 if an internal error occured.
16983 */
16984static int
16985xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16986 xmlSchemaParticlePtr r,
16987 xmlSchemaParticlePtr b)
16988{
16989 /* xmlSchemaParticlePtr part; */
16990 /* TODO: Error codes (rcase-Recurse). */
16991 if ((r->children == NULL) || (b->children == NULL) ||
16992 (r->children->type != b->children->type))
16993 return (-1);
16994 /*
16995 * SPEC "For an all or sequence group particle to be a ·valid
16996 * restriction· of another group particle with the same {compositor}..."
16997 *
16998 * SPEC (1) "R's occurrence range is a valid restriction of B's
16999 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
17000 */
17001 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17002 b->minOccurs, b->maxOccurs))
17003 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017004
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017005
17006 return (0);
17007}
17008
17009#endif
17010
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017011#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17012 xmlSchemaPCustomErrExt(pctxt, \
17013 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017014 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017015 "It is an error for both '%s' and '%s' to be specified on the "\
17016 "same type definition", \
17017 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17018 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17019
17020#define FACET_RESTR_ERR(fac1, msg) \
17021 xmlSchemaPCustomErr(pctxt, \
17022 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017023 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017024 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017025
17026#define FACET_RESTR_FIXED_ERR(fac) \
17027 xmlSchemaPCustomErr(pctxt, \
17028 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017029 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017030 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017031 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017032
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017033static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017034xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17035 xmlSchemaFacetPtr facet1,
17036 xmlSchemaFacetPtr facet2,
17037 int lessGreater,
17038 int orEqual,
17039 int ofBase)
17040{
17041 xmlChar *msg = NULL;
17042
17043 msg = xmlStrdup(BAD_CAST "'");
17044 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17045 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17046 if (lessGreater == 0)
17047 msg = xmlStrcat(msg, BAD_CAST " equal to");
17048 if (lessGreater == 1)
17049 msg = xmlStrcat(msg, BAD_CAST " greater than");
17050 else
17051 msg = xmlStrcat(msg, BAD_CAST " less than");
17052
17053 if (orEqual)
17054 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17055 msg = xmlStrcat(msg, BAD_CAST " '");
17056 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17057 if (ofBase)
17058 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17059 else
17060 msg = xmlStrcat(msg, BAD_CAST "'");
17061
17062 xmlSchemaPCustomErr(pctxt,
17063 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017064 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017065 (const char *) msg, NULL);
17066
17067 if (msg != NULL)
17068 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017069}
17070
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017071/*
17072* xmlSchemaDeriveAndValidateFacets:
17073*
17074* Schema Component Constraint: Simple Type Restriction (Facets)
17075* (st-restrict-facets)
17076*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017077static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017078xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17079 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017080{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017081 xmlSchemaTypePtr base = type->baseType;
17082 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017083 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017084 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17085 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17086 fmininc = NULL, fmaxinc = NULL,
17087 fminexc = NULL, fmaxexc = NULL,
17088 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17089 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17090 bfmininc = NULL, bfmaxinc = NULL,
17091 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017092 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017093
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017094 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017095 * SPEC st-restrict-facets 1:
17096 * "The {variety} of R is the same as that of B."
17097 */
17098 /*
17099 * SPEC st-restrict-facets 2:
17100 * "If {variety} is atomic, the {primitive type definition}
17101 * of R is the same as that of B."
17102 *
17103 * NOTE: we leave 1 & 2 out for now, since this will be
17104 * satisfied by the derivation process.
17105 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17106 */
17107 /*
17108 * SPEC st-restrict-facets 3:
17109 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110 * of B, eliminating duplicates. To eliminate duplicates,
17111 * when a facet of the same kind occurs in both S and the
17112 * {facets} of B, the one in the {facets} of B is not
17113 * included, with the exception of enumeration and pattern
17114 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017115 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017116 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017117
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017118 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17119 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017120
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017121 last = type->facetSet;
17122 if (last != NULL)
17123 while (last->next != NULL)
17124 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017125
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017126 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17127 facet = cur->facet;
17128 switch (facet->type) {
17129 case XML_SCHEMA_FACET_LENGTH:
17130 flength = facet; break;
17131 case XML_SCHEMA_FACET_MINLENGTH:
17132 fminlen = facet; break;
17133 case XML_SCHEMA_FACET_MININCLUSIVE:
17134 fmininc = facet; break;
17135 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17136 fminexc = facet; break;
17137 case XML_SCHEMA_FACET_MAXLENGTH:
17138 fmaxlen = facet; break;
17139 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17140 fmaxinc = facet; break;
17141 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17142 fmaxexc = facet; break;
17143 case XML_SCHEMA_FACET_TOTALDIGITS:
17144 ftotdig = facet; break;
17145 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17146 ffracdig = facet; break;
17147 default:
17148 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017149 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017150 }
17151 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17152 facet = cur->facet;
17153 switch (facet->type) {
17154 case XML_SCHEMA_FACET_LENGTH:
17155 bflength = facet; break;
17156 case XML_SCHEMA_FACET_MINLENGTH:
17157 bfminlen = facet; break;
17158 case XML_SCHEMA_FACET_MININCLUSIVE:
17159 bfmininc = facet; break;
17160 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17161 bfminexc = facet; break;
17162 case XML_SCHEMA_FACET_MAXLENGTH:
17163 bfmaxlen = facet; break;
17164 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17165 bfmaxinc = facet; break;
17166 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17167 bfmaxexc = facet; break;
17168 case XML_SCHEMA_FACET_TOTALDIGITS:
17169 bftotdig = facet; break;
17170 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17171 bffracdig = facet; break;
17172 default:
17173 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017174 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017175 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017176 /*
17177 * length and minLength or maxLength (2.2) + (3.2)
17178 */
17179 if (flength && (fminlen || fmaxlen)) {
17180 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17181 "either of 'minLength' or 'maxLength' to be specified on "
17182 "the same type definition")
17183 }
17184 /*
17185 * Mutual exclusions in the same derivation step.
17186 */
17187 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017188 /*
17189 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017190 */
17191 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17192 }
17193 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017194 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017195 * SCC "minInclusive and minExclusive"
17196 */
17197 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017198 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017199
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017200 if (flength && bflength) {
17201 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017202 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017203 * The values have to be equal.
17204 */
17205 res = xmlSchemaCompareValues(flength->val, bflength->val);
17206 if (res == -2)
17207 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017208 if (res != 0)
17209 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17210 if ((res != 0) && (bflength->fixed)) {
17211 FACET_RESTR_FIXED_ERR(flength)
17212 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017213
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017214 }
17215 if (fminlen && bfminlen) {
17216 /*
17217 * SCC "minLength valid restriction"
17218 * minLength >= BASE minLength
17219 */
17220 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17221 if (res == -2)
17222 goto internal_error;
17223 if (res == -1)
17224 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17225 if ((res != 0) && (bfminlen->fixed)) {
17226 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017228 }
17229 if (fmaxlen && bfmaxlen) {
17230 /*
17231 * SCC "maxLength valid restriction"
17232 * maxLength <= BASE minLength
17233 */
17234 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17235 if (res == -2)
17236 goto internal_error;
17237 if (res == 1)
17238 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17239 if ((res != 0) && (bfmaxlen->fixed)) {
17240 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017241 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017242 }
17243 /*
17244 * SCC "length and minLength or maxLength"
17245 */
17246 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017247 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017248 if (flength) {
17249 if (! fminlen)
17250 flength = bflength;
17251 if (fminlen) {
17252 /* (1.1) length >= minLength */
17253 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17254 if (res == -2)
17255 goto internal_error;
17256 if (res == -1)
17257 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17258 }
17259 if (! fmaxlen)
17260 fmaxlen = bfmaxlen;
17261 if (fmaxlen) {
17262 /* (2.1) length <= maxLength */
17263 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17264 if (res == -2)
17265 goto internal_error;
17266 if (res == 1)
17267 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17268 }
17269 }
17270 if (fmaxinc) {
17271 /*
17272 * "maxInclusive"
17273 */
17274 if (fmininc) {
17275 /* SCC "maxInclusive >= minInclusive" */
17276 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17277 if (res == -2)
17278 goto internal_error;
17279 if (res == -1) {
17280 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17281 }
17282 }
17283 /*
17284 * SCC "maxInclusive valid restriction"
17285 */
17286 if (bfmaxinc) {
17287 /* maxInclusive <= BASE maxInclusive */
17288 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17289 if (res == -2)
17290 goto internal_error;
17291 if (res == 1)
17292 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17293 if ((res != 0) && (bfmaxinc->fixed)) {
17294 FACET_RESTR_FIXED_ERR(fmaxinc)
17295 }
17296 }
17297 if (bfmaxexc) {
17298 /* maxInclusive < BASE maxExclusive */
17299 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17300 if (res == -2)
17301 goto internal_error;
17302 if (res != -1) {
17303 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17304 }
17305 }
17306 if (bfmininc) {
17307 /* maxInclusive >= BASE minInclusive */
17308 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17309 if (res == -2)
17310 goto internal_error;
17311 if (res == -1) {
17312 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17313 }
17314 }
17315 if (bfminexc) {
17316 /* maxInclusive > BASE minExclusive */
17317 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17318 if (res == -2)
17319 goto internal_error;
17320 if (res != 1) {
17321 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17322 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017323 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017324 }
17325 if (fmaxexc) {
17326 /*
17327 * "maxExclusive >= minExclusive"
17328 */
17329 if (fminexc) {
17330 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17331 if (res == -2)
17332 goto internal_error;
17333 if (res == -1) {
17334 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17335 }
17336 }
17337 /*
17338 * "maxExclusive valid restriction"
17339 */
17340 if (bfmaxexc) {
17341 /* maxExclusive <= BASE maxExclusive */
17342 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17343 if (res == -2)
17344 goto internal_error;
17345 if (res == 1) {
17346 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17347 }
17348 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017349 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017350 }
17351 }
17352 if (bfmaxinc) {
17353 /* maxExclusive <= BASE maxInclusive */
17354 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17355 if (res == -2)
17356 goto internal_error;
17357 if (res == 1) {
17358 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17359 }
17360 }
17361 if (bfmininc) {
17362 /* maxExclusive > BASE minInclusive */
17363 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17364 if (res == -2)
17365 goto internal_error;
17366 if (res != 1) {
17367 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17368 }
17369 }
17370 if (bfminexc) {
17371 /* maxExclusive > BASE minExclusive */
17372 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17373 if (res == -2)
17374 goto internal_error;
17375 if (res != 1) {
17376 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17377 }
17378 }
17379 }
17380 if (fminexc) {
17381 /*
17382 * "minExclusive < maxInclusive"
17383 */
17384 if (fmaxinc) {
17385 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17386 if (res == -2)
17387 goto internal_error;
17388 if (res != -1) {
17389 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17390 }
17391 }
17392 /*
17393 * "minExclusive valid restriction"
17394 */
17395 if (bfminexc) {
17396 /* minExclusive >= BASE minExclusive */
17397 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17398 if (res == -2)
17399 goto internal_error;
17400 if (res == -1) {
17401 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17402 }
17403 if ((res != 0) && (bfminexc->fixed)) {
17404 FACET_RESTR_FIXED_ERR(fminexc)
17405 }
17406 }
17407 if (bfmaxinc) {
17408 /* minExclusive <= BASE maxInclusive */
17409 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17410 if (res == -2)
17411 goto internal_error;
17412 if (res == 1) {
17413 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17414 }
17415 }
17416 if (bfmininc) {
17417 /* minExclusive >= BASE minInclusive */
17418 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17419 if (res == -2)
17420 goto internal_error;
17421 if (res == -1) {
17422 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17423 }
17424 }
17425 if (bfmaxexc) {
17426 /* minExclusive < BASE maxExclusive */
17427 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17428 if (res == -2)
17429 goto internal_error;
17430 if (res != -1) {
17431 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17432 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017434 }
17435 if (fmininc) {
17436 /*
17437 * "minInclusive < maxExclusive"
17438 */
17439 if (fmaxexc) {
17440 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17441 if (res == -2)
17442 goto internal_error;
17443 if (res != -1) {
17444 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17445 }
17446 }
17447 /*
17448 * "minExclusive valid restriction"
17449 */
17450 if (bfmininc) {
17451 /* minInclusive >= BASE minInclusive */
17452 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17453 if (res == -2)
17454 goto internal_error;
17455 if (res == -1) {
17456 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17457 }
17458 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017459 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017460 }
17461 }
17462 if (bfmaxinc) {
17463 /* minInclusive <= BASE maxInclusive */
17464 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17465 if (res == -2)
17466 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017467 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017468 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17469 }
17470 }
17471 if (bfminexc) {
17472 /* minInclusive > BASE minExclusive */
17473 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17474 if (res == -2)
17475 goto internal_error;
17476 if (res != 1)
17477 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17478 }
17479 if (bfmaxexc) {
17480 /* minInclusive < BASE maxExclusive */
17481 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17482 if (res == -2)
17483 goto internal_error;
17484 if (res != -1)
17485 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17486 }
17487 }
17488 if (ftotdig && bftotdig) {
17489 /*
17490 * SCC " totalDigits valid restriction"
17491 * totalDigits <= BASE totalDigits
17492 */
17493 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17494 if (res == -2)
17495 goto internal_error;
17496 if (res == 1)
17497 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17498 -1, 1, 1);
17499 if ((res != 0) && (bftotdig->fixed)) {
17500 FACET_RESTR_FIXED_ERR(ftotdig)
17501 }
17502 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017503 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017504 /*
17505 * SCC "fractionDigits valid restriction"
17506 * fractionDigits <= BASE fractionDigits
17507 */
17508 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17509 if (res == -2)
17510 goto internal_error;
17511 if (res == 1)
17512 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17513 -1, 1, 1);
17514 if ((res != 0) && (bffracdig->fixed)) {
17515 FACET_RESTR_FIXED_ERR(ffracdig)
17516 }
17517 }
17518 /*
17519 * SCC "fractionDigits less than or equal to totalDigits"
17520 */
17521 if (! ftotdig)
17522 ftotdig = bftotdig;
17523 if (! ffracdig)
17524 ffracdig = bffracdig;
17525 if (ftotdig && ffracdig) {
17526 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17527 if (res == -2)
17528 goto internal_error;
17529 if (res == 1)
17530 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17531 -1, 1, 0);
17532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017534 * *Enumerations* won' be added here, since only the first set
17535 * of enumerations in the ancestor-or-self axis is used
17536 * for validation, plus we need to use the base type of those
17537 * enumerations for whitespace.
17538 *
17539 * *Patterns*: won't be add here, since they are ORed at
17540 * type level and ANDed at ancestor level. This will
17541 * happed during validation by walking the base axis
17542 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017543 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017544 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17545 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017546 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017547 * Special handling of enumerations and patterns.
17548 * TODO: hmm, they should not appear in the set, so remove this.
17549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017550 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017551 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017552 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017553 /*
17554 * Search for a duplicate facet in the current type.
17555 */
17556 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017557 /* err = 0; */
17558 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017559 while (link != NULL) {
17560 facet = link->facet;
17561 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017563 case XML_SCHEMA_FACET_WHITESPACE:
17564 /*
17565 * The whitespace must be stronger.
17566 */
17567 if (facet->whitespace < bfacet->whitespace) {
17568 FACET_RESTR_ERR(flength,
17569 "The 'whitespace' value has to be equal to "
17570 "or stronger than the 'whitespace' value of "
17571 "the base type")
17572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017574 (facet->whitespace != bfacet->whitespace)) {
17575 FACET_RESTR_FIXED_ERR(facet)
17576 }
17577 break;
17578 default:
17579 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017580 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017581 /* Duplicate found. */
17582 break;
17583 }
17584 link = link->next;
17585 }
17586 /*
17587 * If no duplicate was found: add the base types's facet
17588 * to the set.
17589 */
17590 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017591 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017592 xmlMalloc(sizeof(xmlSchemaFacetLink));
17593 if (link == NULL) {
17594 xmlSchemaPErrMemory(pctxt,
17595 "deriving facets, creating a facet link", NULL);
17596 return (-1);
17597 }
17598 link->facet = cur->facet;
17599 link->next = NULL;
17600 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601 type->facetSet = link;
17602 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017603 last->next = link;
17604 last = link;
17605 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017606
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017607 }
17608
17609 return (0);
17610internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017611 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17612 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017613 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017614}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017615
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017616static int
17617xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17618 xmlSchemaTypePtr type)
17619{
17620 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17621 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017622 * The actual value is then formed by replacing any union type
17623 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017624 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017625 *
17626 * TODO: There's a bug entry at
17627 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17628 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017629 */
17630 link = type->memberTypes;
17631 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017632
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017633 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017634 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017635
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017636 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017637 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017638 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017639 link->type = subLink->type;
17640 if (subLink->next != NULL) {
17641 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017642 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017643 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017644 while (subLink != NULL) {
17645 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017646 xmlMalloc(sizeof(xmlSchemaTypeLink));
17647 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017648 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017649 NULL);
17650 return (-1);
17651 }
17652 newLink->type = subLink->type;
17653 prevLink->next = newLink;
17654 prevLink = newLink;
17655 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017656
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017657 subLink = subLink->next;
17658 }
17659 }
17660 }
17661 }
17662 link = link->next;
17663 }
17664 return (0);
17665}
17666
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017667static void
17668xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17669{
17670 int has = 0, needVal = 0, normVal = 0;
17671
17672 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17673 if (has) {
17674 needVal = (type->baseType->flags &
17675 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17676 normVal = (type->baseType->flags &
17677 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17678 }
17679 if (type->facets != NULL) {
17680 xmlSchemaFacetPtr fac;
17681
17682 for (fac = type->facets; fac != NULL; fac = fac->next) {
17683 switch (fac->type) {
17684 case XML_SCHEMA_FACET_WHITESPACE:
17685 break;
17686 case XML_SCHEMA_FACET_PATTERN:
17687 normVal = 1;
17688 has = 1;
17689 break;
17690 case XML_SCHEMA_FACET_ENUMERATION:
17691 needVal = 1;
17692 normVal = 1;
17693 has = 1;
17694 break;
17695 default:
17696 has = 1;
17697 break;
17698 }
17699 }
17700 }
17701 if (normVal)
17702 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17703 if (needVal)
17704 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17705 if (has)
17706 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17707
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017708 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017709 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17710 /*
17711 * OPTIMIZE VAL TODO: Some facets need a computed value.
17712 */
17713 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17714 (prim->builtInType != XML_SCHEMAS_STRING)) {
17715 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17716 }
17717 }
17718}
17719
17720static int
17721xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17722{
17723
17724
17725 /*
17726 * Evaluate the whitespace-facet value.
17727 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017728 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017729 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17730 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017731 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017732 return (0);
17733
17734 if (type->facetSet != NULL) {
17735 xmlSchemaFacetLinkPtr lin;
17736
17737 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17738 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17739 switch (lin->facet->whitespace) {
17740 case XML_SCHEMAS_FACET_PRESERVE:
17741 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17742 break;
17743 case XML_SCHEMAS_FACET_REPLACE:
17744 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17745 break;
17746 case XML_SCHEMAS_FACET_COLLAPSE:
17747 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17748 break;
17749 default:
17750 return (-1);
17751 }
17752 return (0);
17753 }
17754 }
17755 }
17756 /*
17757 * For all ·atomic· datatypes other than string (and types ·derived·
17758 * by ·restriction· from it) the value of whiteSpace is fixed to
17759 * collapse
17760 */
17761 {
17762 xmlSchemaTypePtr anc;
17763
17764 for (anc = type->baseType; anc != NULL &&
17765 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17766 anc = anc->baseType) {
17767
17768 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17769 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17770 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17771
17772 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17773 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17774 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17775
17776 } else
17777 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17778 break;
17779 }
17780 }
17781 return (0);
17782 }
17783 return (0);
17784}
17785
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017786static int
17787xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17788 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017789{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017790 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17791 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017792 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017793 return(0);
17794 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017795
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017796 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017797 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017798 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017799 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017800 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017801 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017802 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017803 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017804 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017805 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017806 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017807 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017808 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017809 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017810 * Corresponds to <simpleType><union>...
17811 */
17812 if (type->memberTypes == NULL) {
17813 /*
17814 * This one is really needed, so get out.
17815 */
17816 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17817 "union type has no member-types assigned");
17818 return(-1);
17819 }
17820 } else {
17821 /*
17822 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017823 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017824 if (type->baseType == NULL) {
17825 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17826 "type has no base-type assigned");
17827 return(-1);
17828 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017829 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017830 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17831 return(-1);
17832 /*
17833 * Variety
17834 * If the <restriction> alternative is chosen, then the
17835 * {variety} of the {base type definition}.
17836 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017837 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017838 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017839 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017840 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017841 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017842 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017843 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017844 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017845 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017846 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017847 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017848 * NOTE that we won't assign the memberTypes of the base,
17849 * since this will make trouble when freeing them; we will
17850 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017851 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017852 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017853 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017854 return(0);
17855}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017856
Daniel Veillard8651f532002-04-17 09:06:27 +000017857#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017858xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17859 xmlSchemaTypePtr type)
17860{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017861 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017862 xmlGenericError(xmlGenericErrorContext,
17863 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017864 type->node->doc->URL,
17865 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017866 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017867 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017868 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017869 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017870 switch (type->contentType) {
17871 case XML_SCHEMA_CONTENT_SIMPLE:
17872 xmlGenericError(xmlGenericErrorContext, "simple\n");
17873 break;
17874 case XML_SCHEMA_CONTENT_ELEMENTS:
17875 xmlGenericError(xmlGenericErrorContext, "elements\n");
17876 break;
17877 case XML_SCHEMA_CONTENT_UNKNOWN:
17878 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17879 break;
17880 case XML_SCHEMA_CONTENT_EMPTY:
17881 xmlGenericError(xmlGenericErrorContext, "empty\n");
17882 break;
17883 case XML_SCHEMA_CONTENT_MIXED:
17884 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017885 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017886 xmlGenericError(xmlGenericErrorContext,
17887 "mixed as emptiable particle\n");
17888 else
17889 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17890 break;
17891 /* Removed, since not used. */
17892 /*
17893 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17894 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17895 break;
17896 */
17897 case XML_SCHEMA_CONTENT_BASIC:
17898 xmlGenericError(xmlGenericErrorContext, "basic\n");
17899 break;
17900 default:
17901 xmlGenericError(xmlGenericErrorContext,
17902 "not registered !!!\n");
17903 break;
17904 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017905 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017906}
Daniel Veillard8651f532002-04-17 09:06:27 +000017907#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017908
17909/*
17910* 3.14.6 Constraints on Simple Type Definition Schema Components
17911*/
17912static int
17913xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17914 xmlSchemaTypePtr type)
17915{
17916 int res, olderrs = pctxt->nberrors;
17917
17918 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17919 return(-1);
17920
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017921 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017922 return(0);
17923
17924 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17925 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17926
17927 if (type->baseType == NULL) {
17928 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17929 "missing baseType");
17930 goto exit_failure;
17931 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017932 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017933 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017934 /*
17935 * If a member type of a union is a union itself, we need to substitute
17936 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017937 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17938 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017939 */
17940 if ((type->memberTypes != NULL) &&
17941 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17942 return(-1);
17943 /*
17944 * SPEC src-simple-type 1
17945 * "The corresponding simple type definition, if any, must satisfy
17946 * the conditions set out in Constraints on Simple Type Definition
17947 * Schema Components (§3.14.6)."
17948 */
17949 /*
17950 * Schema Component Constraint: Simple Type Definition Properties Correct
17951 * (st-props-correct)
17952 */
17953 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17954 HFAILURE HERROR
17955 /*
17956 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17957 * (cos-st-restricts)
17958 */
17959 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17960 HFAILURE HERROR
17961 /*
17962 * TODO: Removed the error report, since it got annoying to get an
17963 * extra error report, if anything failed until now.
17964 * Enable this if needed.
17965 *
17966 * xmlSchemaPErr(ctxt, type->node,
17967 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17968 * "Simple type '%s' does not satisfy the constraints "
17969 * "on simple type definitions.\n",
17970 * type->name, NULL);
17971 */
17972 /*
17973 * Schema Component Constraint: Simple Type Restriction (Facets)
17974 * (st-restrict-facets)
17975 */
17976 res = xmlSchemaCheckFacetValues(type, pctxt);
17977 HFAILURE HERROR
17978 if ((type->facetSet != NULL) ||
17979 (type->baseType->facetSet != NULL)) {
17980 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17981 HFAILURE HERROR
17982 }
17983 /*
17984 * Whitespace value.
17985 */
17986 res = xmlSchemaTypeFixupWhitespace(type);
17987 HFAILURE HERROR
17988 xmlSchemaTypeFixupOptimFacets(type);
17989
17990exit_error:
17991#ifdef DEBUG_TYPE
17992 xmlSchemaDebugFixedType(pctxt, type);
17993#endif
17994 if (olderrs != pctxt->nberrors)
17995 return(pctxt->err);
17996 return(0);
17997
17998exit_failure:
17999#ifdef DEBUG_TYPE
18000 xmlSchemaDebugFixedType(pctxt, type);
18001#endif
18002 return(-1);
18003}
18004
18005static int
18006xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18007 xmlSchemaTypePtr type)
18008{
18009 int res = 0, olderrs = pctxt->nberrors;
18010 xmlSchemaTypePtr baseType = type->baseType;
18011
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018012 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018013 return(0);
18014 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18015 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018016 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018017 "missing baseType");
18018 goto exit_failure;
18019 }
18020 /*
18021 * Fixup the base type.
18022 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018023 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018024 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018025 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18026 /*
18027 * Skip fixup if the base type is invalid.
18028 * TODO: Generate a warning!
18029 */
18030 return(0);
18031 }
18032 /*
18033 * This basically checks if the base type can be derived.
18034 */
18035 res = xmlSchemaCheckSRCCT(pctxt, type);
18036 HFAILURE HERROR
18037 /*
18038 * Fixup the content type.
18039 */
18040 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18041 /*
18042 * Corresponds to <complexType><simpleContent>...
18043 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018044 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018045 (baseType->contentTypeDef != NULL) &&
18046 (WXS_IS_RESTRICTION(type))) {
18047 xmlSchemaTypePtr contentBase, content;
18048#ifdef ENABLE_NAMED_LOCALS
18049 char buf[30];
18050 const xmlChar *tmpname;
18051#endif
18052 /*
18053 * SPEC (1) If <restriction> + base type is <complexType>,
18054 * "whose own {content type} is a simple type..."
18055 */
18056 if (type->contentTypeDef != NULL) {
18057 /*
18058 * SPEC (1.1) "the simple type definition corresponding to the
18059 * <simpleType> among the [children] of <restriction> if there
18060 * is one;"
18061 * Note that this "<simpleType> among the [children]" was put
18062 * into ->contentTypeDef during parsing.
18063 */
18064 contentBase = type->contentTypeDef;
18065 type->contentTypeDef = NULL;
18066 } else {
18067 /*
18068 * (1.2) "...otherwise (<restriction> has no <simpleType>
18069 * among its [children]), the simple type definition which
18070 * is the {content type} of the ... base type."
18071 */
18072 contentBase = baseType->contentTypeDef;
18073 }
18074 /*
18075 * SPEC
18076 * "... a simple type definition which restricts the simple
18077 * type definition identified in clause 1.1 or clause 1.2
18078 * with a set of facet components"
18079 *
18080 * Create the anonymous simple type, which will be the content
18081 * type of the complex type.
18082 */
18083#ifdef ENABLE_NAMED_LOCALS
18084 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18085 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018086 content = xmlSchemaAddType(pctxt, pctxt->schema,
18087 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018088 type->node, 0);
18089#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018090 content = xmlSchemaAddType(pctxt, pctxt->schema,
18091 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018092 type->node, 0);
18093#endif
18094 if (content == NULL)
18095 goto exit_failure;
18096 /*
18097 * We will use the same node as for the <complexType>
18098 * to have it somehow anchored in the schema doc.
18099 */
18100 content->type = XML_SCHEMA_TYPE_SIMPLE;
18101 content->baseType = contentBase;
18102 /*
18103 * Move the facets, previously anchored on the
18104 * complexType during parsing.
18105 */
18106 content->facets = type->facets;
18107 type->facets = NULL;
18108 content->facetSet = type->facetSet;
18109 type->facetSet = NULL;
18110
18111 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018112 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018113 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018114 /*
18115 * Fixup the newly created type. We don't need to check
18116 * for circularity here.
18117 */
18118 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18119 HFAILURE HERROR
18120 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18121 HFAILURE HERROR
18122
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018123 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018124 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18125 (WXS_IS_RESTRICTION(type))) {
18126 /*
18127 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18128 * an emptiable particle, then a simple type definition which
18129 * restricts the <restriction>'s <simpleType> child.
18130 */
18131 if ((type->contentTypeDef == NULL) ||
18132 (type->contentTypeDef->baseType == NULL)) {
18133 /*
18134 * TODO: Check if this ever happens.
18135 */
18136 xmlSchemaPCustomErr(pctxt,
18137 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018138 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018139 "Internal error: xmlSchemaTypeFixup, "
18140 "complex type '%s': the <simpleContent><restriction> "
18141 "is missing a <simpleType> child, but was not catched "
18142 "by xmlSchemaCheckSRCCT()", type->name);
18143 goto exit_failure;
18144 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018145 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018146 /*
18147 * SPEC (3) If <extension> + base is <complexType> with
18148 * <simpleType> content, "...then the {content type} of that
18149 * complex type definition"
18150 */
18151 if (baseType->contentTypeDef == NULL) {
18152 /*
18153 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18154 * should have catched this already.
18155 */
18156 xmlSchemaPCustomErr(pctxt,
18157 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018158 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018159 "Internal error: xmlSchemaTypeFixup, "
18160 "complex type '%s': the <extension>ed base type is "
18161 "a complex type with no simple content type",
18162 type->name);
18163 goto exit_failure;
18164 }
18165 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018166 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018167 /*
18168 * SPEC (4) <extension> + base is <simpleType>
18169 * "... then that simple type definition"
18170 */
18171 type->contentTypeDef = baseType;
18172 } else {
18173 /*
18174 * TODO: Check if this ever happens.
18175 */
18176 xmlSchemaPCustomErr(pctxt,
18177 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018178 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018179 "Internal error: xmlSchemaTypeFixup, "
18180 "complex type '%s' with <simpleContent>: unhandled "
18181 "derivation case", type->name);
18182 goto exit_failure;
18183 }
18184 } else {
18185 int dummySequence = 0;
18186 xmlSchemaParticlePtr particle =
18187 (xmlSchemaParticlePtr) type->subtypes;
18188 /*
18189 * Corresponds to <complexType><complexContent>...
18190 *
18191 * NOTE that the effective mixed was already set during parsing of
18192 * <complexType> and <complexContent>; its flag value is
18193 * XML_SCHEMAS_TYPE_MIXED.
18194 *
18195 * Compute the "effective content":
18196 * (2.1.1) + (2.1.2) + (2.1.3)
18197 */
18198 if ((particle == NULL) ||
18199 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18200 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18201 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18202 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18203 (particle->minOccurs == 0))) &&
18204 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18205 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18206 /*
18207 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18208 * a particle whose properties are as follows:..."
18209 *
18210 * Empty sequence model group with
18211 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18212 * NOTE that we sill assign it the <complexType> node to
18213 * somehow anchor it in the doc.
18214 */
18215 if ((particle == NULL) ||
18216 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18217 /*
18218 * Create the particle.
18219 */
18220 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18221 type->node, 1, 1);
18222 if (particle == NULL)
18223 goto exit_failure;
18224 /*
18225 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018226 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018227 particle->children = (xmlSchemaTreeItemPtr)
18228 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18229 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18230 if (particle->children == NULL)
18231 goto exit_failure;
18232
18233 type->subtypes = (xmlSchemaTypePtr) particle;
18234 }
18235 dummySequence = 1;
18236 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18237 } else {
18238 /*
18239 * SPEC (2.1.5) "otherwise empty"
18240 */
18241 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18242 }
18243 } else {
18244 /*
18245 * SPEC (2.2) "otherwise the particle corresponding to the
18246 * <all>, <choice>, <group> or <sequence> among the
18247 * [children]."
18248 */
18249 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18250 }
18251 /*
18252 * Compute the "content type".
18253 */
18254 if (WXS_IS_RESTRICTION(type)) {
18255 /*
18256 * SPEC (3.1) "If <restriction>..."
18257 * (3.1.1) + (3.1.2) */
18258 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18259 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18260 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18261 }
18262 } else {
18263 /*
18264 * SPEC (3.2) "If <extension>..."
18265 */
18266 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18267 /*
18268 * SPEC (3.2.1)
18269 */
18270 type->contentType = baseType->contentType;
18271 type->subtypes = baseType->subtypes;
18272 /*
18273 * NOTE that the effective mixed is ignored here.
18274 */
18275 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18276 /*
18277 * SPEC (3.2.2)
18278 */
18279 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18280 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18281 } else {
18282 /*
18283 * SPEC (3.2.3)
18284 */
18285 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18286 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18287 /*
18288 * "A model group whose {compositor} is sequence and whose
18289 * {particles} are..."
18290 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018291 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18292 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18293 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18294 XML_SCHEMA_TYPE_ALL))
18295 {
18296 /*
18297 * SPEC cos-all-limited (1)
18298 */
18299 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18300 /* TODO: error code */
18301 XML_SCHEMAP_COS_ALL_LIMITED,
18302 WXS_ITEM_NODE(type), NULL,
18303 "The type has an 'all' model group in its "
18304 "{content type} and thus cannot be derived from "
18305 "a non-empty type, since this would produce a "
18306 "'sequence' model group containing the 'all' "
18307 "model group; 'all' model groups are not "
18308 "allowed to appear inside other model groups",
18309 NULL, NULL);
18310
18311 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18312 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18313 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18314 XML_SCHEMA_TYPE_ALL))
18315 {
18316 /*
18317 * SPEC cos-all-limited (1)
18318 */
18319 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18320 /* TODO: error code */
18321 XML_SCHEMAP_COS_ALL_LIMITED,
18322 WXS_ITEM_NODE(type), NULL,
18323 "A type cannot be derived by extension from a type "
18324 "which has an 'all' model group in its "
18325 "{content type}, since this would produce a "
18326 "'sequence' model group containing the 'all' "
18327 "model group; 'all' model groups are not "
18328 "allowed to appear inside other model groups",
18329 NULL, NULL);
18330
18331 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018332 xmlSchemaTreeItemPtr effectiveContent =
18333 (xmlSchemaTreeItemPtr) type->subtypes;
18334 /*
18335 * Create the particle.
18336 */
18337 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18338 type->node, 1, 1);
18339 if (particle == NULL)
18340 goto exit_failure;
18341 /*
18342 * Create the "sequence" model group.
18343 */
18344 particle->children = (xmlSchemaTreeItemPtr)
18345 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18346 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18347 if (particle->children == NULL)
18348 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018349 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018350 /*
18351 * SPEC "the particle of the {content type} of
18352 * the ... base ..."
18353 * Create a duplicate of the base type's particle
18354 * and assign its "term" to it.
18355 */
18356 particle->children->children =
18357 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18358 pctxt->schema, type->node,
18359 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18360 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18361 if (particle->children->children == NULL)
18362 goto exit_failure;
18363 particle = (xmlSchemaParticlePtr)
18364 particle->children->children;
18365 particle->children =
18366 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18367 /*
18368 * SPEC "followed by the ·effective content·."
18369 */
18370 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018371 /*
18372 * This all will result in:
18373 * new-particle
18374 * --> new-sequence(
18375 * new-particle
18376 * --> base-model,
18377 * this-particle
18378 * --> this-model
18379 * )
18380 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018381 } else {
18382 /*
18383 * This is the case when there is already an empty
18384 * <sequence> with minOccurs==maxOccurs==1.
18385 * Just add the base types's content type.
18386 * NOTE that, although we miss to add an intermediate
18387 * <sequence>, this should produce no difference to
18388 * neither the regex compilation of the content model,
18389 * nor to the complex type contraints.
18390 */
18391 particle->children->children =
18392 (xmlSchemaTreeItemPtr) baseType->subtypes;
18393 }
18394 }
18395 }
18396 }
18397 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018398 * Now fixup attribute uses:
18399 * - expand attr. group references
18400 * - intersect attribute wildcards
18401 * - inherit attribute uses of the base type
18402 * - inherit or union attr. wildcards if extending
18403 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018404 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018405 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018406 HFAILURE HERROR
18407 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018408 * Apply the complex type component constraints; this will not
18409 * check attributes, since this is done in
18410 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018411 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018412 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018413 HFAILURE HERROR
18414
18415#ifdef DEBUG_TYPE
18416 xmlSchemaDebugFixedType(pctxt, type);
18417#endif
18418 if (olderrs != pctxt->nberrors)
18419 return(pctxt->err);
18420 else
18421 return(0);
18422
18423exit_error:
18424 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18425#ifdef DEBUG_TYPE
18426 xmlSchemaDebugFixedType(pctxt, type);
18427#endif
18428 return(pctxt->err);
18429
18430exit_failure:
18431 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18432#ifdef DEBUG_TYPE
18433 xmlSchemaDebugFixedType(pctxt, type);
18434#endif
18435 return(-1);
18436}
18437
18438
18439/**
18440 * xmlSchemaTypeFixup:
18441 * @typeDecl: the schema type definition
18442 * @ctxt: the schema parser context
18443 *
18444 * Fixes the content model of the type.
18445 * URGENT TODO: We need an int result!
18446 */
18447static int
18448xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018449 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018450{
18451 if (type == NULL)
18452 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018453 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18454 AERROR_INT("xmlSchemaTypeFixup",
18455 "this function needs a parser context");
18456 return(-1);
18457 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018458 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018459 return(0);
18460 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018461 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018462 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018463 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018464 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018465}
18466
18467/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018468 * xmlSchemaCheckFacet:
18469 * @facet: the facet
18470 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018471 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018472 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018473 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018475 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018476 * Returns 0 if valid, a positive error code if not valid and
18477 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018478 */
18479int
18480xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018481 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018482 xmlSchemaParserCtxtPtr pctxt,
18483 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018484{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018485 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018486
Daniel Veillardce682bc2004-11-05 17:22:25 +000018487 if ((facet == NULL) || (typeDecl == NULL))
18488 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018490 * TODO: will the parser context be given if used from
18491 * the relaxNG module?
18492 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 if (pctxt == NULL)
18494 ctxtGiven = 0;
18495 else
18496 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018497
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018498 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018499 case XML_SCHEMA_FACET_MININCLUSIVE:
18500 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18501 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018502 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18503 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018504 /*
18505 * Okay we need to validate the value
18506 * at that point.
18507 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018508 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018509
18510 /* 4.3.5.5 Constraints on enumeration Schema Components
18511 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018512 * It is an ·error· if any member of {value} is not in the
18513 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018514 *
18515 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018516 * The value ·must· be in the
18517 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018518 */
18519 /*
18520 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018521 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018523 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018524 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018525 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018527 */
18528 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18529 base = typeDecl->baseType;
18530 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018531 PERROR_INT("xmlSchemaCheckFacet",
18532 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018533 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018534 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018535 } else
18536 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537
18538 if (! ctxtGiven) {
18539 /*
18540 * A context is needed if called from RelaxNG.
18541 */
18542 pctxt = xmlSchemaNewParserCtxt("*");
18543 if (pctxt == NULL)
18544 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018545 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018546 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018547 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018548 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018549 * facet->node is just the node holding the facet
18550 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018551 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018552 */
18553 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018554 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018555 facet->value, &(facet->val), 1, 1, 0);
18556 if (ret != 0) {
18557 if (ret < 0) {
18558 /* No error message for RelaxNG. */
18559 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018560 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018561 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18562 "Internal error: xmlSchemaCheckFacet, "
18563 "failed to validate the value '%s' of the "
18564 "facet '%s' against the base type",
18565 facet->value, xmlSchemaFacetTypeToString(facet->type));
18566 }
18567 goto internal_error;
18568 }
18569 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18570 /* No error message for RelaxNG. */
18571 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018572 xmlChar *str = NULL;
18573
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018574 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018575 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018576 "The value '%s' of the facet does not validate "
18577 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018578 facet->value,
18579 xmlSchemaFormatQName(&str,
18580 base->targetNamespace, base->name));
18581 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018583 goto exit;
18584 } else if (facet->val == NULL) {
18585 if (ctxtGiven) {
18586 PERROR_INT("xmlSchemaCheckFacet",
18587 "value was not computed");
18588 }
18589 TODO
18590 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018591 break;
18592 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018593 case XML_SCHEMA_FACET_PATTERN:
18594 facet->regexp = xmlRegexpCompile(facet->value);
18595 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018596 ret = XML_SCHEMAP_REGEXP_INVALID;
18597 /* No error message for RelaxNG. */
18598 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018599 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018600 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018601 "The value '%s' of the facet 'pattern' is not a "
18602 "valid regular expression",
18603 facet->value, NULL);
18604 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018605 }
18606 break;
18607 case XML_SCHEMA_FACET_TOTALDIGITS:
18608 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18609 case XML_SCHEMA_FACET_LENGTH:
18610 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018611 case XML_SCHEMA_FACET_MINLENGTH:
18612
18613 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18614 ret = xmlSchemaValidatePredefinedType(
18615 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18616 facet->value, &(facet->val));
18617 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018618 ret = xmlSchemaValidatePredefinedType(
18619 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18620 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018621 }
18622 if (ret != 0) {
18623 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 /* No error message for RelaxNG. */
18625 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018626 PERROR_INT("xmlSchemaCheckFacet",
18627 "validating facet value");
18628 }
18629 goto internal_error;
18630 }
18631 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18632 /* No error message for RelaxNG. */
18633 if (ctxtGiven) {
18634 /* error code */
18635 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18636 ret, facet->node, WXS_BASIC_CAST typeDecl,
18637 "The value '%s' of the facet '%s' is not a valid '%s'",
18638 facet->value,
18639 xmlSchemaFacetTypeToString(facet->type),
18640 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18641 BAD_CAST "nonNegativeInteger" :
18642 BAD_CAST "positiveInteger",
18643 NULL);
18644 }
18645 }
18646 break;
18647
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018648 case XML_SCHEMA_FACET_WHITESPACE:{
18649 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18650 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18651 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18652 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18653 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18654 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18655 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18657 /* No error message for RelaxNG. */
18658 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018659 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018660 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018661 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018662 "The value '%s' of the facet 'whitespace' is not "
18663 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018664 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018665 }
18666 }
18667 default:
18668 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018669 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018670exit:
18671 if ((! ctxtGiven) && (pctxt != NULL))
18672 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018673 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018674internal_error:
18675 if ((! ctxtGiven) && (pctxt != NULL))
18676 xmlSchemaFreeParserCtxt(pctxt);
18677 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018678}
18679
18680/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018681 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018682 * @typeDecl: the schema type definition
18683 * @ctxt: the schema parser context
18684 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018685 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018686 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018687static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018688xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018689 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018690{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018691 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018693 /*
18694 * NOTE: It is intended to use the facets list, instead
18695 * of facetSet.
18696 */
18697 if (typeDecl->facets != NULL) {
18698 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018699
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018700 /*
18701 * Temporarily assign the "schema" to the validation context
18702 * of the parser context. This is needed for NOTATION validation.
18703 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018704 if (pctxt->vctxt == NULL) {
18705 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18706 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018707 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018708 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018709 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018710 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18711 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018712 facet = facet->next;
18713 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018714 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018715 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018716 if (olderrs != pctxt->nberrors)
18717 return(pctxt->err);
18718 return(0);
18719exit_failure:
18720 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018721}
18722
18723/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018724 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018725 * @ctxtMGroup: the searched model group
18726 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018727 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018728 *
18729 * This one is intended to be used by
18730 * xmlSchemaCheckGroupDefCircular only.
18731 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018732 * Returns the particle with the circular model group definition reference,
18733 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018734 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018735static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018736xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018737 xmlSchemaTreeItemPtr particle)
18738{
18739 xmlSchemaTreeItemPtr circ = NULL;
18740 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018741 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018742
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018743 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018744 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018745 if (term == NULL)
18746 continue;
18747 switch (term->type) {
18748 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018749 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018750 if (gdef == groupDef)
18751 return (particle);
18752 /*
18753 * Mark this model group definition to avoid infinite
18754 * recursion on circular references not yet examined.
18755 */
18756 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18757 continue;
18758 if (gdef->children != NULL) {
18759 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18760 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18761 gdef->children->children);
18762 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18763 if (circ != NULL)
18764 return (circ);
18765 }
18766 break;
18767 case XML_SCHEMA_TYPE_SEQUENCE:
18768 case XML_SCHEMA_TYPE_CHOICE:
18769 case XML_SCHEMA_TYPE_ALL:
18770 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18771 if (circ != NULL)
18772 return (circ);
18773 break;
18774 default:
18775 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018776 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018777 }
18778 return (NULL);
18779}
18780
18781/**
18782 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018783 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018784 * @ctxt: the parser context
18785 * @name: the name
18786 *
18787 * Checks for circular references to model group definitions.
18788 */
18789static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018790xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018791 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018792{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018793 /*
18794 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018795 * 2 Circular groups are disallowed. That is, within the {particles}
18796 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018797 * is the group itself.
18798 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018799 if ((item == NULL) ||
18800 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18801 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018802 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018803 {
18804 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018805
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018806 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018807 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018808 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018809 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018810 * TODO: The error report is not adequate: this constraint
18811 * is defined for model groups but not definitions, but since
18812 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018813 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018814 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018815 */
18816 xmlSchemaPCustomErr(ctxt,
18817 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018818 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018819 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018820 "defined", xmlSchemaFormatQName(&str,
18821 item->targetNamespace, item->name));
18822 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018823 /*
18824 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018825 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018826 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018827 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018828 }
18829 }
18830}
18831
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018832/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018833 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018834 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018835 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018836 *
18837 * Assigns the model group of model group definitions to the "term"
18838 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018839 * In xmlSchemaResolveModelGroupParticleReferences the model group
18840 * definitions were assigned to the "term", since needed for the
18841 * circularity check.
18842 *
18843 * Schema Component Constraint:
18844 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018845 */
18846static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018847xmlSchemaModelGroupToModelGroupDefFixup(
18848 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18849 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018850{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018851 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18852
18853 while (particle != NULL) {
18854 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18855 ((WXS_PARTICLE_TERM(particle))->type !=
18856 XML_SCHEMA_TYPE_GROUP))
18857 {
18858 particle = WXS_PTC_CAST particle->next;
18859 continue;
18860 }
18861 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18862 /*
18863 * TODO: Remove the particle.
18864 */
18865 WXS_PARTICLE_TERM(particle) = NULL;
18866 particle = WXS_PTC_CAST particle->next;
18867 continue;
18868 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018869 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018870 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018871 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018872 WXS_PARTICLE_TERM(particle) =
18873 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18874
18875 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018876 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018877}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018878
18879/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018880 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018881 * @ctxtGr: the searched attribute group
18882 * @attr: the current attribute list to be processed
18883 *
18884 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018885 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018886 *
18887 * Returns the circular attribute grou reference, otherwise NULL.
18888 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018889static xmlSchemaQNameRefPtr
18890xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18891 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018892{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018893 xmlSchemaAttributeGroupPtr gr;
18894 xmlSchemaQNameRefPtr ref, circ;
18895 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018896 /*
18897 * We will search for an attribute group reference which
18898 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018899 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018900 for (i = 0; i < list->nbItems; i++) {
18901 ref = list->items[i];
18902 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18903 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18904 (ref->item != NULL))
18905 {
18906 gr = WXS_ATTR_GROUP_CAST ref->item;
18907 if (gr == ctxtGr)
18908 return(ref);
18909 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18910 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018911 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018912 * Mark as visited to avoid infinite recursion on
18913 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018914 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018915 if ((gr->attrUses) &&
18916 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18917 {
18918 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18919 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18920 (xmlSchemaItemListPtr) gr->attrUses);
18921 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18922 if (circ != NULL)
18923 return (circ);
18924 }
18925
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018926 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018927 }
18928 return (NULL);
18929}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018930
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018931/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018932 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018933 * attrGr: the attribute group definition
18934 * @ctxt: the parser context
18935 * @name: the name
18936 *
18937 * Checks for circular references of attribute groups.
18938 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018939static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018940xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018941 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018942{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018943 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018944 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018945 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018946 * 3 Circular group reference is disallowed outside <redefine>.
18947 * That is, unless this element information item's parent is
18948 * <redefine>, then among the [children], if any, there must
18949 * not be an <attributeGroup> with ref [attribute] which resolves
18950 * to the component corresponding to this <attributeGroup>. Indirect
18951 * circularity is also ruled out. That is, when QName resolution
18952 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18953 * any <attributeGroup>s with a ref [attribute] among the [children],
18954 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955 * which resolves to the component corresponding to this <attributeGroup>.
18956 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018957 if (attrGr->attrUses == NULL)
18958 return(0);
18959 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18960 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018961 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018962 xmlSchemaQNameRefPtr circ;
18963
18964 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18965 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018966 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018967 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018968 /*
18969 * TODO: Report the referenced attr group as QName.
18970 */
18971 xmlSchemaPCustomErr(ctxt,
18972 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018973 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018974 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018975 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18976 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018977 /*
18978 * NOTE: We will cut the reference to avoid further
18979 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018980 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018981 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018982 circ->item = NULL;
18983 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018984 }
18985 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018986 return(0);
18987}
18988
18989static int
18990xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18991 xmlSchemaAttributeGroupPtr attrGr);
18992
18993/**
18994 * xmlSchemaExpandAttributeGroupRefs:
18995 * @pctxt: the parser context
18996 * @node: the node of the component holding the attribute uses
18997 * @completeWild: the intersected wildcard to be returned
18998 * @list: the attribute uses
18999 *
19000 * Substitutes contained attribute group references
19001 * for their attribute uses. Wilcards are intersected.
19002 * Attribute use prohibitions are removed from the list
19003 * and returned via the @prohibs list.
19004 * Pointlessness of attr. prohibs, if a matching attr. decl
19005 * is existent a well, are checked.
19006 */
19007static int
19008xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19009 xmlSchemaBasicItemPtr item,
19010 xmlSchemaWildcardPtr *completeWild,
19011 xmlSchemaItemListPtr list,
19012 xmlSchemaItemListPtr prohibs)
19013{
19014 xmlSchemaAttributeGroupPtr gr;
19015 xmlSchemaAttributeUsePtr use;
19016 xmlSchemaItemListPtr sublist;
19017 int i, j;
19018 int created = (*completeWild == NULL) ? 0 : 1;
19019
19020 if (prohibs)
19021 prohibs->nbItems = 0;
19022
19023 for (i = 0; i < list->nbItems; i++) {
19024 use = list->items[i];
19025
19026 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19027 if (prohibs == NULL) {
19028 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19029 "unexpected attr prohibition found");
19030 return(-1);
19031 }
19032 /*
19033 * Remove from attribute uses.
19034 */
19035 if (xmlSchemaItemListRemove(list, i) == -1)
19036 return(-1);
19037 i--;
19038 /*
19039 * Note that duplicate prohibitions were already
19040 * handled at parsing time.
19041 */
19042 /*
19043 * Add to list of prohibitions.
19044 */
19045 xmlSchemaItemListAddSize(prohibs, 2, use);
19046 continue;
19047 }
19048 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19049 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19050 {
19051 if ((WXS_QNAME_CAST use)->item == NULL)
19052 return(-1);
19053 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19054 /*
19055 * Expand the referenced attr. group.
19056 * TODO: remove this, this is done in a previous step, so
19057 * already done here.
19058 */
19059 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19060 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19061 return(-1);
19062 }
19063 /*
19064 * Build the 'complete' wildcard; i.e. intersect multiple
19065 * wildcards.
19066 */
19067 if (gr->attributeWildcard != NULL) {
19068 if (*completeWild == NULL) {
19069 *completeWild = gr->attributeWildcard;
19070 } else {
19071 if (! created) {
19072 xmlSchemaWildcardPtr tmpWild;
19073
19074 /*
19075 * Copy the first encountered wildcard as context,
19076 * except for the annotation.
19077 *
19078 * Although the complete wildcard might not correspond
19079 * to any node in the schema, we will anchor it on
19080 * the node of the owner component.
19081 */
19082 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19083 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19084 WXS_ITEM_NODE(item));
19085 if (tmpWild == NULL)
19086 return(-1);
19087 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19088 tmpWild, *completeWild) == -1)
19089 return (-1);
19090 tmpWild->processContents = (*completeWild)->processContents;
19091 *completeWild = tmpWild;
19092 created = 1;
19093 }
19094
19095 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19096 gr->attributeWildcard) == -1)
19097 return(-1);
19098 }
19099 }
19100 /*
19101 * Just remove the reference if the referenced group does not
19102 * contain any attribute uses.
19103 */
19104 if (gr->attrUses == NULL) {
19105 if (xmlSchemaItemListRemove(list, i) == -1)
19106 return(-1);
19107 i--;
19108 continue;
19109 }
19110 /*
19111 * Add the attribute uses.
19112 */
19113 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19114 if (sublist->nbItems != 0) {
19115 list->items[i] = sublist->items[0];
19116 if (sublist->nbItems != 1) {
19117 for (j = 1; j < sublist->nbItems; j++) {
19118 i++;
19119 if (xmlSchemaItemListInsert(list,
19120 sublist->items[j], i) == -1)
19121 return(-1);
19122 }
19123 }
19124 }
19125 }
19126
19127 }
19128 /*
19129 * Handle pointless prohibitions of declared attributes.
19130 */
19131 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19132 xmlSchemaAttributeUseProhibPtr prohib;
19133
19134 for (i = prohibs->nbItems -1; i >= 0; i--) {
19135 prohib = prohibs->items[i];
19136 for (j = 0; j < list->nbItems; j++) {
19137 use = list->items[j];
19138
19139 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19140 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19141 {
19142 xmlChar *str = NULL;
19143
19144 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19145 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19146 prohib->node, NULL,
19147 "Skipping pointless attribute use prohibition "
19148 "'%s', since a corresponding attribute use "
19149 "exists already in the type definition",
19150 xmlSchemaFormatQName(&str,
19151 prohib->targetNamespace, prohib->name),
19152 NULL, NULL);
19153 FREE_AND_NULL(str);
19154 /*
19155 * Remove the prohibition.
19156 */
19157 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19158 return(-1);
19159 break;
19160 }
19161 }
19162 }
19163 }
19164 return(0);
19165}
19166
19167/**
19168 * xmlSchemaAttributeGroupExpandRefs:
19169 * @pctxt: the parser context
19170 * @attrGr: the attribute group definition
19171 *
19172 * Computation of:
19173 * {attribute uses} property
19174 * {attribute wildcard} property
19175 *
19176 * Substitutes contained attribute group references
19177 * for their attribute uses. Wilcards are intersected.
19178 */
19179static int
19180xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19181 xmlSchemaAttributeGroupPtr attrGr)
19182{
19183 if ((attrGr->attrUses == NULL) ||
19184 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19185 return(0);
19186
19187 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19188 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19189 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19190 return(-1);
19191 return(0);
19192}
19193
19194/**
19195 * xmlSchemaAttributeGroupExpandRefs:
19196 * @pctxt: the parser context
19197 * @attrGr: the attribute group definition
19198 *
19199 * Substitutes contained attribute group references
19200 * for their attribute uses. Wilcards are intersected.
19201 *
19202 * Schema Component Constraint:
19203 * Attribute Group Definition Properties Correct (ag-props-correct)
19204 */
19205static int
19206xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19207 xmlSchemaAttributeGroupPtr attrGr)
19208{
19209 /*
19210 * SPEC ag-props-correct
19211 * (1) "The values of the properties of an attribute group definition
19212 * must be as described in the property tableau in The Attribute
19213 * Group Definition Schema Component (§3.6.1), modulo the impact of
19214 * Missing Sub-components (§5.3);"
19215 */
19216
19217 if ((attrGr->attrUses != NULL) &&
19218 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19219 {
19220 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19221 xmlSchemaAttributeUsePtr use, tmp;
19222 int i, j, hasId = 0;
19223
19224 for (i = uses->nbItems -1; i >= 0; i--) {
19225 use = uses->items[i];
19226 /*
19227 * SPEC ag-props-correct
19228 * (2) "Two distinct members of the {attribute uses} must not have
19229 * {attribute declaration}s both of whose {name}s match and whose
19230 * {target namespace}s are identical."
19231 */
19232 if (i > 0) {
19233 for (j = i -1; j >= 0; j--) {
19234 tmp = uses->items[j];
19235 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19236 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19237 (WXS_ATTRUSE_DECL_TNS(use) ==
19238 WXS_ATTRUSE_DECL_TNS(tmp)))
19239 {
19240 xmlChar *str = NULL;
19241
19242 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19243 XML_SCHEMAP_AG_PROPS_CORRECT,
19244 attrGr->node, WXS_BASIC_CAST attrGr,
19245 "Duplicate %s",
19246 xmlSchemaGetComponentDesignation(&str, use),
19247 NULL);
19248 FREE_AND_NULL(str);
19249 /*
19250 * Remove the duplicate.
19251 */
19252 if (xmlSchemaItemListRemove(uses, i) == -1)
19253 return(-1);
19254 goto next_use;
19255 }
19256 }
19257 }
19258 /*
19259 * SPEC ag-props-correct
19260 * (3) "Two distinct members of the {attribute uses} must not have
19261 * {attribute declaration}s both of whose {type definition}s are or
19262 * are derived from ID."
19263 * TODO: Does 'derived' include member-types of unions?
19264 */
19265 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19266 if (xmlSchemaIsDerivedFromBuiltInType(
19267 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19268 {
19269 if (hasId) {
19270 xmlChar *str = NULL;
19271
19272 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19273 XML_SCHEMAP_AG_PROPS_CORRECT,
19274 attrGr->node, WXS_BASIC_CAST attrGr,
19275 "There must not exist more than one attribute "
19276 "declaration of type 'xs:ID' "
19277 "(or derived from 'xs:ID'). The %s violates this "
19278 "constraint",
19279 xmlSchemaGetComponentDesignation(&str, use),
19280 NULL);
19281 FREE_AND_NULL(str);
19282 if (xmlSchemaItemListRemove(uses, i) == -1)
19283 return(-1);
19284 }
19285 hasId = 1;
19286 }
19287 }
19288next_use: {}
19289 }
19290 }
19291 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019292}
19293
19294/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019295 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019296 * @attrgrpDecl: the schema attribute definition
19297 * @ctxt: the schema parser context
19298 * @name: the attribute name
19299 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019300 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019301 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019302static int
19303xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19304 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019305{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019306 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019307
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019308 if (ref->item != NULL)
19309 return(0);
19310 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19311 ref->name,
19312 ref->targetNamespace);
19313 if (group == NULL) {
19314 xmlSchemaPResCompAttrErr(ctxt,
19315 XML_SCHEMAP_SRC_RESOLVE,
19316 NULL, ref->node,
19317 "ref", ref->name, ref->targetNamespace,
19318 ref->itemType, NULL);
19319 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019320 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019321 ref->item = WXS_BASIC_CAST group;
19322 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019323}
19324
19325/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019326 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019327 * @item: an schema attribute declaration/use
19328 * @ctxt: a schema parser context
19329 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019330 *
19331 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019332 * Schema Component Constraint:
19333 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019334 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019335 * Validates the value constraints of an attribute declaration/use.
19336 * NOTE that this needs the simle type definitions to be already
19337 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019338 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019339static int
19340xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19341 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019342{
19343
19344 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019345 * SPEC a-props-correct (1)
19346 * "The values of the properties of an attribute declaration must
19347 * be as described in the property tableau in The Attribute
19348 * Declaration Schema Component (§3.2.1), modulo the impact of
19349 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019350 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019351
19352 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19353 return(0);
19354
19355 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019356 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019357
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019358 /*
19359 * SPEC a-props-correct (3)
19360 * "If the {type definition} is or is derived from ID then there
19361 * must not be a {value constraint}."
19362 */
19363 if (xmlSchemaIsDerivedFromBuiltInType(
19364 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19365 {
19366 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19367 XML_SCHEMAP_A_PROPS_CORRECT_3,
19368 NULL, WXS_BASIC_CAST attr,
19369 "Value constraints are not allowed if the type definition "
19370 "is or is derived from xs:ID",
19371 NULL, NULL);
19372 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019373 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019374 /*
19375 * SPEC a-props-correct (2)
19376 * "if there is a {value constraint}, the canonical lexical
19377 * representation of its value must be ·valid· with respect
19378 * to the {type definition} as defined in String Valid (§3.14.4)."
19379 * TODO: Don't care about the *cononical* stuff here, this requirement
19380 * will be removed in WXS 1.1 anyway.
19381 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019382 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019383 attr->node, WXS_ATTR_TYPEDEF(attr),
19384 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019385 1, 1, 0);
19386 if (ret != 0) {
19387 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019388 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019389 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019390 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019391 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019392 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019393 XML_SCHEMAP_A_PROPS_CORRECT_2,
19394 NULL, WXS_BASIC_CAST attr,
19395 "The value of the value constraint is not valid",
19396 NULL, NULL);
19397 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019399 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019400
19401 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019402}
19403
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019404static xmlSchemaElementPtr
19405xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19406 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019407{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019408 xmlSchemaElementPtr ret;
19409
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019410 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019411 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019412 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019413 return (ancestor);
19414
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019415 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019416 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019417 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019418 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019419 WXS_SUBST_HEAD(ancestor));
19420 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019421
19422 return (ret);
19423}
19424
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019425/**
19426 * xmlSchemaCheckElemPropsCorrect:
19427 * @ctxt: a schema parser context
19428 * @decl: the element declaration
19429 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019430 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019431 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019432 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019433 *
19434 * STATUS:
19435 * missing: (6)
19436 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019437static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019438xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19439 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019440{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019441 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019442 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019443 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019444 * SPEC (1) "The values of the properties of an element declaration
19445 * must be as described in the property tableau in The Element
19446 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19447 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019448 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019449 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19450 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019451
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019452 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019454 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019455 * affiliation}, then {scope} must be global."
19456 */
19457 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19458 xmlSchemaPCustomErr(pctxt,
19459 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019460 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019461 "Only global element declarations can have a "
19462 "substitution group affiliation", NULL);
19463 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019464 }
19465 /*
19466 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19467 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019468 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019469 * property."
19470 */
19471 if (head == elemDecl)
19472 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019473 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019474 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19475 else
19476 circ = NULL;
19477 if (circ != NULL) {
19478 xmlChar *strA = NULL, *strB = NULL;
19479
19480 xmlSchemaPCustomErrExt(pctxt,
19481 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019482 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019483 "The element declaration '%s' defines a circular "
19484 "substitution group to element declaration '%s'",
19485 xmlSchemaGetComponentQName(&strA, circ),
19486 xmlSchemaGetComponentQName(&strB, head),
19487 NULL);
19488 FREE_AND_NULL(strA)
19489 FREE_AND_NULL(strB)
19490 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19491 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019492 /*
19493 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019494 * the {type definition}
19495 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019496 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019497 * of the {substitution group exclusions} of the {substitution group
19498 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19499 * (if the {type definition} is complex) or as defined in
19500 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019501 * simple)."
19502 *
19503 * NOTE: {substitution group exclusions} means the values of the
19504 * attribute "final".
19505 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019507 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019508 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019509
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19511 set |= SUBSET_EXTENSION;
19512 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19513 set |= SUBSET_RESTRICTION;
19514
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019515 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019516 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019517 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19518
19519 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019520 xmlSchemaPCustomErrExt(pctxt,
19521 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019522 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019523 "The type definition '%s' was "
19524 "either rejected by the substitution group "
19525 "affiliation '%s', or not validly derived from its type "
19526 "definition '%s'",
19527 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019528 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019529 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019530 FREE_AND_NULL(strA)
19531 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019532 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019533 }
19534 }
19535 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019536 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019537 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019538 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019539 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019540 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019541 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019542 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019543 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019544 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019545 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019546 (WXS_IS_COMPLEX(typeDef) &&
19547 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019548 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19549 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019550
19551 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19552 xmlSchemaPCustomErr(pctxt,
19553 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019554 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019555 "The type definition (or type definition's content type) is or "
19556 "is derived from ID; value constraints are not allowed in "
19557 "conjunction with such a type definition", NULL);
19558 } else if (elemDecl->value != NULL) {
19559 int vcret;
19560 xmlNodePtr node = NULL;
19561
19562 /*
19563 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19564 * representation of its value must be ·valid· with respect to the
19565 * {type definition} as defined in Element Default Valid (Immediate)
19566 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019567 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019568 if (typeDef == NULL) {
19569 xmlSchemaPErr(pctxt, elemDecl->node,
19570 XML_SCHEMAP_INTERNAL,
19571 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19572 "type is missing... skipping validation of "
19573 "the value constraint", NULL, NULL);
19574 return (-1);
19575 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019576 if (elemDecl->node != NULL) {
19577 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19578 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19579 BAD_CAST "fixed");
19580 else
19581 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19582 BAD_CAST "default");
19583 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019584 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19585 typeDef, elemDecl->value, &(elemDecl->defVal));
19586 if (vcret != 0) {
19587 if (vcret < 0) {
19588 PERROR_INT("xmlSchemaElemCheckValConstr",
19589 "failed to validate the value constraint of an "
19590 "element declaration");
19591 return (-1);
19592 }
19593 return (vcret);
19594 }
19595 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019596
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019597 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019598}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019599
19600/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019601 * xmlSchemaCheckElemSubstGroup:
19602 * @ctxt: a schema parser context
19603 * @decl: the element declaration
19604 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019605 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019606 * Schema Component Constraint:
19607 * Substitution Group (cos-equiv-class)
19608 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019609 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019610 * a list will be built for each subst. group head, holding all direct
19611 * referents to this head.
19612 * NOTE that this function needs:
19613 * 1. circular subst. groups to be checked beforehand
19614 * 2. the declaration's type to be derived from the head's type
19615 *
19616 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019617 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019618 */
19619static void
19620xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19621 xmlSchemaElementPtr elemDecl)
19622{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019623 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019624 /* SPEC (1) "Its {abstract} is false." */
19625 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19626 return;
19627 {
19628 xmlSchemaElementPtr head;
19629 xmlSchemaTypePtr headType, type;
19630 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019631 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019632 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19633 * {disallowed substitutions} as the blocking constraint, as defined in
19634 * Substitution Group OK (Transitive) (§3.3.6)."
19635 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019636 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19637 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019638 set = 0;
19639 methSet = 0;
19640 /*
19641 * The blocking constraints.
19642 */
19643 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19644 continue;
19645 headType = head->subtypes;
19646 type = elemDecl->subtypes;
19647 if (headType == type)
19648 goto add_member;
19649 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19650 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19651 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19652 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19653 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019654 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019655 * "The set of all {derivation method}s involved in the
19656 * derivation of D's {type definition} from C's {type definition}
19657 * does not intersect with the union of the blocking constraint,
19658 * C's {prohibited substitutions} (if C is complex, otherwise the
19659 * empty set) and the {prohibited substitutions} (respectively the
19660 * empty set) of any intermediate {type definition}s in the
19661 * derivation of D's {type definition} from C's {type definition}."
19662 */
19663 /*
19664 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19665 * subst.head axis, the methSet does not need to be computed for
19666 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019667 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019668 /*
19669 * The set of all {derivation method}s involved in the derivation
19670 */
19671 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019672 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019673 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19674 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019675
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019676 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019677 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19678 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19679
19680 type = type->baseType;
19681 }
19682 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019683 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019684 * the head's type.
19685 */
19686 type = elemDecl->subtypes->baseType;
19687 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019688 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019689 if ((type->flags &
19690 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19691 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19692 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19693 if ((type->flags &
19694 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19695 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19696 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19697 } else
19698 break;
19699 if (type == headType)
19700 break;
19701 type = type->baseType;
19702 }
19703 if ((set != 0) &&
19704 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19705 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19706 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19707 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19708 continue;
19709 }
19710add_member:
19711 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19712 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19713 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19714 }
19715 }
19716}
19717
19718/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019719 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019720 * @item: an schema element declaration/particle
19721 * @ctxt: a schema parser context
19722 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019723 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019724 * Validates the value constraints of an element declaration.
19725 *
19726 * Fixes finish doing the computations on the element declarations.
19727 */
19728static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019729xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019730 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019731{
19732 if (elemDecl == NULL)
19733 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019734 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19735 return;
19736 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019737 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19738 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019739}
19740
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019741/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019742 * xmlSchemaResolveModelGroupParticleReferences:
19743 * @particle: a particle component
19744 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019745 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019746 * Resolves references of a model group's {particles} to
19747 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019748 */
19749static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019750xmlSchemaResolveModelGroupParticleReferences(
19751 xmlSchemaParserCtxtPtr ctxt,
19752 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019753{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019754 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19755 xmlSchemaQNameRefPtr ref;
19756 xmlSchemaBasicItemPtr refItem;
19757
19758 /*
19759 * URGENT TODO: Test this.
19760 */
19761 while (particle != NULL) {
19762 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19763 ((WXS_PARTICLE_TERM(particle))->type !=
19764 XML_SCHEMA_EXTRA_QNAMEREF))
19765 {
19766 goto next_particle;
19767 }
19768 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019769 /*
19770 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019771 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019772 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019773 particle->children = NULL;
19774
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019775 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19776 ref->itemType, ref->name, ref->targetNamespace);
19777 if (refItem == NULL) {
19778 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019779 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019780 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019781 /* TODO: remove the particle. */
19782 goto next_particle;
19783 }
19784 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19785 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19786 /* TODO: remove the particle. */
19787 goto next_particle;
19788 /*
19789 * NOTE that we will assign the model group definition
19790 * itself to the "term" of the particle. This will ease
19791 * the check for circular model group definitions. After
19792 * that the "term" will be assigned the model group of the
19793 * model group definition.
19794 */
19795 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19796 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019797 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019798 * SPEC cos-all-limited (1)
19799 * SPEC cos-all-limited (1.2)
19800 * "It appears only as the value of one or both of the
19801 * following properties:"
19802 * (1.1) "the {model group} property of a model group
19803 * definition."
19804 * (1.2) "the {term} property of a particle [... of] the "
19805 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019806 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019807 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19808 /* TODO: error code */
19809 XML_SCHEMAP_COS_ALL_LIMITED,
19810 WXS_ITEM_NODE(particle), NULL,
19811 "A model group definition is referenced, but "
19812 "it contains an 'all' model group, which "
19813 "cannot be contained by model groups",
19814 NULL, NULL);
19815 /* TODO: remove the particle. */
19816 goto next_particle;
19817 }
19818 particle->children = (xmlSchemaTreeItemPtr) refItem;
19819 } else {
19820 /*
19821 * TODO: Are referenced element declarations the only
19822 * other components we expect here?
19823 */
19824 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019825 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019826next_particle:
19827 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019828 }
19829}
19830
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019831static int
19832xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19833 xmlSchemaValPtr y)
19834{
19835 xmlSchemaTypePtr tx, ty, ptx, pty;
19836 int ret;
19837
19838 while (x != NULL) {
19839 /* Same types. */
19840 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19841 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19842 ptx = xmlSchemaGetPrimitiveType(tx);
19843 pty = xmlSchemaGetPrimitiveType(ty);
19844 /*
19845 * (1) if a datatype T' is ·derived· by ·restriction· from an
19846 * atomic datatype T then the ·value space· of T' is a subset of
19847 * the ·value space· of T. */
19848 /*
19849 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19850 * from a common atomic ancestor T then the ·value space·s of T'
19851 * and T'' may overlap.
19852 */
19853 if (ptx != pty)
19854 return(0);
19855 /*
19856 * We assume computed values to be normalized, so do a fast
19857 * string comparison for string based types.
19858 */
19859 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019860 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019861 if (! xmlStrEqual(
19862 xmlSchemaValueGetAsString(x),
19863 xmlSchemaValueGetAsString(y)))
19864 return (0);
19865 } else {
19866 ret = xmlSchemaCompareValuesWhtsp(
19867 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19868 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19869 if (ret == -2)
19870 return(-1);
19871 if (ret != 0)
19872 return(0);
19873 }
19874 /*
19875 * Lists.
19876 */
19877 x = xmlSchemaValueGetNext(x);
19878 if (x != NULL) {
19879 y = xmlSchemaValueGetNext(y);
19880 if (y == NULL)
19881 return (0);
19882 } else if (xmlSchemaValueGetNext(y) != NULL)
19883 return (0);
19884 else
19885 return (1);
19886 }
19887 return (0);
19888}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019889
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019890/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019891 * xmlSchemaResolveAttrUseReferences:
19892 * @item: an attribute use
19893 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019894 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019895 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019896 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019897static int
19898xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19899 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019900{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019901 if ((ctxt == NULL) || (ause == NULL))
19902 return(-1);
19903 if ((ause->attrDecl == NULL) ||
19904 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19905 return(0);
19906
19907 {
19908 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19909
19910 /*
19911 * TODO: Evaluate, what errors could occur if the declaration is not
19912 * found.
19913 */
19914 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19915 ref->name, ref->targetNamespace);
19916 if (ause->attrDecl == NULL) {
19917 xmlSchemaPResCompAttrErr(ctxt,
19918 XML_SCHEMAP_SRC_RESOLVE,
19919 WXS_BASIC_CAST ause, ause->node,
19920 "ref", ref->name, ref->targetNamespace,
19921 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19922 return(ctxt->err);;
19923 }
19924 }
19925 return(0);
19926}
19927
19928/**
19929 * xmlSchemaCheckAttrUsePropsCorrect:
19930 * @ctxt: a parser context
19931 * @use: an attribute use
19932 *
19933 * Schema Component Constraint:
19934 * Attribute Use Correct (au-props-correct)
19935 *
19936 */
19937static int
19938xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19939 xmlSchemaAttributeUsePtr use)
19940{
19941 if ((ctxt == NULL) || (use == NULL))
19942 return(-1);
19943 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19944 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19945 return(0);
19946
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019947 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019948 * SPEC au-props-correct (1)
19949 * "The values of the properties of an attribute use must be as
19950 * described in the property tableau in The Attribute Use Schema
19951 * Component (§3.5.1), modulo the impact of Missing
19952 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019953 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019954
19955 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19956 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19957 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19958 {
19959 xmlSchemaPCustomErr(ctxt,
19960 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19961 WXS_BASIC_CAST use, NULL,
19962 "The attribute declaration has a 'fixed' value constraint "
19963 ", thus the attribute use must also have a 'fixed' value "
19964 "constraint",
19965 NULL);
19966 return(ctxt->err);
19967 }
19968 /*
19969 * Compute and check the value constraint's value.
19970 */
19971 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19972 int ret;
19973 /*
19974 * TODO: The spec seems to be missing a check of the
19975 * value constraint of the attribute use. We will do it here.
19976 */
19977 /*
19978 * SPEC a-props-correct (3)
19979 */
19980 if (xmlSchemaIsDerivedFromBuiltInType(
19981 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19982 {
19983 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19984 XML_SCHEMAP_AU_PROPS_CORRECT,
19985 NULL, WXS_BASIC_CAST use,
19986 "Value constraints are not allowed if the type definition "
19987 "is or is derived from xs:ID",
19988 NULL, NULL);
19989 return(ctxt->err);
19990 }
19991
19992 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19993 use->node, WXS_ATTRUSE_TYPEDEF(use),
19994 use->defValue, &(use->defVal),
19995 1, 1, 0);
19996 if (ret != 0) {
19997 if (ret < 0) {
19998 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19999 "calling xmlSchemaVCheckCVCSimpleType()");
20000 return(-1);
20001 }
20002 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20003 XML_SCHEMAP_AU_PROPS_CORRECT,
20004 NULL, WXS_BASIC_CAST use,
20005 "The value of the value constraint is not valid",
20006 NULL, NULL);
20007 return(ctxt->err);
20008 }
20009 }
20010 /*
20011 * SPEC au-props-correct (2)
20012 * "If the {attribute declaration} has a fixed
20013 * {value constraint}, then if the attribute use itself has a
20014 * {value constraint}, it must also be fixed and its value must match
20015 * that of the {attribute declaration}'s {value constraint}."
20016 */
20017 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20018 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20019 {
20020 if (! xmlSchemaAreValuesEqual(use->defVal,
20021 (WXS_ATTRUSE_DECL(use))->defVal))
20022 {
20023 xmlSchemaPCustomErr(ctxt,
20024 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20025 WXS_BASIC_CAST use, NULL,
20026 "The 'fixed' value constraint of the attribute use "
20027 "must match the attribute declaration's value "
20028 "constraint '%s'",
20029 (WXS_ATTRUSE_DECL(use))->defValue);
20030 }
20031 return(ctxt->err);
20032 }
20033 return(0);
20034}
20035
20036
20037
20038
20039/**
20040 * xmlSchemaResolveAttrTypeReferences:
20041 * @item: an attribute declaration
20042 * @ctxt: a parser context
20043 *
20044 * Resolves the referenced type definition component.
20045 */
20046static int
20047xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20048 xmlSchemaParserCtxtPtr ctxt)
20049{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020050 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020051 * The simple type definition corresponding to the <simpleType> element
20052 * information item in the [children], if present, otherwise the simple
20053 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000020054 * [attribute], if present, otherwise the ·simple ur-type definition·.
20055 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020056 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020057 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020058 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20059 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020060 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020061 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020062 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020063
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020064 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20065 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020066 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020067 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020068 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020069 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020070 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020071 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020072 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020073 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020074 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020075
Daniel Veillard3646d642004-06-02 19:19:14 +000020076 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020077 /*
20078 * The type defaults to the xs:anySimpleType.
20079 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020080 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20081 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020082 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020083}
20084
20085/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020086 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020087 * @idc: the identity-constraint definition
20088 * @ctxt: the schema parser context
20089 * @name: the attribute name
20090 *
20091 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020092 * Schema Component Constraint:
20093 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020094 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020095static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020096xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020097 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020098{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020099 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020100 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020101 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020102 idc->ref->item = (xmlSchemaBasicItemPtr)
20103 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20104 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020105 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020106 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020107 * TODO: It is actually not an error to fail to resolve
20108 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020109 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020110 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020111 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020112 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020113 "refer", idc->ref->name,
20114 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020115 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020116 return(pctxt->err);
20117 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20118 /*
20119 * SPEC c-props-correct (1)
20120 */
20121 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20122 XML_SCHEMAP_C_PROPS_CORRECT,
20123 NULL, WXS_BASIC_CAST idc,
20124 "The keyref references a keyref",
20125 NULL, NULL);
20126 idc->ref->item = NULL;
20127 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020128 } else {
20129 if (idc->nbFields !=
20130 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20131 xmlChar *str = NULL;
20132 xmlSchemaIDCPtr refer;
20133
20134 refer = (xmlSchemaIDCPtr) idc->ref->item;
20135 /*
20136 * SPEC c-props-correct(2)
20137 * "If the {identity-constraint category} is keyref,
20138 * the cardinality of the {fields} must equal that of
20139 * the {fields} of the {referenced key}.
20140 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020141 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020142 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020143 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020144 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020145 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020146 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020147 refer->name),
20148 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020149 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020150 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020151 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020152 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020153 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020154 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020155}
20156
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020157static int
20158xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20159 xmlSchemaParserCtxtPtr pctxt)
20160{
20161 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20162 prohib->targetNamespace) == NULL) {
20163
20164 xmlSchemaPResCompAttrErr(pctxt,
20165 XML_SCHEMAP_SRC_RESOLVE,
20166 NULL, prohib->node,
20167 "ref", prohib->name, prohib->targetNamespace,
20168 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20169 return(XML_SCHEMAP_SRC_RESOLVE);
20170 }
20171 return(0);
20172}
20173
20174#define WXS_REDEFINED_TYPE(c) \
20175(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20176
20177#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20178(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20179
20180#define WXS_REDEFINED_ATTR_GROUP(c) \
20181(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20182
20183static int
20184xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20185{
20186 int err = 0;
20187 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20188 xmlSchemaBasicItemPtr prev, item;
20189 int wasRedefined;
20190
20191 if (redef == NULL)
20192 return(0);
20193
20194 do {
20195 item = redef->item;
20196 /*
20197 * First try to locate the redefined component in the
20198 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020199 * NOTE: According to this schema bug entry:
20200 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20201 * it's not clear if the referenced component needs to originate
20202 * from the <redefine>d schema _document_ or the schema; the latter
20203 * would include all imported and included sub-schemas of the
20204 * <redefine>d schema. Currenlty we latter approach is used.
20205 * SUPPLEMENT: It seems that the WG moves towards the latter
20206 * approach, so we are doing it right.
20207 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020208 */
20209 prev = xmlSchemaFindRedefCompInGraph(
20210 redef->targetBucket, item->type,
20211 redef->refName, redef->refTargetNs);
20212 if (prev == NULL) {
20213 xmlChar *str = NULL;
20214 xmlNodePtr node;
20215
20216 /*
20217 * SPEC src-redefine:
20218 * (6.2.1) "The ·actual value· of its own name attribute plus
20219 * target namespace must successfully ·resolve· to a model
20220 * group definition in I."
20221 * (7.2.1) "The ·actual value· of its own name attribute plus
20222 * target namespace must successfully ·resolve· to an attribute
20223 * group definition in I."
20224
20225 *
20226 * Note that, if we are redefining with the use of references
20227 * to components, the spec assumes the src-resolve to be used;
20228 * but this won't assure that we search only *inside* the
20229 * redefined schema.
20230 */
20231 if (redef->reference)
20232 node = WXS_ITEM_NODE(redef->reference);
20233 else
20234 node = WXS_ITEM_NODE(item);
20235 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20236 /*
20237 * TODO: error code.
20238 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20239 * reference kind.
20240 */
20241 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020242 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020243 "the redefined schema",
20244 WXS_ITEM_TYPE_NAME(item),
20245 xmlSchemaFormatQName(&str, redef->refTargetNs,
20246 redef->refName));
20247 FREE_AND_NULL(str);
20248 err = pctxt->err;
20249 redef = redef->next;
20250 continue;
20251 }
20252 /*
20253 * TODO: Obtaining and setting the redefinition state is really
20254 * clumsy.
20255 */
20256 wasRedefined = 0;
20257 switch (item->type) {
20258 case XML_SCHEMA_TYPE_COMPLEX:
20259 case XML_SCHEMA_TYPE_SIMPLE:
20260 if ((WXS_TYPE_CAST prev)->flags &
20261 XML_SCHEMAS_TYPE_REDEFINED)
20262 {
20263 wasRedefined = 1;
20264 break;
20265 }
20266 /* Mark it as redefined. */
20267 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20268 /*
20269 * Assign the redefined type to the
20270 * base type of the redefining type.
20271 * TODO: How
20272 */
20273 ((xmlSchemaTypePtr) item)->baseType =
20274 (xmlSchemaTypePtr) prev;
20275 break;
20276 case XML_SCHEMA_TYPE_GROUP:
20277 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20278 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20279 {
20280 wasRedefined = 1;
20281 break;
20282 }
20283 /* Mark it as redefined. */
20284 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20285 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20286 if (redef->reference != NULL) {
20287 /*
20288 * Overwrite the QName-reference with the
20289 * referenced model group def.
20290 */
20291 (WXS_PTC_CAST redef->reference)->children =
20292 WXS_TREE_CAST prev;
20293 }
20294 redef->target = prev;
20295 break;
20296 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20297 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20298 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20299 {
20300 wasRedefined = 1;
20301 break;
20302 }
20303 (WXS_ATTR_GROUP_CAST prev)->flags |=
20304 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20305 if (redef->reference != NULL) {
20306 /*
20307 * Assign the redefined attribute group to the
20308 * QName-reference component.
20309 * This is the easy case, since we will just
20310 * expand the redefined group.
20311 */
20312 (WXS_QNAME_CAST redef->reference)->item = prev;
20313 redef->target = NULL;
20314 } else {
20315 /*
20316 * This is the complicated case: we need
20317 * to apply src-redefine (7.2.2) at a later
20318 * stage, i.e. when attribute group references
20319 * have beed expanded and simple types have
20320 * beed fixed.
20321 */
20322 redef->target = prev;
20323 }
20324 break;
20325 default:
20326 PERROR_INT("xmlSchemaResolveRedefReferences",
20327 "Unexpected redefined component type");
20328 return(-1);
20329 }
20330 if (wasRedefined) {
20331 xmlChar *str = NULL;
20332 xmlNodePtr node;
20333
20334 if (redef->reference)
20335 node = WXS_ITEM_NODE(redef->reference);
20336 else
20337 node = WXS_ITEM_NODE(redef->item);
20338
20339 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20340 /* TODO: error code. */
20341 XML_SCHEMAP_SRC_REDEFINE,
20342 node, NULL,
20343 "The referenced %s was already redefined. Multiple "
20344 "redefinition of the same component is not supported",
20345 xmlSchemaGetComponentDesignation(&str, prev),
20346 NULL);
20347 FREE_AND_NULL(str)
20348 err = pctxt->err;
20349 redef = redef->next;
20350 continue;
20351 }
20352 redef = redef->next;
20353 } while (redef != NULL);
20354
20355 return(err);
20356}
20357
20358static int
20359xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20360{
20361 int err = 0;
20362 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20363 xmlSchemaBasicItemPtr item;
20364
20365 if (redef == NULL)
20366 return(0);
20367
20368 do {
20369 if (redef->target == NULL) {
20370 redef = redef->next;
20371 continue;
20372 }
20373 item = redef->item;
20374
20375 switch (item->type) {
20376 case XML_SCHEMA_TYPE_SIMPLE:
20377 case XML_SCHEMA_TYPE_COMPLEX:
20378 /*
20379 * Since the spec wants the {name} of the redefined
20380 * type to be 'absent', we'll NULL it.
20381 */
20382 (WXS_TYPE_CAST redef->target)->name = NULL;
20383
20384 /*
20385 * TODO: Seems like there's nothing more to do. The normal
20386 * inheritance mechanism is used. But not 100% sure.
20387 */
20388 break;
20389 case XML_SCHEMA_TYPE_GROUP:
20390 /*
20391 * URGENT TODO:
20392 * SPEC src-redefine:
20393 * (6.2.2) "The {model group} of the model group definition
20394 * which corresponds to it per XML Representation of Model
20395 * Group Definition Schema Components (§3.7.2) must be a
20396 * ·valid restriction· of the {model group} of that model
20397 * group definition in I, as defined in Particle Valid
20398 * (Restriction) (§3.9.6)."
20399 */
20400 break;
20401 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20402 /*
20403 * SPEC src-redefine:
20404 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20405 * the attribute group definition which corresponds to it
20406 * per XML Representation of Attribute Group Definition Schema
20407 * Components (§3.6.2) must be ·valid restrictions· of the
20408 * {attribute uses} and {attribute wildcard} of that attribute
20409 * group definition in I, as defined in clause 2, clause 3 and
20410 * clause 4 of Derivation Valid (Restriction, Complex)
20411 * (§3.4.6) (where references to the base type definition are
20412 * understood as references to the attribute group definition
20413 * in I)."
20414 */
20415 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20416 XML_SCHEMA_ACTION_REDEFINE,
20417 item, redef->target,
20418 (WXS_ATTR_GROUP_CAST item)->attrUses,
20419 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20420 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20421 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20422 if (err == -1)
20423 return(-1);
20424 break;
20425 default:
20426 break;
20427 }
20428 redef = redef->next;
20429 } while (redef != NULL);
20430 return(0);
20431}
20432
20433
20434static int
20435xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20436 xmlSchemaBucketPtr bucket)
20437{
20438 xmlSchemaBasicItemPtr item;
20439 int err;
20440 xmlHashTablePtr *table;
20441 const xmlChar *name;
20442 int i;
20443
20444#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20445 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20446 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20447 else \
20448 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20449
20450 /*
20451 * Add global components to the schema's hash tables.
20452 * This is the place where duplicate components will be
20453 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020454 * TODO: I think normally we should support imports of the
20455 * same namespace from multiple locations. We don't do currently,
20456 * but if we do then according to:
20457 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20458 * we would need, if imported directly, to import redefined
20459 * components as well to be able to catch clashing components.
20460 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020461 */
20462 if (bucket == NULL)
20463 return(-1);
20464 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20465 return(0);
20466 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20467
20468 for (i = 0; i < bucket->globals->nbItems; i++) {
20469 item = bucket->globals->items[i];
20470 table = NULL;
20471 switch (item->type) {
20472 case XML_SCHEMA_TYPE_COMPLEX:
20473 case XML_SCHEMA_TYPE_SIMPLE:
20474 if (WXS_REDEFINED_TYPE(item))
20475 continue;
20476 name = (WXS_TYPE_CAST item)->name;
20477 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20478 break;
20479 case XML_SCHEMA_TYPE_ELEMENT:
20480 name = (WXS_ELEM_CAST item)->name;
20481 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20482 break;
20483 case XML_SCHEMA_TYPE_ATTRIBUTE:
20484 name = (WXS_ATTR_CAST item)->name;
20485 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20486 break;
20487 case XML_SCHEMA_TYPE_GROUP:
20488 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20489 continue;
20490 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20491 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20492 break;
20493 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20494 if (WXS_REDEFINED_ATTR_GROUP(item))
20495 continue;
20496 name = (WXS_ATTR_GROUP_CAST item)->name;
20497 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20498 break;
20499 case XML_SCHEMA_TYPE_IDC_KEY:
20500 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20501 case XML_SCHEMA_TYPE_IDC_KEYREF:
20502 name = (WXS_IDC_CAST item)->name;
20503 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20504 break;
20505 case XML_SCHEMA_TYPE_NOTATION:
20506 name = ((xmlSchemaNotationPtr) item)->name;
20507 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20508 break;
20509 default:
20510 PERROR_INT("xmlSchemaAddComponents",
20511 "Unexpected global component type");
20512 continue;
20513 }
20514 if (*table == NULL) {
20515 *table = xmlHashCreateDict(10, pctxt->dict);
20516 if (*table == NULL) {
20517 PERROR_INT("xmlSchemaAddComponents",
20518 "failed to create a component hash table");
20519 return(-1);
20520 }
20521 }
20522 err = xmlHashAddEntry(*table, name, item);
20523 if (err != 0) {
20524 xmlChar *str = NULL;
20525
20526 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20527 XML_SCHEMAP_REDEFINED_TYPE,
20528 WXS_ITEM_NODE(item),
20529 WXS_BASIC_CAST item,
20530 "A global %s '%s' does already exist",
20531 WXS_ITEM_TYPE_NAME(item),
20532 xmlSchemaGetComponentQName(&str, item));
20533 FREE_AND_NULL(str);
20534 }
20535 }
20536 /*
20537 * Process imported/included schemas.
20538 */
20539 if (bucket->relations != NULL) {
20540 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20541 do {
20542 if ((rel->bucket != NULL) &&
20543 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20544 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20545 return(-1);
20546 }
20547 rel = rel->next;
20548 } while (rel != NULL);
20549 }
20550 return(0);
20551}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020552
20553static int
20554xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20555{
20556 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20557 xmlSchemaTreeItemPtr item, *items;
20558 int nbItems, i;
20559
20560#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20561
20562 if ((con->pending == NULL) ||
20563 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020564 return(0);
20565
20566 /* TODO:
20567 * SPEC (src-redefine):
20568 * (6.2) "If it has no such self-reference, then all of the
20569 * following must be true:"
20570
20571 * (6.2.2) The {model group} of the model group definition which
20572 * corresponds to it per XML Representation of Model Group
20573 * Definition Schema Components (§3.7.2) must be a ·valid
20574 * restriction· of the {model group} of that model group definition
20575 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20576 */
20577 xmlSchemaCheckSRCRedefineFirst(pctxt);
20578
20579 /*
20580 * Add global components to the schemata's hash tables.
20581 */
20582 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020583
20584 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020585 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20586 nbItems = con->pending->nbItems;
20587 /*
20588 * Now that we have parsed *all* the schema document(s) and converted
20589 * them to schema components, we can resolve references, apply component
20590 * constraints, create the FSA from the content model, etc.
20591 */
20592 /*
20593 * Resolve references of..
20594 *
20595 * 1. element declarations:
20596 * - the type definition
20597 * - the substitution group affiliation
20598 * 2. simple/complex types:
20599 * - the base type definition
20600 * - the memberTypes of union types
20601 * - the itemType of list types
20602 * 3. attributes declarations and attribute uses:
20603 * - the type definition
20604 * - if an attribute use, then the attribute declaration
20605 * 4. attribute group references:
20606 * - the attribute group definition
20607 * 5. particles:
20608 * - the term of the particle (e.g. a model group)
20609 * 6. IDC key-references:
20610 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020611 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020612 */
20613 for (i = 0; i < nbItems; i++) {
20614 item = items[i];
20615 switch (item->type) {
20616 case XML_SCHEMA_TYPE_ELEMENT:
20617 xmlSchemaResolveElementReferences(
20618 (xmlSchemaElementPtr) item, pctxt);
20619 FIXHFAILURE;
20620 break;
20621 case XML_SCHEMA_TYPE_COMPLEX:
20622 case XML_SCHEMA_TYPE_SIMPLE:
20623 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020624 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020625 FIXHFAILURE;
20626 break;
20627 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020628 xmlSchemaResolveAttrTypeReferences(
20629 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020630 FIXHFAILURE;
20631 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020632 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20633 xmlSchemaResolveAttrUseReferences(
20634 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020635 FIXHFAILURE;
20636 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020637 case XML_SCHEMA_EXTRA_QNAMEREF:
20638 if ((WXS_QNAME_CAST item)->itemType ==
20639 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20640 {
20641 xmlSchemaResolveAttrGroupReferences(
20642 WXS_QNAME_CAST item, pctxt);
20643 }
20644 FIXHFAILURE;
20645 break;
20646 case XML_SCHEMA_TYPE_SEQUENCE:
20647 case XML_SCHEMA_TYPE_CHOICE:
20648 case XML_SCHEMA_TYPE_ALL:
20649 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20650 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020651 FIXHFAILURE;
20652 break;
20653 case XML_SCHEMA_TYPE_IDC_KEY:
20654 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20655 case XML_SCHEMA_TYPE_IDC_KEYREF:
20656 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020657 (xmlSchemaIDCPtr) item, pctxt);
20658 FIXHFAILURE;
20659 break;
20660 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20661 /*
20662 * Handle attribue prohibition which had a
20663 * "ref" attribute.
20664 */
20665 xmlSchemaResolveAttrUseProhibReferences(
20666 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020667 FIXHFAILURE;
20668 break;
20669 default:
20670 break;
20671 }
20672 }
20673 if (pctxt->nberrors != 0)
20674 goto exit_error;
20675
20676 /*
20677 * Now that all references are resolved we
20678 * can check for circularity of...
20679 * 1. the base axis of type definitions
20680 * 2. nested model group definitions
20681 * 3. nested attribute group definitions
20682 * TODO: check for circual substitution groups.
20683 */
20684 for (i = 0; i < nbItems; i++) {
20685 item = items[i];
20686 /*
20687 * Let's better stop on the first error here.
20688 */
20689 switch (item->type) {
20690 case XML_SCHEMA_TYPE_COMPLEX:
20691 case XML_SCHEMA_TYPE_SIMPLE:
20692 xmlSchemaCheckTypeDefCircular(
20693 (xmlSchemaTypePtr) item, pctxt);
20694 FIXHFAILURE;
20695 if (pctxt->nberrors != 0)
20696 goto exit_error;
20697 break;
20698 case XML_SCHEMA_TYPE_GROUP:
20699 xmlSchemaCheckGroupDefCircular(
20700 (xmlSchemaModelGroupDefPtr) item, pctxt);
20701 FIXHFAILURE;
20702 if (pctxt->nberrors != 0)
20703 goto exit_error;
20704 break;
20705 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20706 xmlSchemaCheckAttrGroupCircular(
20707 (xmlSchemaAttributeGroupPtr) item, pctxt);
20708 FIXHFAILURE;
20709 if (pctxt->nberrors != 0)
20710 goto exit_error;
20711 break;
20712 default:
20713 break;
20714 }
20715 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020716 if (pctxt->nberrors != 0)
20717 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020718 /*
20719 * Model group definition references:
20720 * Such a reference is reflected by a particle at the component
20721 * level. Until now the 'term' of such particles pointed
20722 * to the model group definition; this was done, in order to
20723 * ease circularity checks. Now we need to set the 'term' of
20724 * such particles to the model group of the model group definition.
20725 */
20726 for (i = 0; i < nbItems; i++) {
20727 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020728 switch (item->type) {
20729 case XML_SCHEMA_TYPE_SEQUENCE:
20730 case XML_SCHEMA_TYPE_CHOICE:
20731 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20732 WXS_MODEL_GROUP_CAST item);
20733 break;
20734 default:
20735 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020736 }
20737 }
20738 if (pctxt->nberrors != 0)
20739 goto exit_error;
20740 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020741 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020742 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020743 for (i = 0; i < nbItems; i++) {
20744 item = items[i];
20745 switch (item->type) {
20746 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20747 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20748 WXS_ATTR_GROUP_HAS_REFS(item))
20749 {
20750 xmlSchemaAttributeGroupExpandRefs(pctxt,
20751 WXS_ATTR_GROUP_CAST item);
20752 FIXHFAILURE;
20753 }
20754 break;
20755 default:
20756 break;
20757 }
20758 }
20759 if (pctxt->nberrors != 0)
20760 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020761 /*
20762 * First compute the variety of simple types. This is needed as
20763 * a seperate step, since otherwise we won't be able to detect
20764 * circular union types in all cases.
20765 */
20766 for (i = 0; i < nbItems; i++) {
20767 item = items[i];
20768 switch (item->type) {
20769 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020770 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020771 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20772 (xmlSchemaTypePtr) item);
20773 FIXHFAILURE;
20774 }
20775 break;
20776 default:
20777 break;
20778 }
20779 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020780 if (pctxt->nberrors != 0)
20781 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020782 /*
20783 * Detect circular union types. Note that this needs the variety to
20784 * be already computed.
20785 */
20786 for (i = 0; i < nbItems; i++) {
20787 item = items[i];
20788 switch (item->type) {
20789 case XML_SCHEMA_TYPE_SIMPLE:
20790 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20791 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20792 (xmlSchemaTypePtr) item);
20793 FIXHFAILURE;
20794 }
20795 break;
20796 default:
20797 break;
20798 }
20799 }
20800 if (pctxt->nberrors != 0)
20801 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020802
20803 /*
20804 * Do the complete type fixup for simple types.
20805 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020806 for (i = 0; i < nbItems; i++) {
20807 item = items[i];
20808 switch (item->type) {
20809 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020810 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20811 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20812 FIXHFAILURE;
20813 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020814 break;
20815 default:
20816 break;
20817 }
20818 }
20819 if (pctxt->nberrors != 0)
20820 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020821 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020822 * At this point we need all simple types to be builded and checked.
20823 */
20824 /*
20825 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020826 */
20827 for (i = 0; i < nbItems; i++) {
20828 item = items[i];
20829 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020830 case XML_SCHEMA_TYPE_ATTRIBUTE:
20831 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20832 FIXHFAILURE;
20833 break;
20834 default:
20835 break;
20836 }
20837 }
20838 if (pctxt->nberrors != 0)
20839 goto exit_error;
20840 /*
20841 * Apply constraints for attribute uses.
20842 */
20843 for (i = 0; i < nbItems; i++) {
20844 item = items[i];
20845 switch (item->type) {
20846 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20847 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20848 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20849 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020850 FIXHFAILURE;
20851 }
20852 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020853 default:
20854 break;
20855 }
20856 }
20857 if (pctxt->nberrors != 0)
20858 goto exit_error;
20859
20860 /*
20861 * Apply constraints for attribute group definitions.
20862 */
20863 for (i = 0; i < nbItems; i++) {
20864 item = items[i];
20865 switch (item->type) {
20866 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20867 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20868 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20869 {
20870 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20871 FIXHFAILURE;
20872 }
20873 break;
20874 default:
20875 break;
20876 }
20877 }
20878 if (pctxt->nberrors != 0)
20879 goto exit_error;
20880
20881 /*
20882 * Apply constraints for redefinitions.
20883 */
20884 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20885 xmlSchemaCheckSRCRedefineSecond(pctxt);
20886 if (pctxt->nberrors != 0)
20887 goto exit_error;
20888
20889 /*
20890 * Fixup complex types.
20891 */
20892 for (i = 0; i < nbItems; i++) {
20893 item = con->pending->items[i];
20894 switch (item->type) {
20895 case XML_SCHEMA_TYPE_COMPLEX:
20896 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20897 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20898 FIXHFAILURE;
20899 }
20900 break;
20901 default:
20902 break;
20903 }
20904 }
20905 if (pctxt->nberrors != 0)
20906 goto exit_error;
20907
20908 /*
20909 * The list could have changed, since xmlSchemaFixupComplexType()
20910 * will create particles and model groups in some cases.
20911 */
20912 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20913 nbItems = con->pending->nbItems;
20914
20915 /*
20916 * At this point all complex types need to be builded and checked.
20917 */
20918 /*
20919 * Apply some constraints for element declarations.
20920 */
20921 for (i = 0; i < nbItems; i++) {
20922 item = items[i];
20923 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020924 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020925
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020926 if ((((xmlSchemaElementPtr) item)->flags &
20927 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20928 xmlSchemaCheckElementDeclComponent(
20929 (xmlSchemaElementPtr) item, pctxt);
20930 FIXHFAILURE;
20931 }
20932 break;
20933 default:
20934 break;
20935 }
20936 }
20937 if (pctxt->nberrors != 0)
20938 goto exit_error;
20939 /*
20940 * Finally we can build the automaton from the content model of
20941 * complex types.
20942 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020943
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020944 for (i = 0; i < nbItems; i++) {
20945 item = items[i];
20946 switch (item->type) {
20947 case XML_SCHEMA_TYPE_COMPLEX:
20948 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020949 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020950 break;
20951 default:
20952 break;
20953 }
20954 }
20955 if (pctxt->nberrors != 0)
20956 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020957 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020958 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020959 */
20960 con->pending->nbItems = 0;
20961 return(0);
20962exit_error:
20963 con->pending->nbItems = 0;
20964 return(pctxt->err);
20965exit_failure:
20966 con->pending->nbItems = 0;
20967 return(-1);
20968}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020969/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020970 * xmlSchemaParse:
20971 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020972 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020973 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020974 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000020975 *
20976 * Returns the internal XML Schema structure built from the resource or
20977 * NULL in case of error
20978 */
20979xmlSchemaPtr
20980xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20981{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020982 xmlSchemaPtr schema = NULL;
20983 xmlSchemaBucketPtr bucket = NULL;
20984 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020985
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020987 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020988 * the API; i.e. not automatically by the validated instance document.
20989 */
20990
Daniel Veillard4255d502002-04-16 15:50:10 +000020991 xmlSchemaInitTypes();
20992
Daniel Veillard6045c902002-10-09 21:13:59 +000020993 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020994 return (NULL);
20995
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020996 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020997 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020998 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020999 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021000
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021001 /* Create the *main* schema. */
21002 schema = xmlSchemaNewSchema(ctxt);
21003 if (schema == NULL)
21004 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021005 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021006 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021007 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021008 if (ctxt->constructor == NULL) {
21009 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21010 if (ctxt->constructor == NULL)
21011 return(NULL);
21012 /* Take ownership of the constructor to be able to free it. */
21013 ctxt->ownsConstructor = 1;
21014 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021015 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021016 /*
21017 * Locate and add the schema document.
21018 */
21019 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21020 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21021 NULL, NULL, &bucket);
21022 if (res == -1)
21023 goto exit_failure;
21024 if (res != 0)
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000021025 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021026
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021027 if (bucket == NULL) {
21028 /* TODO: Error code, actually we failed to *locate* the schema. */
21029 if (ctxt->URL)
21030 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21031 NULL, NULL,
21032 "Failed to locate the main schema resource at '%s'",
21033 ctxt->URL, NULL);
21034 else
21035 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21036 NULL, NULL,
21037 "Failed to locate the main schema resource",
21038 NULL, NULL);
21039 goto exit;
21040 }
21041 /* Set the main schema bucket. */
21042 ctxt->constructor->bucket = bucket;
21043 ctxt->targetNamespace = bucket->targetNamespace;
21044 schema->targetNamespace = bucket->targetNamespace;
21045
21046 /* Then do the parsing for good. */
21047 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
21048 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021049 if (ctxt->nberrors != 0)
21050 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021051
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021052 schema->doc = bucket->doc;
21053 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021054
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021055 ctxt->schema = schema;
21056
21057 if (xmlSchemaFixupComponents(ctxt) == -1)
21058 goto exit_failure;
21059
21060 /*
21061 * TODO: This is not nice, since we cannot distinguish from the
21062 * result if there was an internal error or not.
21063 */
21064exit:
21065 if (ctxt->nberrors != 0) {
21066 if (schema) {
21067 xmlSchemaFree(schema);
21068 schema = NULL;
21069 }
21070 if (ctxt->constructor) {
21071 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21072 ctxt->constructor = NULL;
21073 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021074 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021075 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021076 ctxt->schema = NULL;
21077 return(schema);
21078exit_failure:
21079 /*
21080 * Quite verbose, but should catch internal errors, which were
21081 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021082 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021083 if (schema) {
21084 xmlSchemaFree(schema);
21085 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021086 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021087 if (ctxt->constructor) {
21088 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21089 ctxt->constructor = NULL;
21090 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021091 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021092 PERROR_INT2("xmlSchemaParse",
21093 "An internal error occured");
21094 ctxt->schema = NULL;
21095 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021096}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021097
Daniel Veillard4255d502002-04-16 15:50:10 +000021098/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021099 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021100 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021101 * @err: the error callback
21102 * @warn: the warning callback
21103 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021104 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021105 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021106 */
21107void
21108xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021109 xmlSchemaValidityErrorFunc err,
21110 xmlSchemaValidityWarningFunc warn, void *ctx)
21111{
Daniel Veillard4255d502002-04-16 15:50:10 +000021112 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021113 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021114 ctxt->error = err;
21115 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021116 ctxt->errCtxt = ctx;
21117 if (ctxt->vctxt != NULL)
21118 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21119}
21120
21121/**
21122 * xmlSchemaSetParserStructuredErrors:
21123 * @ctxt: a schema parser context
21124 * @serror: the structured error function
21125 * @ctx: the functions context
21126 *
21127 * Set the structured error callback
21128 */
21129void
21130xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21131 xmlStructuredErrorFunc serror,
21132 void *ctx)
21133{
21134 if (ctxt == NULL)
21135 return;
21136 ctxt->serror = serror;
21137 ctxt->errCtxt = ctx;
21138 if (ctxt->vctxt != NULL)
21139 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021140}
21141
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021142/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021143 * xmlSchemaGetParserErrors:
21144 * @ctxt: a XMl-Schema parser context
21145 * @err: the error callback result
21146 * @warn: the warning callback result
21147 * @ctx: contextual data for the callbacks result
21148 *
21149 * Get the callback information used to handle errors for a parser context
21150 *
21151 * Returns -1 in case of failure, 0 otherwise
21152 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021153int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021154xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021155 xmlSchemaValidityErrorFunc * err,
21156 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021157{
21158 if (ctxt == NULL)
21159 return(-1);
21160 if (err != NULL)
21161 *err = ctxt->error;
21162 if (warn != NULL)
21163 *warn = ctxt->warning;
21164 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021165 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021166 return(0);
21167}
21168
21169/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021170 * xmlSchemaFacetTypeToString:
21171 * @type: the facet type
21172 *
21173 * Convert the xmlSchemaTypeType to a char string.
21174 *
21175 * Returns the char string representation of the facet type if the
21176 * type is a facet and an "Internal Error" string otherwise.
21177 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021178static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021179xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21180{
21181 switch (type) {
21182 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021183 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021184 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021185 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021186 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021187 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021188 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021189 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021190 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021191 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021192 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021193 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021194 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021195 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021196 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021197 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021198 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021199 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021200 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021201 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021202 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021203 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021204 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021205 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021206 default:
21207 break;
21208 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021209 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021210}
21211
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021212static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021213xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21214{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021215 /*
21216 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021217 * from xsd:string.
21218 */
21219 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021220 /*
21221 * Note that we assume a whitespace of preserve for anySimpleType.
21222 */
21223 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21224 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21225 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021226 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021227 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021228 else {
21229 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021230 * For all ·atomic· datatypes other than string (and types ·derived·
21231 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021232 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021233 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021234 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021235 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021236 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021237 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021238 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021239 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021240 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021241 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021242 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021243 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021244 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021245 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21246 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21247 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21248 return (XML_SCHEMA_WHITESPACE_REPLACE);
21249 else
21250 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021252 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021253}
21254
Daniel Veillard4255d502002-04-16 15:50:10 +000021255/************************************************************************
21256 * *
21257 * Simple type validation *
21258 * *
21259 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021260
Daniel Veillard4255d502002-04-16 15:50:10 +000021261
21262/************************************************************************
21263 * *
21264 * DOM Validation code *
21265 * *
21266 ************************************************************************/
21267
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021268/**
21269 * xmlSchemaAssembleByLocation:
21270 * @pctxt: a schema parser context
21271 * @vctxt: a schema validation context
21272 * @schema: the existing schema
21273 * @node: the node that fired the assembling
21274 * @nsName: the namespace name of the new schema
21275 * @location: the location of the schema
21276 *
21277 * Expands an existing schema by an additional schema.
21278 *
21279 * Returns 0 if the new schema is correct, a positive error code
21280 * number otherwise and -1 in case of an internal or API error.
21281 */
21282static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021283xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021284 xmlSchemaPtr schema,
21285 xmlNodePtr node,
21286 const xmlChar *nsName,
21287 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021288{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021289 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021290 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021291 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021292
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021293 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021294 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021295
21296 if (vctxt->pctxt == NULL) {
21297 VERROR_INT("xmlSchemaAssembleByLocation",
21298 "no parser context available");
21299 return(-1);
21300 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021301 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021302 if (pctxt->constructor == NULL) {
21303 PERROR_INT("xmlSchemaAssembleByLocation",
21304 "no constructor");
21305 return(-1);
21306 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021307 /*
21308 * Acquire the schema document.
21309 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021310 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21311 location, node);
21312 /*
21313 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21314 * the process will automatically change this to
21315 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21316 */
21317 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21318 location, NULL, NULL, 0, node, NULL, nsName,
21319 &bucket);
21320 if (ret != 0)
21321 return(ret);
21322 if (bucket == NULL) {
21323 PERROR_INT("xmlSchemaAssembleByLocation",
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021324 "no schema bucket acquired");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021325 return(-1);
21326 }
21327 /*
21328 * The first located schema will be handled as if all other
21329 * schemas imported by XSI were imported by this first schema.
21330 */
21331 if ((bucket != NULL) &&
21332 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21333 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21334 /*
21335 * TODO: Is this handled like an import? I.e. is it not an error
21336 * if the schema cannot be located?
21337 */
21338 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21339 return(0);
21340 /*
21341 * We will reuse the parser context for every schema imported
21342 * directly via XSI. So reset the context.
21343 */
21344 pctxt->nberrors = 0;
21345 pctxt->err = 0;
21346 pctxt->doc = bucket->doc;
21347
21348 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21349 if (ret == -1) {
21350 pctxt->doc = NULL;
21351 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021352 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021353 /* Paranoid error channelling. */
21354 if ((ret == 0) && (pctxt->nberrors != 0))
21355 ret = pctxt->err;
21356 if (pctxt->nberrors == 0) {
21357 /*
21358 * Only bother to fixup pending components, if there was
21359 * no error yet.
21360 */
21361 xmlSchemaFixupComponents(pctxt);
21362 vctxt->nberrors += pctxt->nberrors;
21363 } else {
21364 /* Add to validation error sum. */
21365 vctxt->nberrors += pctxt->nberrors;
21366 }
21367 pctxt->doc = NULL;
21368 return(ret);
21369exit_failure:
21370 pctxt->doc = NULL;
21371 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021372}
21373
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021374static xmlSchemaAttrInfoPtr
21375xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21376 int metaType)
21377{
21378 if (vctxt->nbAttrInfos == 0)
21379 return (NULL);
21380 {
21381 int i;
21382 xmlSchemaAttrInfoPtr iattr;
21383
21384 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21385 iattr = vctxt->attrInfos[i];
21386 if (iattr->metaType == metaType)
21387 return (iattr);
21388 }
21389
21390 }
21391 return (NULL);
21392}
21393
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021394/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021395 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021396 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021397 *
21398 * Expands an existing schema by an additional schema using
21399 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21400 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21401 * must be set to 1.
21402 *
21403 * Returns 0 if the new schema is correct, a positive error code
21404 * number otherwise and -1 in case of an internal or API error.
21405 */
21406static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021407xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021408{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021409 const xmlChar *cur, *end;
21410 const xmlChar *nsname = NULL, *location;
21411 int count = 0;
21412 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021413 xmlSchemaAttrInfoPtr iattr;
21414
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021415 /*
21416 * Parse the value; we will assume an even number of values
21417 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021418 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021419 * URGENT TODO: !! This needs to work for both
21420 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21421 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021422 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021423 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21424 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21425 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021426 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021427 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21428 if (iattr == NULL)
21429 return (0);
21430 cur = iattr->value;
21431 do {
21432 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021433 /*
21434 * Get the namespace name.
21435 */
21436 while (IS_BLANK_CH(*cur))
21437 cur++;
21438 end = cur;
21439 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21440 end++;
21441 if (end == cur)
21442 break;
21443 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021444 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021445 cur = end;
21446 }
21447 /*
21448 * Get the URI.
21449 */
21450 while (IS_BLANK_CH(*cur))
21451 cur++;
21452 end = cur;
21453 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21454 end++;
21455 if (end == cur)
21456 break;
21457 count++;
21458 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021459 cur = end;
21460 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21461 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021462 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021463 VERROR_INT("xmlSchemaAssembleByXSI",
21464 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021465 return (-1);
21466 }
21467 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021468 return (ret);
21469}
21470
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021471static const xmlChar *
21472xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21473 const xmlChar *prefix)
21474{
21475 if (vctxt->sax != NULL) {
21476 int i, j;
21477 xmlSchemaNodeInfoPtr inode;
21478
21479 for (i = vctxt->depth; i >= 0; i--) {
21480 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21481 inode = vctxt->elemInfos[i];
21482 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21483 if (((prefix == NULL) &&
21484 (inode->nsBindings[j] == NULL)) ||
21485 ((prefix != NULL) && xmlStrEqual(prefix,
21486 inode->nsBindings[j]))) {
21487
21488 /*
21489 * Note that the namespace bindings are already
21490 * in a string dict.
21491 */
21492 return (inode->nsBindings[j+1]);
21493 }
21494 }
21495 }
21496 }
21497 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021498#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021499 } else if (vctxt->reader != NULL) {
21500 xmlChar *nsName;
21501
21502 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21503 if (nsName != NULL) {
21504 const xmlChar *ret;
21505
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021506 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21507 xmlFree(nsName);
21508 return (ret);
21509 } else
21510 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021511#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021512 } else {
21513 xmlNsPtr ns;
21514
21515 if ((vctxt->inode->node == NULL) ||
21516 (vctxt->inode->node->doc == NULL)) {
21517 VERROR_INT("xmlSchemaLookupNamespace",
21518 "no node or node's doc avaliable");
21519 return (NULL);
21520 }
21521 ns = xmlSearchNs(vctxt->inode->node->doc,
21522 vctxt->inode->node, prefix);
21523 if (ns != NULL)
21524 return (ns->href);
21525 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021526 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021527}
21528
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021529/*
21530* This one works on the schema of the validation context.
21531*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021532static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021533xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21534 xmlSchemaPtr schema,
21535 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021536 const xmlChar *value,
21537 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021538 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021539{
21540 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021541
21542 if (vctxt && (vctxt->schema == NULL)) {
21543 VERROR_INT("xmlSchemaValidateNotation",
21544 "a schema is needed on the validation context");
21545 return (-1);
21546 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021547 ret = xmlValidateQName(value, 1);
21548 if (ret != 0)
21549 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021550 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021551 xmlChar *localName = NULL;
21552 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021553
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021554 localName = xmlSplitQName2(value, &prefix);
21555 if (prefix != NULL) {
21556 const xmlChar *nsName = NULL;
21557
21558 if (vctxt != NULL)
21559 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21560 else if (node != NULL) {
21561 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21562 if (ns != NULL)
21563 nsName = ns->href;
21564 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021565 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021566 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021567 return (1);
21568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021569 if (nsName == NULL) {
21570 xmlFree(prefix);
21571 xmlFree(localName);
21572 return (1);
21573 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021574 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021575 if (valNeeded && (val != NULL)) {
21576 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21577 BAD_CAST xmlStrdup(nsName));
21578 if (*val == NULL)
21579 ret = -1;
21580 }
21581 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021582 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021583 xmlFree(prefix);
21584 xmlFree(localName);
21585 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021586 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021587 if (valNeeded && (val != NULL)) {
21588 (*val) = xmlSchemaNewNOTATIONValue(
21589 BAD_CAST xmlStrdup(value), NULL);
21590 if (*val == NULL)
21591 ret = -1;
21592 }
21593 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021594 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021595 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021597 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021598}
21599
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021600static int
21601xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21602 const xmlChar* lname,
21603 const xmlChar* nsname)
21604{
21605 int i;
21606
21607 lname = xmlDictLookup(vctxt->dict, lname, -1);
21608 if (lname == NULL)
21609 return(-1);
21610 if (nsname != NULL) {
21611 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21612 if (nsname == NULL)
21613 return(-1);
21614 }
21615 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21616 if ((vctxt->nodeQNames->items [i] == lname) &&
21617 (vctxt->nodeQNames->items[i +1] == nsname))
21618 /* Already there */
21619 return(i);
21620 }
21621 /* Add new entry. */
21622 i = vctxt->nodeQNames->nbItems;
21623 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21624 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21625 return(i);
21626}
21627
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021628/************************************************************************
21629 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021630 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021631 * *
21632 ************************************************************************/
21633
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021634/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021635 * xmlSchemaAugmentIDC:
21636 * @idcDef: the IDC definition
21637 *
21638 * Creates an augmented IDC definition item.
21639 *
21640 * Returns the item, or NULL on internal errors.
21641 */
21642static void
21643xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21644 xmlSchemaValidCtxtPtr vctxt)
21645{
21646 xmlSchemaIDCAugPtr aidc;
21647
21648 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21649 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021650 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021651 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21652 NULL);
21653 return;
21654 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021655 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021656 aidc->def = idcDef;
21657 aidc->next = NULL;
21658 if (vctxt->aidcs == NULL)
21659 vctxt->aidcs = aidc;
21660 else {
21661 aidc->next = vctxt->aidcs;
21662 vctxt->aidcs = aidc;
21663 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021664 /*
21665 * Save if we have keyrefs at all.
21666 */
21667 if ((vctxt->hasKeyrefs == 0) &&
21668 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21669 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021670}
21671
21672/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021673 * xmlSchemaIDCNewBinding:
21674 * @idcDef: the IDC definition of this binding
21675 *
21676 * Creates a new IDC binding.
21677 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021678 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021679 */
21680static xmlSchemaPSVIIDCBindingPtr
21681xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21682{
21683 xmlSchemaPSVIIDCBindingPtr ret;
21684
21685 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21686 sizeof(xmlSchemaPSVIIDCBinding));
21687 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021688 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021689 "allocating a PSVI IDC binding item", NULL);
21690 return (NULL);
21691 }
21692 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21693 ret->definition = idcDef;
21694 return (ret);
21695}
21696
21697/**
21698 * xmlSchemaIDCStoreNodeTableItem:
21699 * @vctxt: the WXS validation context
21700 * @item: the IDC node table item
21701 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021702 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021703 * They are stored to avoid copying them if IDC node-tables are merged
21704 * with corresponding parent IDC node-tables (bubbling).
21705 *
21706 * Returns 0 if succeeded, -1 on internal errors.
21707 */
21708static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021709xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021710 xmlSchemaPSVIIDCNodePtr item)
21711{
21712 /*
21713 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021714 */
21715 if (vctxt->idcNodes == NULL) {
21716 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021717 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21718 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021719 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021720 "allocating the IDC node table item list", NULL);
21721 return (-1);
21722 }
21723 vctxt->sizeIdcNodes = 20;
21724 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21725 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021726 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21727 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021728 sizeof(xmlSchemaPSVIIDCNodePtr));
21729 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021730 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021731 "re-allocating the IDC node table item list", NULL);
21732 return (-1);
21733 }
21734 }
21735 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021736
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021737 return (0);
21738}
21739
21740/**
21741 * xmlSchemaIDCStoreKey:
21742 * @vctxt: the WXS validation context
21743 * @item: the IDC key
21744 *
21745 * The validation context is used to store an IDC key.
21746 *
21747 * Returns 0 if succeeded, -1 on internal errors.
21748 */
21749static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021750xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021751 xmlSchemaPSVIIDCKeyPtr key)
21752{
21753 /*
21754 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021755 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021756 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021757 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021758 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21759 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021760 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021761 "allocating the IDC key storage list", NULL);
21762 return (-1);
21763 }
21764 vctxt->sizeIdcKeys = 40;
21765 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21766 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021767 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21768 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021769 sizeof(xmlSchemaPSVIIDCKeyPtr));
21770 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021771 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021772 "re-allocating the IDC key storage list", NULL);
21773 return (-1);
21774 }
21775 }
21776 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021777
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021778 return (0);
21779}
21780
21781/**
21782 * xmlSchemaIDCAppendNodeTableItem:
21783 * @bind: the IDC binding
21784 * @ntItem: the node-table item
21785 *
21786 * Appends the IDC node-table item to the binding.
21787 *
21788 * Returns 0 on success and -1 on internal errors.
21789 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021790static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021791xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21792 xmlSchemaPSVIIDCNodePtr ntItem)
21793{
21794 if (bind->nodeTable == NULL) {
21795 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021796 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021797 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21798 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021799 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021800 "allocating an array of IDC node-table items", NULL);
21801 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021802 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021803 } else if (bind->sizeNodes <= bind->nbNodes) {
21804 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021805 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21806 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021807 sizeof(xmlSchemaPSVIIDCNodePtr));
21808 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021809 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021810 "re-allocating an array of IDC node-table items", NULL);
21811 return(-1);
21812 }
21813 }
21814 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021815 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021816}
21817
21818/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021819 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021820 * @vctxt: the WXS validation context
21821 * @matcher: the IDC matcher
21822 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021823 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021824 * of the given matcher. If none found, a new one is created
21825 * and added to the IDC table.
21826 *
21827 * Returns an IDC binding or NULL on internal errors.
21828 */
21829static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021830xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021831 xmlSchemaIDCMatcherPtr matcher)
21832{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021833 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021834
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021835 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021836
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021837 if (ielem->idcTable == NULL) {
21838 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21839 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021840 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021841 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021842 } else {
21843 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021844
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021845 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021846 do {
21847 if (bind->definition == matcher->aidc->def)
21848 return(bind);
21849 if (bind->next == NULL) {
21850 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21851 if (bind->next == NULL)
21852 return (NULL);
21853 return(bind->next);
21854 }
21855 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021856 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021857 }
21858 return (NULL);
21859}
21860
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021861static xmlSchemaItemListPtr
21862xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21863 xmlSchemaIDCMatcherPtr matcher)
21864{
21865 if (matcher->targets == NULL)
21866 matcher->targets = xmlSchemaItemListCreate();
21867 return(matcher->targets);
21868}
21869
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021870/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021871 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021872 * @key: the IDC key
21873 *
21874 * Frees an IDC key together with its compiled value.
21875 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021876static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021877xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21878{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021879 if (key->val != NULL)
21880 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021881 xmlFree(key);
21882}
21883
21884/**
21885 * xmlSchemaIDCFreeBinding:
21886 *
21887 * Frees an IDC binding. Note that the node table-items
21888 * are not freed.
21889 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021890static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021891xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21892{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021893 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021894 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021895 if (bind->dupls != NULL)
21896 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021897 xmlFree(bind);
21898}
21899
21900/**
21901 * xmlSchemaIDCFreeIDCTable:
21902 * @bind: the first IDC binding in the list
21903 *
21904 * Frees an IDC table, i.e. all the IDC bindings in the list.
21905 */
21906static void
21907xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21908{
21909 xmlSchemaPSVIIDCBindingPtr prev;
21910
21911 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021912 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021913 bind = bind->next;
21914 xmlSchemaIDCFreeBinding(prev);
21915 }
21916}
21917
21918/**
21919 * xmlSchemaIDCFreeMatcherList:
21920 * @matcher: the first IDC matcher in the list
21921 *
21922 * Frees a list of IDC matchers.
21923 */
21924static void
21925xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21926{
21927 xmlSchemaIDCMatcherPtr next;
21928
21929 while (matcher != NULL) {
21930 next = matcher->next;
21931 if (matcher->keySeqs != NULL) {
21932 int i;
21933 for (i = 0; i < matcher->sizeKeySeqs; i++)
21934 if (matcher->keySeqs[i] != NULL)
21935 xmlFree(matcher->keySeqs[i]);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021936 xmlFree(matcher->keySeqs);
21937 }
21938 if (matcher->targets != NULL) {
21939 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
21940 int i;
21941 xmlSchemaPSVIIDCNodePtr idcNode;
21942 /*
21943 * Node-table items for keyrefs are not stored globally
21944 * to the validation context, since they are not bubbled.
21945 * We need to free them here.
21946 */
21947 for (i = 0; i < matcher->targets->nbItems; i++) {
21948 idcNode =
21949 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
21950 xmlFree(idcNode->keys);
21951 xmlFree(idcNode);
21952 }
21953 }
21954 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021955 }
21956 xmlFree(matcher);
21957 matcher = next;
21958 }
21959}
21960
21961/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021962 * xmlSchemaIDCAddStateObject:
21963 * @vctxt: the WXS validation context
21964 * @matcher: the IDC matcher
21965 * @sel: the XPath information
21966 * @parent: the parent "selector" state object if any
21967 * @type: "selector" or "field"
21968 *
21969 * Creates/reuses and activates state objects for the given
21970 * XPath information; if the XPath expression consists of unions,
21971 * multiple state objects are created for every unioned expression.
21972 *
21973 * Returns 0 on success and -1 on internal errors.
21974 */
21975static int
21976xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21977 xmlSchemaIDCMatcherPtr matcher,
21978 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021979 int type)
21980{
21981 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021982
21983 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021984 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021985 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021986 if (vctxt->xpathStatePool != NULL) {
21987 sto = vctxt->xpathStatePool;
21988 vctxt->xpathStatePool = sto->next;
21989 sto->next = NULL;
21990 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021991 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021992 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021993 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021994 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21995 if (sto == NULL) {
21996 xmlSchemaVErrMemory(NULL,
21997 "allocating an IDC state object", NULL);
21998 return (-1);
21999 }
22000 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22001 }
22002 /*
22003 * Add to global list.
22004 */
22005 if (vctxt->xpathStates != NULL)
22006 sto->next = vctxt->xpathStates;
22007 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022008
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022009 /*
22010 * Free the old xpath validation context.
22011 */
22012 if (sto->xpathCtxt != NULL)
22013 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22014
22015 /*
22016 * Create a new XPath (pattern) validation context.
22017 */
22018 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22019 (xmlPatternPtr) sel->xpathComp);
22020 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022021 VERROR_INT("xmlSchemaIDCAddStateObject",
22022 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022023 return (-1);
22024 }
22025 sto->type = type;
22026 sto->depth = vctxt->depth;
22027 sto->matcher = matcher;
22028 sto->sel = sel;
22029 sto->nbHistory = 0;
22030
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022031#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022032 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22033 sto->sel->xpath);
22034#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022035 return (0);
22036}
22037
22038/**
22039 * xmlSchemaXPathEvaluate:
22040 * @vctxt: the WXS validation context
22041 * @nodeType: the nodeType of the current node
22042 *
22043 * Evaluates all active XPath state objects.
22044 *
22045 * Returns the number of IC "field" state objects which resolved to
22046 * this node, 0 if none resolved and -1 on internal errors.
22047 */
22048static int
22049xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022050 xmlElementType nodeType)
22051{
22052 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022053 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022054
22055 if (vctxt->xpathStates == NULL)
22056 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022057
22058 if (nodeType == XML_ATTRIBUTE_NODE)
22059 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022060#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022061 {
22062 xmlChar *str = NULL;
22063 xmlGenericError(xmlGenericErrorContext,
22064 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022065 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22066 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022067 FREE_AND_NULL(str)
22068 }
22069#endif
22070 /*
22071 * Process all active XPath state objects.
22072 */
22073 first = vctxt->xpathStates;
22074 sto = first;
22075 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022076#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022077 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022078 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22079 sto->matcher->aidc->def->name, sto->sel->xpath);
22080 else
22081 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22082 sto->matcher->aidc->def->name, sto->sel->xpath);
22083#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022084 if (nodeType == XML_ELEMENT_NODE)
22085 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022086 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022087 else
22088 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022089 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022090
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022091 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022092 VERROR_INT("xmlSchemaXPathEvaluate",
22093 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022094 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022095 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022096 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022097 goto next_sto;
22098 /*
22099 * Full match.
22100 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022101#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022102 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022103 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022104#endif
22105 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022106 * Register a match in the state object history.
22107 */
22108 if (sto->history == NULL) {
22109 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22110 if (sto->history == NULL) {
22111 xmlSchemaVErrMemory(NULL,
22112 "allocating the state object history", NULL);
22113 return(-1);
22114 }
22115 sto->sizeHistory = 10;
22116 } else if (sto->sizeHistory <= sto->nbHistory) {
22117 sto->sizeHistory *= 2;
22118 sto->history = (int *) xmlRealloc(sto->history,
22119 sto->sizeHistory * sizeof(int));
22120 if (sto->history == NULL) {
22121 xmlSchemaVErrMemory(NULL,
22122 "re-allocating the state object history", NULL);
22123 return(-1);
22124 }
22125 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022126 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022127
22128#ifdef DEBUG_IDC
22129 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22130 vctxt->depth);
22131#endif
22132
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022133 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22134 xmlSchemaIDCSelectPtr sel;
22135 /*
22136 * Activate state objects for the IDC fields of
22137 * the IDC selector.
22138 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022139#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022140 xmlGenericError(xmlGenericErrorContext, "IDC: "
22141 "activating field states\n");
22142#endif
22143 sel = sto->matcher->aidc->def->fields;
22144 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022145 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22146 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22147 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022148 sel = sel->next;
22149 }
22150 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22151 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022152 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022153 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022154#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022155 xmlGenericError(xmlGenericErrorContext,
22156 "IDC: key found\n");
22157#endif
22158 /*
22159 * Notify that the character value of this node is
22160 * needed.
22161 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022162 if (resolved == 0) {
22163 if ((vctxt->inode->flags &
22164 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22165 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22166 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022167 resolved++;
22168 }
22169next_sto:
22170 if (sto->next == NULL) {
22171 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022172 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022173 */
22174 head = first;
22175 sto = vctxt->xpathStates;
22176 } else
22177 sto = sto->next;
22178 }
22179 return (resolved);
22180}
22181
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022182static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022183xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022184 xmlChar **buf,
22185 xmlSchemaPSVIIDCKeyPtr *seq,
22186 int count)
22187{
22188 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022189 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022190
22191 *buf = xmlStrdup(BAD_CAST "[");
22192 for (i = 0; i < count; i++) {
22193 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022194 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22195 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22196 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022197 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022198 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022199 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022200 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22201 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022202 *buf = xmlStrcat(*buf, BAD_CAST "???");
22203 }
22204 if (i < count -1)
22205 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22206 else
22207 *buf = xmlStrcat(*buf, BAD_CAST "'");
22208 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022209 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022210 value = NULL;
22211 }
22212 }
22213 *buf = xmlStrcat(*buf, BAD_CAST "]");
22214
22215 return (BAD_CAST *buf);
22216}
22217
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022218/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022219 * xmlSchemaXPathPop:
22220 * @vctxt: the WXS validation context
22221 *
22222 * Pops all XPath states.
22223 *
22224 * Returns 0 on success and -1 on internal errors.
22225 */
22226static int
22227xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22228{
22229 xmlSchemaIDCStateObjPtr sto;
22230 int res;
22231
22232 if (vctxt->xpathStates == NULL)
22233 return(0);
22234 sto = vctxt->xpathStates;
22235 do {
22236 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22237 if (res == -1)
22238 return (-1);
22239 sto = sto->next;
22240 } while (sto != NULL);
22241 return(0);
22242}
22243
22244/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022245 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022246 * @vctxt: the WXS validation context
22247 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022248 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022249 *
22250 * Processes and pops the history items of the IDC state objects.
22251 * IDC key-sequences are validated/created on IDC bindings.
22252 *
22253 * Returns 0 on success and -1 on internal errors.
22254 */
22255static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022256xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022257 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022258{
22259 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022260 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022261 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022262 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022263
22264 if (vctxt->xpathStates == NULL)
22265 return (0);
22266 sto = vctxt->xpathStates;
22267
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022268#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022269 {
22270 xmlChar *str = NULL;
22271 xmlGenericError(xmlGenericErrorContext,
22272 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022273 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22274 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022275 FREE_AND_NULL(str)
22276 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022277#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022278 /*
22279 * Evaluate the state objects.
22280 */
22281 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022282 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22283 if (res == -1) {
22284 VERROR_INT("xmlSchemaXPathProcessHistory",
22285 "calling xmlStreamPop()");
22286 return (-1);
22287 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022288#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022289 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22290 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022291#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022292 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022293 goto deregister_check;
22294
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022295 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022296
22297 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022298 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022299 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022300 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022301 sto = sto->next;
22302 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022303 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022304 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022305 /*
22306 * NOTE: According to
22307 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22308 * ... the simple-content of complex types is also allowed.
22309 */
22310
22311 if (WXS_IS_COMPLEX(type)) {
22312 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22313 /*
22314 * Sanity check for complex types with simple content.
22315 */
22316 simpleType = type->contentTypeDef;
22317 if (simpleType == NULL) {
22318 VERROR_INT("xmlSchemaXPathProcessHistory",
22319 "field resolves to a CT with simple content "
22320 "but the CT is missing the ST definition");
22321 return (-1);
22322 }
22323 } else
22324 simpleType = NULL;
22325 } else
22326 simpleType = type;
22327 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022328 xmlChar *str = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022329
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022330 /*
22331 * Not qualified if the field resolves to a node of non
22332 * simple type.
22333 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022334 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022335 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022336 WXS_BASIC_CAST sto->matcher->aidc->def,
22337 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022338 "non-simple type",
22339 sto->sel->xpath,
22340 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22341 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022342 sto->nbHistory--;
22343 goto deregister_check;
22344 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022345
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022346 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022347 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022348 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022349 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022350 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022351 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022352 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022353 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022354 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022355 sto->nbHistory--;
22356 goto deregister_check;
22357 } else {
22358 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22359 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022360 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022361
22362 /*
22363 * The key will be anchored on the matcher's list of
22364 * key-sequences. The position in this list is determined
22365 * by the target node's depth relative to the matcher's
22366 * depth of creation (i.e. the depth of the scope element).
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022367 *
22368 * Element Depth Pos List-entries
22369 * <scope> 0 NULL
22370 * <bar> 1 NULL
22371 * <target/> 2 2 target
22372 * <bar>
22373 * </scope>
22374 *
22375 * The size of the list is only dependant on the depth of
22376 * the tree.
22377 * An entry will be NULLed in selector_leave, i.e. when
22378 * we hit the target's
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022379 */
22380 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022381 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022382
22383 /*
22384 * Create/grow the array of key-sequences.
22385 */
22386 if (matcher->keySeqs == NULL) {
22387 if (pos > 9)
22388 matcher->sizeKeySeqs = pos * 2;
22389 else
22390 matcher->sizeKeySeqs = 10;
22391 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22392 xmlMalloc(matcher->sizeKeySeqs *
22393 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22394 if (matcher->keySeqs == NULL) {
22395 xmlSchemaVErrMemory(NULL,
22396 "allocating an array of key-sequences",
22397 NULL);
22398 return(-1);
22399 }
22400 memset(matcher->keySeqs, 0,
22401 matcher->sizeKeySeqs *
22402 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22403 } else if (pos >= matcher->sizeKeySeqs) {
22404 int i = matcher->sizeKeySeqs;
22405
22406 matcher->sizeKeySeqs *= 2;
22407 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22408 xmlRealloc(matcher->keySeqs,
22409 matcher->sizeKeySeqs *
22410 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022411 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022412 xmlSchemaVErrMemory(NULL,
22413 "reallocating an array of key-sequences",
22414 NULL);
22415 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022416 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022417 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022418 * The array needs to be NULLed.
22419 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022420 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022421 for (; i < matcher->sizeKeySeqs; i++)
22422 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022423 }
22424
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022425 /*
22426 * Get/create the key-sequence.
22427 */
22428 keySeq = matcher->keySeqs[pos];
22429 if (keySeq == NULL) {
22430 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022431 } else if (keySeq[idx] != NULL) {
22432 xmlChar *str = NULL;
22433 /*
22434 * cvc-identity-constraint:
22435 * 3 For each node in the ·target node set· all
22436 * of the {fields}, with that node as the context
22437 * node, evaluate to either an empty node-set or
22438 * a node-set with exactly one member, which must
22439 * have a simple type.
22440 *
22441 * The key was already set; report an error.
22442 */
22443 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22444 XML_SCHEMAV_CVC_IDC, NULL,
22445 WXS_BASIC_CAST matcher->aidc->def,
22446 "The XPath '%s' of a field of %s evaluates to a "
22447 "node-set with more than one member",
22448 sto->sel->xpath,
22449 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22450 FREE_AND_NULL(str);
22451 sto->nbHistory--;
22452 goto deregister_check;
22453 } else
22454 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022455
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022456create_sequence:
22457 /*
22458 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022459 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022460 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22461 matcher->aidc->def->nbFields *
22462 sizeof(xmlSchemaPSVIIDCKeyPtr));
22463 if (keySeq == NULL) {
22464 xmlSchemaVErrMemory(NULL,
22465 "allocating an IDC key-sequence", NULL);
22466 return(-1);
22467 }
22468 memset(keySeq, 0, matcher->aidc->def->nbFields *
22469 sizeof(xmlSchemaPSVIIDCKeyPtr));
22470 matcher->keySeqs[pos] = keySeq;
22471create_key:
22472 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022473 * Create a key once per node only.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022474 */
22475 if (key == NULL) {
22476 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22477 sizeof(xmlSchemaPSVIIDCKey));
22478 if (key == NULL) {
22479 xmlSchemaVErrMemory(NULL,
22480 "allocating a IDC key", NULL);
22481 xmlFree(keySeq);
22482 matcher->keySeqs[pos] = NULL;
22483 return(-1);
22484 }
22485 /*
22486 * Consume the compiled value.
22487 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022488 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022489 key->val = vctxt->inode->val;
22490 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022491 /*
22492 * Store the key in a global list.
22493 */
22494 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22495 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022496 return (-1);
22497 }
22498 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022499 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022500 }
22501 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022502
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022503 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022504 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022505 xmlSchemaPSVIIDCNodePtr ntItem;
22506 xmlSchemaIDCMatcherPtr matcher;
22507 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022508 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022509 int pos, i, j, nbKeys;
22510 /*
22511 * Here we have the following scenario:
22512 * An IDC 'selector' state object resolved to a target node,
22513 * during the time this target node was in the
22514 * ancestor-or-self axis, the 'field' state object(s) looked
22515 * out for matching nodes to create a key-sequence for this
22516 * target node. Now we are back to this target node and need
22517 * to put the key-sequence, together with the target node
22518 * itself, into the node-table of the corresponding IDC
22519 * binding.
22520 */
22521 matcher = sto->matcher;
22522 idc = matcher->aidc->def;
22523 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022524 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022525 /*
22526 * Check if the matcher has any key-sequences at all, plus
22527 * if it has a key-sequence for the current target node.
22528 */
22529 if ((matcher->keySeqs == NULL) ||
22530 (matcher->sizeKeySeqs <= pos)) {
22531 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22532 goto selector_key_error;
22533 else
22534 goto selector_leave;
22535 }
22536
22537 keySeq = &(matcher->keySeqs[pos]);
22538 if (*keySeq == NULL) {
22539 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22540 goto selector_key_error;
22541 else
22542 goto selector_leave;
22543 }
22544
22545 for (i = 0; i < nbKeys; i++) {
22546 if ((*keySeq)[i] == NULL) {
22547 /*
22548 * Not qualified, if not all fields did resolve.
22549 */
22550 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22551 /*
22552 * All fields of a "key" IDC must resolve.
22553 */
22554 goto selector_key_error;
22555 }
22556 goto selector_leave;
22557 }
22558 }
22559 /*
22560 * All fields did resolve.
22561 */
22562
22563 /*
22564 * 4.1 If the {identity-constraint category} is unique(/key),
22565 * then no two members of the ·qualified node set· have
22566 * ·key-sequences· whose members are pairwise equal, as
22567 * defined by Equal in [XML Schemas: Datatypes].
22568 *
22569 * Get the IDC binding from the matcher and check for
22570 * duplicate key-sequences.
22571 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022572#if 0
22573 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22574#endif
22575 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022576 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022577 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022578 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022579
22580 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022581 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022582 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022583 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022584 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022585 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022586 bkeySeq =
22587 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022588 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022589 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022590 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022591 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022592 if (res == -1) {
22593 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022594 } else if (res == 0) {
22595 /*
22596 * One of the keys differs, so the key-sequence
22597 * won't be equal; get out.
22598 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022599 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022600 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022601 }
22602 if (res == 1) {
22603 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022604 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022605 */
22606 break;
22607 }
22608 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022609 } while (i < targets->nbItems);
22610 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022611 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022612 /*
22613 * TODO: Try to report the key-sequence.
22614 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022615 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022616 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022617 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022618 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022619 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022620 (*keySeq), nbKeys),
22621 xmlSchemaGetIDCDesignation(&strB, idc));
22622 FREE_AND_NULL(str);
22623 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022624 goto selector_leave;
22625 }
22626 }
22627 /*
22628 * Add a node-table item to the IDC binding.
22629 */
22630 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22631 sizeof(xmlSchemaPSVIIDCNode));
22632 if (ntItem == NULL) {
22633 xmlSchemaVErrMemory(NULL,
22634 "allocating an IDC node-table item", NULL);
22635 xmlFree(*keySeq);
22636 *keySeq = NULL;
22637 return(-1);
22638 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022639 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022640
22641 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022642 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022643 */
22644 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22645 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22646 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022647 xmlFree(*keySeq);
22648 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022649 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022650 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022651 ntItem->nodeQNameID = -1;
22652 } else {
22653 /*
22654 * Save a cached QName for this node on the IDC node, to be
22655 * able to report it, even if the node is not saved.
22656 */
22657 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22658 vctxt->inode->localName, vctxt->inode->nsName);
22659 if (ntItem->nodeQNameID == -1) {
22660 xmlFree(ntItem);
22661 xmlFree(*keySeq);
22662 *keySeq = NULL;
22663 return (-1);
22664 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022665 }
22666 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022667 * Init the node-table item: Save the node, position and
22668 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022669 */
22670 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022671 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022672 ntItem->keys = *keySeq;
22673 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022674#if 0
22675 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22676#endif
22677 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022678 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22679 /*
22680 * Free the item, since keyref items won't be
22681 * put on a global list.
22682 */
22683 xmlFree(ntItem->keys);
22684 xmlFree(ntItem);
22685 }
22686 return (-1);
22687 }
22688
22689 goto selector_leave;
22690selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022691 {
22692 xmlChar *str = NULL;
22693 /*
22694 * 4.2.1 (KEY) The ·target node set· and the
22695 * ·qualified node set· are equal, that is, every
22696 * member of the ·target node set· is also a member
22697 * of the ·qualified node set· and vice versa.
22698 */
22699 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22700 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022701 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022702 "Not all fields of %s evaluate to a node",
22703 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22704 FREE_AND_NULL(str);
22705 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022706selector_leave:
22707 /*
22708 * Free the key-sequence if not added to the IDC table.
22709 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022710 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022711 xmlFree(*keySeq);
22712 *keySeq = NULL;
22713 }
22714 } /* if selector */
22715
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022716 sto->nbHistory--;
22717
22718deregister_check:
22719 /*
22720 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022721 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022722 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022723#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022724 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22725 sto->sel->xpath);
22726#endif
22727 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022728 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022729 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022730 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022731 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022732 nextsto = sto->next;
22733 /*
22734 * Unlink from the list of active XPath state objects.
22735 */
22736 vctxt->xpathStates = sto->next;
22737 sto->next = vctxt->xpathStatePool;
22738 /*
22739 * Link it to the pool of reusable state objects.
22740 */
22741 vctxt->xpathStatePool = sto;
22742 sto = nextsto;
22743 } else
22744 sto = sto->next;
22745 } /* while (sto != NULL) */
22746 return (0);
22747}
22748
22749/**
22750 * xmlSchemaIDCRegisterMatchers:
22751 * @vctxt: the WXS validation context
22752 * @elemDecl: the element declaration
22753 *
22754 * Creates helper objects to evaluate IDC selectors/fields
22755 * successively.
22756 *
22757 * Returns 0 if OK and -1 on internal errors.
22758 */
22759static int
22760xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22761 xmlSchemaElementPtr elemDecl)
22762{
22763 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22764 xmlSchemaIDCPtr idc, refIdc;
22765 xmlSchemaIDCAugPtr aidc;
22766
22767 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22768 if (idc == NULL)
22769 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022770
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022771#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022772 {
22773 xmlChar *str = NULL;
22774 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022775 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022776 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22777 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022778 FREE_AND_NULL(str)
22779 }
22780#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022781 if (vctxt->inode->idcMatchers != NULL) {
22782 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22783 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022784 return (-1);
22785 }
22786 do {
22787 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22788 /*
22789 * Since IDCs bubbles are expensive we need to know the
22790 * depth at which the bubbles should stop; this will be
22791 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022792 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022793 * be -1, indicating that no bubbles are needed.
22794 */
22795 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22796 if (refIdc != NULL) {
22797 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022798 * Remember that we have keyrefs on this node.
22799 */
22800 vctxt->inode->hasKeyrefs = 1;
22801 /*
22802 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022803 */
22804 aidc = vctxt->aidcs;
22805 while (aidc != NULL) {
22806 if (aidc->def == refIdc)
22807 break;
22808 aidc = aidc->next;
22809 }
22810 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022811 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022812 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022813 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022814 return (-1);
22815 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022816 if ((aidc->keyrefDepth == -1) ||
22817 (vctxt->depth < aidc->keyrefDepth))
22818 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022819 }
22820 }
22821 /*
22822 * Lookup the augmented IDC item for the IDC definition.
22823 */
22824 aidc = vctxt->aidcs;
22825 while (aidc != NULL) {
22826 if (aidc->def == idc)
22827 break;
22828 aidc = aidc->next;
22829 }
22830 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022831 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22832 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022833 return (-1);
22834 }
22835 /*
22836 * Create an IDC matcher for every IDC definition.
22837 */
22838 matcher = (xmlSchemaIDCMatcherPtr)
22839 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22840 if (matcher == NULL) {
22841 xmlSchemaVErrMemory(vctxt,
22842 "allocating an IDC matcher", NULL);
22843 return (-1);
22844 }
22845 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22846 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022847 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022848 else
22849 last->next = matcher;
22850 last = matcher;
22851
22852 matcher->type = IDC_MATCHER;
22853 matcher->depth = vctxt->depth;
22854 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022855 matcher->idcType = aidc->def->type;
22856#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022857 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22858#endif
22859 /*
22860 * Init the automaton state object.
22861 */
22862 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022863 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022864 return (-1);
22865
22866 idc = idc->next;
22867 } while (idc != NULL);
22868 return (0);
22869}
22870
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022871static int
22872xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22873 xmlSchemaNodeInfoPtr ielem)
22874{
22875 xmlSchemaPSVIIDCBindingPtr bind;
22876 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22877 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22878 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22879
22880 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22881 /* vctxt->createIDCNodeTables */
22882 while (matcher != NULL) {
22883 /*
22884 * Skip keyref IDCs and empty IDC target-lists.
22885 */
22886 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22887 WXS_ILIST_IS_EMPTY(matcher->targets))
22888 {
22889 matcher = matcher->next;
22890 continue;
22891 }
22892 /*
22893 * If we _want_ the IDC node-table to be created in any case
22894 * then do so. Otherwise create them only if keyrefs need them.
22895 */
22896 if ((! vctxt->createIDCNodeTables) &&
22897 ((matcher->aidc->keyrefDepth == -1) ||
22898 (matcher->aidc->keyrefDepth > vctxt->depth)))
22899 {
22900 matcher = matcher->next;
22901 continue;
22902 }
22903 /*
22904 * Get/create the IDC binding on this element for the IDC definition.
22905 */
22906 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22907
22908 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22909 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22910 nbDupls = bind->dupls->nbItems;
22911 } else {
22912 dupls = NULL;
22913 nbDupls = 0;
22914 }
22915 if (bind->nodeTable != NULL) {
22916 nbNodeTable = bind->nbNodes;
22917 } else {
22918 nbNodeTable = 0;
22919 }
22920
22921 if ((nbNodeTable == 0) && (nbDupls == 0)) {
22922 /*
22923 * Transfer all IDC target-nodes to the IDC node-table.
22924 */
22925 bind->nodeTable =
22926 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22927 bind->sizeNodes = matcher->targets->sizeItems;
22928 bind->nbNodes = matcher->targets->nbItems;
22929
22930 matcher->targets->items = NULL;
22931 matcher->targets->sizeItems = 0;
22932 matcher->targets->nbItems = 0;
22933 } else {
22934 /*
22935 * Compare the key-sequences and add to the IDC node-table.
22936 */
22937 nbTargets = matcher->targets->nbItems;
22938 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
22939 nbFields = matcher->aidc->def->nbFields;
22940 i = 0;
22941 do {
22942 keys = targets[i]->keys;
22943 if (nbDupls) {
22944 /*
22945 * Search in already found duplicates first.
22946 */
22947 j = 0;
22948 do {
22949 if (nbFields == 1) {
22950 res = xmlSchemaAreValuesEqual(keys[0]->val,
22951 dupls[j]->keys[0]->val);
22952 if (res == -1)
22953 goto internal_error;
22954 if (res == 1) {
22955 /*
22956 * Equal key-sequence.
22957 */
22958 goto next_target;
22959 }
22960 } else {
22961 res = 0;
22962 ntkeys = dupls[j]->keys;
22963 for (k = 0; k < nbFields; k++) {
22964 res = xmlSchemaAreValuesEqual(keys[k]->val,
22965 ntkeys[k]->val);
22966 if (res == -1)
22967 goto internal_error;
22968 if (res == 0) {
22969 /*
22970 * One of the keys differs.
22971 */
22972 break;
22973 }
22974 }
22975 if (res == 1) {
22976 /*
22977 * Equal key-sequence found.
22978 */
22979 goto next_target;
22980 }
22981 }
22982 j++;
22983 } while (j < nbDupls);
22984 }
22985 if (nbNodeTable) {
22986 j = 0;
22987 do {
22988 if (nbFields == 1) {
22989 res = xmlSchemaAreValuesEqual(keys[0]->val,
22990 bind->nodeTable[j]->keys[0]->val);
22991 if (res == -1)
22992 goto internal_error;
22993 if (res == 0) {
22994 /*
22995 * The key-sequence differs.
22996 */
22997 goto next_node_table_entry;
22998 }
22999 } else {
23000 res = 0;
23001 ntkeys = bind->nodeTable[j]->keys;
23002 for (k = 0; k < nbFields; k++) {
23003 res = xmlSchemaAreValuesEqual(keys[k]->val,
23004 ntkeys[k]->val);
23005 if (res == -1)
23006 goto internal_error;
23007 if (res == 0) {
23008 /*
23009 * One of the keys differs.
23010 */
23011 goto next_node_table_entry;
23012 }
23013 }
23014 }
23015 /*
23016 * Add the duplicate to the list of duplicates.
23017 */
23018 if (bind->dupls == NULL) {
23019 bind->dupls = xmlSchemaItemListCreate();
23020 if (bind->dupls == NULL)
23021 goto internal_error;
23022 }
23023 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23024 goto internal_error;
23025 /*
23026 * Remove the duplicate entry from the IDC node-table.
23027 */
23028 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23029 bind->nbNodes--;
23030
23031 goto next_target;
23032
23033next_node_table_entry:
23034 j++;
23035 } while (j < nbNodeTable);
23036 }
23037 /*
23038 * If everything is fine, then add the IDC target-node to
23039 * the IDC node-table.
23040 */
23041 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23042 goto internal_error;
23043
23044next_target:
23045 i++;
23046 } while (i < nbTargets);
23047 }
23048 matcher = matcher->next;
23049 }
23050 return(0);
23051
23052internal_error:
23053 return(-1);
23054}
23055
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023056/**
23057 * xmlSchemaBubbleIDCNodeTables:
23058 * @depth: the current tree depth
23059 *
23060 * Merges IDC bindings of an element at @depth into the corresponding IDC
23061 * bindings of its parent element. If a duplicate note-table entry is found,
23062 * both, the parent node-table entry and child entry are discarded from the
23063 * node-table of the parent.
23064 *
23065 * Returns 0 if OK and -1 on internal errors.
23066 */
23067static int
23068xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23069{
23070 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023071 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23072 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023073 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023074 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023075
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023076 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023077 if (bind == NULL) {
23078 /* Fine, no table, no bubbles. */
23079 return (0);
23080 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023081
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023082 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23083 /*
23084 * Walk all bindings; create new or add to existing bindings.
23085 * Remove duplicate key-sequences.
23086 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023087 while (bind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023088
23089 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23090 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023091 /*
23092 * Check if the key/unique IDC table needs to be bubbled.
23093 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023094 if (! vctxt->createIDCNodeTables) {
23095 aidc = vctxt->aidcs;
23096 do {
23097 if (aidc->def == bind->definition) {
23098 if ((aidc->keyrefDepth == -1) ||
23099 (aidc->keyrefDepth >= vctxt->depth)) {
23100 goto next_binding;
23101 }
23102 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023103 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023104 aidc = aidc->next;
23105 } while (aidc != NULL);
23106 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023107
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023108 if (parTable != NULL)
23109 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023110 /*
23111 * Search a matching parent binding for the
23112 * IDC definition.
23113 */
23114 while (parBind != NULL) {
23115 if (parBind->definition == bind->definition)
23116 break;
23117 parBind = parBind->next;
23118 }
23119
23120 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023121 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023122 * Compare every node-table entry of the child node,
23123 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023124 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023125 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023126
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023127 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23128 oldDupls = parBind->dupls->nbItems;
23129 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23130 } else {
23131 dupls = NULL;
23132 oldDupls = 0;
23133 }
23134
23135 parNodes = parBind->nodeTable;
23136 nbFields = bind->definition->nbFields;
23137
23138 for (i = 0; i < bind->nbNodes; i++) {
23139 node = bind->nodeTable[i];
23140 if (node == NULL)
23141 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023142 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023143 * ...with every key-sequence of the parent node, already
23144 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023145 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023146 if (oldDupls) {
23147 j = 0;
23148 while (j < oldDupls) {
23149 if (nbFields == 1) {
23150 ret = xmlSchemaAreValuesEqual(
23151 node->keys[0]->val,
23152 dupls[j]->keys[0]->val);
23153 if (ret == -1)
23154 goto internal_error;
23155 if (ret == 0) {
23156 j++;
23157 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023158 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023159 } else {
23160 parNode = dupls[j];
23161 for (k = 0; k < nbFields; k++) {
23162 ret = xmlSchemaAreValuesEqual(
23163 node->keys[k]->val,
23164 parNode->keys[k]->val);
23165 if (ret == -1)
23166 goto internal_error;
23167 if (ret == 0)
23168 break;
23169 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023170 }
23171 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023172 /* Duplicate found. */
23173 break;
23174 j++;
23175 }
23176 if (j != oldDupls) {
23177 /* Duplicate found. Skip this entry. */
23178 continue;
23179 }
23180 }
23181 /*
23182 * ... and with every key-sequence of the parent node.
23183 */
23184 if (oldNum) {
23185 j = 0;
23186 while (j < oldNum) {
23187 if (nbFields == 1) {
23188 ret = xmlSchemaAreValuesEqual(
23189 node->keys[0]->val,
23190 parNodes[j]->keys[0]->val);
23191 if (ret == -1)
23192 goto internal_error;
23193 if (ret == 0) {
23194 j++;
23195 continue;
23196 }
23197 } else {
23198 parNode = parNodes[j];
23199 for (k = 0; k < nbFields; k++) {
23200 ret = xmlSchemaAreValuesEqual(
23201 node->keys[k]->val,
23202 parNode->keys[k]->val);
23203 if (ret == -1)
23204 goto internal_error;
23205 if (ret == 0)
23206 break;
23207 }
23208 }
23209 if (ret == 1)
23210 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023211 break;
23212 j++;
23213 }
23214 if (j != oldNum) {
23215 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023216 * Handle duplicates. Move the duplicate in
23217 * the parent's node-table to the list of
23218 * duplicates.
23219 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023220 oldNum--;
23221 parBind->nbNodes--;
23222 /*
23223 * Move last old item to pos of duplicate.
23224 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023225 parNodes[j] = parNodes[oldNum];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023226
23227 if (parBind->nbNodes != oldNum) {
23228 /*
23229 * If new items exist, move last new item to
23230 * last of old items.
23231 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023232 parNodes[oldNum] =
23233 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023234 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023235 if (parBind->dupls == NULL) {
23236 parBind->dupls = xmlSchemaItemListCreate();
23237 if (parBind->dupls == NULL)
23238 goto internal_error;
23239 }
23240 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023241 } else {
23242 /*
23243 * Add the node-table entry (node and key-sequence) of
23244 * the child node to the node table of the parent node.
23245 */
23246 if (parBind->nodeTable == NULL) {
23247 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023248 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023249 if (parBind->nodeTable == NULL) {
23250 xmlSchemaVErrMemory(NULL,
23251 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023252 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023253 }
23254 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023255 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023256 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023257 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23258 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23259 sizeof(xmlSchemaPSVIIDCNodePtr));
23260 if (parBind->nodeTable == NULL) {
23261 xmlSchemaVErrMemory(NULL,
23262 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023263 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023264 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023265 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023266 /*
23267 * Append the new node-table entry to the 'new node-table
23268 * entries' section.
23269 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023270 parBind->nodeTable[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023271 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023272
23273 }
23274
23275 }
23276 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023277 /*
23278 * No binding for the IDC was found: create a new one and
23279 * copy all node-tables.
23280 */
23281 parBind = xmlSchemaIDCNewBinding(bind->definition);
23282 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023283 goto internal_error;
23284
23285 /*
23286 * TODO: Hmm, how to optimize the initial number of
23287 * allocated entries?
23288 */
23289 if (bind->nbNodes != 0) {
23290 /*
23291 * Add all IDC node-table entries.
23292 */
23293 if (! vctxt->psviExposeIDCNodeTables) {
23294 /*
23295 * Just move the entries.
23296 * NOTE: this is quite save here, since
23297 * all the keyref lookups have already been
23298 * performed.
23299 */
23300 parBind->nodeTable = bind->nodeTable;
23301 bind->nodeTable = NULL;
23302 parBind->sizeNodes = bind->sizeNodes;
23303 bind->sizeNodes = 0;
23304 parBind->nbNodes = bind->nbNodes;
23305 bind->nbNodes = 0;
23306 } else {
23307 /*
23308 * Copy the entries.
23309 */
23310 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23311 xmlMalloc(bind->nbNodes *
23312 sizeof(xmlSchemaPSVIIDCNodePtr));
23313 if (parBind->nodeTable == NULL) {
23314 xmlSchemaVErrMemory(NULL,
23315 "allocating an array of IDC node-table "
23316 "items", NULL);
23317 xmlSchemaIDCFreeBinding(parBind);
23318 goto internal_error;
23319 }
23320 parBind->sizeNodes = bind->nbNodes;
23321 parBind->nbNodes = bind->nbNodes;
23322 memcpy(parBind->nodeTable, bind->nodeTable,
23323 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23324 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023325 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023326 if (bind->dupls) {
23327 /*
23328 * Move the duplicates.
23329 */
23330 if (parBind->dupls != NULL)
23331 xmlSchemaItemListFree(parBind->dupls);
23332 parBind->dupls = bind->dupls;
23333 bind->dupls = NULL;
23334 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023335 if (*parTable == NULL)
23336 *parTable = parBind;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023337 else {
23338 parBind->next = *parTable;
23339 *parTable = parBind;
23340 }
23341 }
23342
23343next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023344 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023345 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023346 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023347
23348internal_error:
23349 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023350}
23351
23352/**
23353 * xmlSchemaCheckCVCIDCKeyRef:
23354 * @vctxt: the WXS validation context
23355 * @elemDecl: the element declaration
23356 *
23357 * Check the cvc-idc-keyref constraints.
23358 */
23359static int
23360xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23361{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023362 xmlSchemaIDCMatcherPtr matcher;
23363 xmlSchemaPSVIIDCBindingPtr bind;
23364
23365 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023366 /*
23367 * Find a keyref.
23368 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023369 while (matcher != NULL) {
23370 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23371 matcher->targets &&
23372 matcher->targets->nbItems)
23373 {
23374 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023375 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023376 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023377
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023378 nbFields = matcher->aidc->def->nbFields;
23379
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023380 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023381 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023383 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023384 while (bind != NULL) {
23385 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023386 bind->definition)
23387 break;
23388 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023389 }
23390 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023391 /*
23392 * Search for a matching key-sequences.
23393 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023394 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023395 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023396 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023397 if (bind != NULL) {
23398 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023399 for (j = 0; j < bind->nbNodes; j++) {
23400 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023401 for (k = 0; k < nbFields; k++) {
23402 res = xmlSchemaAreValuesEqual(keys[k]->val,
23403 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023404 if (res == 0)
23405 break;
23406 else if (res == -1) {
23407 return (-1);
23408 }
23409 }
23410 if (res == 1) {
23411 /*
23412 * Match found.
23413 */
23414 break;
23415 }
23416 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023417 if ((res == 0) && hasDupls) {
23418 /*
23419 * Search in duplicates
23420 */
23421 for (j = 0; j < bind->dupls->nbItems; j++) {
23422 keys = ((xmlSchemaPSVIIDCNodePtr)
23423 bind->dupls->items[j])->keys;
23424 for (k = 0; k < nbFields; k++) {
23425 res = xmlSchemaAreValuesEqual(keys[k]->val,
23426 refKeys[k]->val);
23427 if (res == 0)
23428 break;
23429 else if (res == -1) {
23430 return (-1);
23431 }
23432 }
23433 if (res == 1) {
23434 /*
23435 * Match in duplicates found.
23436 */
23437 xmlChar *str = NULL, *strB = NULL;
23438 xmlSchemaKeyrefErr(vctxt,
23439 XML_SCHEMAV_CVC_IDC, refNode,
23440 (xmlSchemaTypePtr) matcher->aidc->def,
23441 "More than one match found for "
23442 "key-sequence %s of keyref '%s'",
23443 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23444 refNode->keys, nbFields),
23445 xmlSchemaGetComponentQName(&strB,
23446 matcher->aidc->def));
23447 FREE_AND_NULL(str);
23448 FREE_AND_NULL(strB);
23449 break;
23450 }
23451 }
23452 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023453 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023454
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023455 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023456 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023457 xmlSchemaKeyrefErr(vctxt,
23458 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023459 (xmlSchemaTypePtr) matcher->aidc->def,
23460 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023461 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023462 refNode->keys, nbFields),
23463 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023464 FREE_AND_NULL(str);
23465 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023466 }
23467 }
23468 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023469 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023470 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023471 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023472 return (0);
23473}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023474
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023475/************************************************************************
23476 * *
23477 * XML Reader validation code *
23478 * *
23479 ************************************************************************/
23480
23481static xmlSchemaAttrInfoPtr
23482xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023484 xmlSchemaAttrInfoPtr iattr;
23485 /*
23486 * Grow/create list of attribute infos.
23487 */
23488 if (vctxt->attrInfos == NULL) {
23489 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23490 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23491 vctxt->sizeAttrInfos = 1;
23492 if (vctxt->attrInfos == NULL) {
23493 xmlSchemaVErrMemory(vctxt,
23494 "allocating attribute info list", NULL);
23495 return (NULL);
23496 }
23497 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23498 vctxt->sizeAttrInfos++;
23499 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23500 xmlRealloc(vctxt->attrInfos,
23501 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23502 if (vctxt->attrInfos == NULL) {
23503 xmlSchemaVErrMemory(vctxt,
23504 "re-allocating attribute info list", NULL);
23505 return (NULL);
23506 }
23507 } else {
23508 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23509 if (iattr->localName != NULL) {
23510 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23511 "attr info not cleared");
23512 return (NULL);
23513 }
23514 iattr->nodeType = XML_ATTRIBUTE_NODE;
23515 return (iattr);
23516 }
23517 /*
23518 * Create an attribute info.
23519 */
23520 iattr = (xmlSchemaAttrInfoPtr)
23521 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23522 if (iattr == NULL) {
23523 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23524 return (NULL);
23525 }
23526 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23527 iattr->nodeType = XML_ATTRIBUTE_NODE;
23528 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23529
23530 return (iattr);
23531}
23532
23533static int
23534xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23535 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023536 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023537 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023538 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023539 int ownedNames,
23540 xmlChar *value,
23541 int ownedValue)
23542{
23543 xmlSchemaAttrInfoPtr attr;
23544
23545 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23546 if (attr == NULL) {
23547 VERROR_INT("xmlSchemaPushAttribute",
23548 "calling xmlSchemaGetFreshAttrInfo()");
23549 return (-1);
23550 }
23551 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023552 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023553 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23554 attr->localName = localName;
23555 attr->nsName = nsName;
23556 if (ownedNames)
23557 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23558 /*
23559 * Evaluate if it's an XSI attribute.
23560 */
23561 if (nsName != NULL) {
23562 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23563 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23564 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23565 }
23566 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23567 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23568 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23569 }
23570 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23571 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23572 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23573 }
23574 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23575 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23576 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23577 }
23578 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23579 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23580 }
23581 }
23582 attr->value = value;
23583 if (ownedValue)
23584 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23585 if (attr->metaType != 0)
23586 attr->state = XML_SCHEMAS_ATTR_META;
23587 return (0);
23588}
23589
23590static void
23591xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23592{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023593 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000023594 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23596 FREE_AND_NULL(ielem->localName);
23597 FREE_AND_NULL(ielem->nsName);
23598 } else {
23599 ielem->localName = NULL;
23600 ielem->nsName = NULL;
23601 }
23602 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23603 FREE_AND_NULL(ielem->value);
23604 } else {
23605 ielem->value = NULL;
23606 }
23607 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023608 /*
23609 * PSVI TODO: Be careful not to free it when the value is
23610 * exposed via PSVI.
23611 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023612 xmlSchemaFreeValue(ielem->val);
23613 ielem->val = NULL;
23614 }
23615 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023616 /*
23617 * URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23618 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023619 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23620 ielem->idcMatchers = NULL;
23621 }
23622 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023623 /*
23624 * OPTIMIZE TODO: Use a pool of IDC tables??.
23625 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023626 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23627 ielem->idcTable = NULL;
23628 }
23629 if (ielem->regexCtxt != NULL) {
23630 xmlRegFreeExecCtxt(ielem->regexCtxt);
23631 ielem->regexCtxt = NULL;
23632 }
23633 if (ielem->nsBindings != NULL) {
23634 xmlFree((xmlChar **)ielem->nsBindings);
23635 ielem->nsBindings = NULL;
23636 ielem->nbNsBindings = 0;
23637 ielem->sizeNsBindings = 0;
23638 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023639}
23640
23641/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023642 * xmlSchemaGetFreshElemInfo:
23643 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023644 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023645 * Creates/reuses and initializes the element info item for
23646 * the currect tree depth.
23647 *
23648 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023649 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023650static xmlSchemaNodeInfoPtr
23651xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023652{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023653 xmlSchemaNodeInfoPtr info = NULL;
23654
23655 if (vctxt->depth > vctxt->sizeElemInfos) {
23656 VERROR_INT("xmlSchemaGetFreshElemInfo",
23657 "inconsistent depth encountered");
23658 return (NULL);
23659 }
23660 if (vctxt->elemInfos == NULL) {
23661 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23662 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23663 if (vctxt->elemInfos == NULL) {
23664 xmlSchemaVErrMemory(vctxt,
23665 "allocating the element info array", NULL);
23666 return (NULL);
23667 }
23668 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23669 vctxt->sizeElemInfos = 10;
23670 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23671 int i = vctxt->sizeElemInfos;
23672
23673 vctxt->sizeElemInfos *= 2;
23674 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23675 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23676 sizeof(xmlSchemaNodeInfoPtr));
23677 if (vctxt->elemInfos == NULL) {
23678 xmlSchemaVErrMemory(vctxt,
23679 "re-allocating the element info array", NULL);
23680 return (NULL);
23681 }
23682 /*
23683 * We need the new memory to be NULLed.
23684 * TODO: Use memset instead?
23685 */
23686 for (; i < vctxt->sizeElemInfos; i++)
23687 vctxt->elemInfos[i] = NULL;
23688 } else
23689 info = vctxt->elemInfos[vctxt->depth];
23690
23691 if (info == NULL) {
23692 info = (xmlSchemaNodeInfoPtr)
23693 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23694 if (info == NULL) {
23695 xmlSchemaVErrMemory(vctxt,
23696 "allocating an element info", NULL);
23697 return (NULL);
23698 }
23699 vctxt->elemInfos[vctxt->depth] = info;
23700 } else {
23701 if (info->localName != NULL) {
23702 VERROR_INT("xmlSchemaGetFreshElemInfo",
23703 "elem info has not been cleared");
23704 return (NULL);
23705 }
23706 }
23707 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23708 info->nodeType = XML_ELEMENT_NODE;
23709 info->depth = vctxt->depth;
23710
23711 return (info);
23712}
23713
23714#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23715#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23716#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23717
23718static int
23719xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23720 xmlNodePtr node,
23721 xmlSchemaTypePtr type,
23722 xmlSchemaValType valType,
23723 const xmlChar * value,
23724 xmlSchemaValPtr val,
23725 unsigned long length,
23726 int fireErrors)
23727{
23728 int ret, error = 0;
23729
23730 xmlSchemaTypePtr tmpType;
23731 xmlSchemaFacetLinkPtr facetLink;
23732 xmlSchemaFacetPtr facet;
23733 unsigned long len = 0;
23734 xmlSchemaWhitespaceValueType ws;
23735
23736 /*
23737 * In Libxml2, derived built-in types have currently no explicit facets.
23738 */
23739 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023740 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023741
23742 /*
23743 * NOTE: Do not jump away, if the facetSet of the given type is
23744 * empty: until now, "pattern" and "enumeration" facets of the
23745 * *base types* need to be checked as well.
23746 */
23747 if (type->facetSet == NULL)
23748 goto pattern_and_enum;
23749
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023750 if (! WXS_IS_ATOMIC(type)) {
23751 if (WXS_IS_LIST(type))
23752 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023753 else
23754 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023755 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023756 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023757 * Whitespace handling is only of importance for string-based
23758 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023759 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023760 tmpType = xmlSchemaGetPrimitiveType(type);
23761 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023762 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023763 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23764 } else
23765 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23766 /*
23767 * If the value was not computed (for string or
23768 * anySimpleType based types), then use the provided
23769 * type.
23770 */
23771 if (val == NULL)
23772 valType = valType;
23773 else
23774 valType = xmlSchemaGetValType(val);
23775
23776 ret = 0;
23777 for (facetLink = type->facetSet; facetLink != NULL;
23778 facetLink = facetLink->next) {
23779 /*
23780 * Skip the pattern "whiteSpace": it is used to
23781 * format the character content beforehand.
23782 */
23783 switch (facetLink->facet->type) {
23784 case XML_SCHEMA_FACET_WHITESPACE:
23785 case XML_SCHEMA_FACET_PATTERN:
23786 case XML_SCHEMA_FACET_ENUMERATION:
23787 continue;
23788 case XML_SCHEMA_FACET_LENGTH:
23789 case XML_SCHEMA_FACET_MINLENGTH:
23790 case XML_SCHEMA_FACET_MAXLENGTH:
23791 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23792 valType, value, val, &len, ws);
23793 break;
23794 default:
23795 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23796 valType, value, val, ws);
23797 break;
23798 }
23799 if (ret < 0) {
23800 AERROR_INT("xmlSchemaValidateFacets",
23801 "validating against a atomic type facet");
23802 return (-1);
23803 } else if (ret > 0) {
23804 if (fireErrors)
23805 xmlSchemaFacetErr(actxt, ret, node,
23806 value, len, type, facetLink->facet, NULL, NULL, NULL);
23807 else
23808 return (ret);
23809 if (error == 0)
23810 error = ret;
23811 }
23812 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023813 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023814
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023815WXS_IS_LIST:
23816 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023817 goto pattern_and_enum;
23818 /*
23819 * "length", "minLength" and "maxLength" of list types.
23820 */
23821 ret = 0;
23822 for (facetLink = type->facetSet; facetLink != NULL;
23823 facetLink = facetLink->next) {
23824
23825 switch (facetLink->facet->type) {
23826 case XML_SCHEMA_FACET_LENGTH:
23827 case XML_SCHEMA_FACET_MINLENGTH:
23828 case XML_SCHEMA_FACET_MAXLENGTH:
23829 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23830 value, length, NULL);
23831 break;
23832 default:
23833 continue;
23834 }
23835 if (ret < 0) {
23836 AERROR_INT("xmlSchemaValidateFacets",
23837 "validating against a list type facet");
23838 return (-1);
23839 } else if (ret > 0) {
23840 if (fireErrors)
23841 xmlSchemaFacetErr(actxt, ret, node,
23842 value, length, type, facetLink->facet, NULL, NULL, NULL);
23843 else
23844 return (ret);
23845 if (error == 0)
23846 error = ret;
23847 }
23848 ret = 0;
23849 }
23850
23851pattern_and_enum:
23852 if (error >= 0) {
23853 int found = 0;
23854 /*
23855 * Process enumerations. Facet values are in the value space
23856 * of the defining type's base type. This seems to be a bug in the
23857 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23858 * Only the first set of enumerations in the ancestor-or-self axis
23859 * is used for validation.
23860 */
23861 ret = 0;
23862 tmpType = type;
23863 do {
23864 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23865 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23866 continue;
23867 found = 1;
23868 ret = xmlSchemaAreValuesEqual(facet->val, val);
23869 if (ret == 1)
23870 break;
23871 else if (ret < 0) {
23872 AERROR_INT("xmlSchemaValidateFacets",
23873 "validating against an enumeration facet");
23874 return (-1);
23875 }
23876 }
23877 if (ret != 0)
23878 break;
23879 tmpType = tmpType->baseType;
23880 } while ((tmpType != NULL) &&
23881 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23882 if (found && (ret == 0)) {
23883 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23884 if (fireErrors) {
23885 xmlSchemaFacetErr(actxt, ret, node,
23886 value, 0, type, NULL, NULL, NULL, NULL);
23887 } else
23888 return (ret);
23889 if (error == 0)
23890 error = ret;
23891 }
23892 }
23893
23894 if (error >= 0) {
23895 int found;
23896 /*
23897 * Process patters. Pattern facets are ORed at type level
23898 * and ANDed if derived. Walk the base type axis.
23899 */
23900 tmpType = type;
23901 facet = NULL;
23902 do {
23903 found = 0;
23904 for (facetLink = tmpType->facetSet; facetLink != NULL;
23905 facetLink = facetLink->next) {
23906 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23907 continue;
23908 found = 1;
23909 /*
23910 * NOTE that for patterns, @value needs to be the
23911 * normalized vaule.
23912 */
23913 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23914 if (ret == 1)
23915 break;
23916 else if (ret < 0) {
23917 AERROR_INT("xmlSchemaValidateFacets",
23918 "validating against a pattern facet");
23919 return (-1);
23920 } else {
23921 /*
23922 * Save the last non-validating facet.
23923 */
23924 facet = facetLink->facet;
23925 }
23926 }
23927 if (found && (ret != 1)) {
23928 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23929 if (fireErrors) {
23930 xmlSchemaFacetErr(actxt, ret, node,
23931 value, 0, type, facet, NULL, NULL, NULL);
23932 } else
23933 return (ret);
23934 if (error == 0)
23935 error = ret;
23936 break;
23937 }
23938 tmpType = tmpType->baseType;
23939 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23940 }
23941
23942 return (error);
23943}
23944
23945static xmlChar *
23946xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23947 const xmlChar *value)
23948{
23949 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23950 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23951 return (xmlSchemaCollapseString(value));
23952 case XML_SCHEMA_WHITESPACE_REPLACE:
23953 return (xmlSchemaWhiteSpaceReplace(value));
23954 default:
23955 return (NULL);
23956 }
23957}
23958
23959static int
23960xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23961 const xmlChar *value,
23962 xmlSchemaValPtr *val,
23963 int valNeeded)
23964{
23965 int ret;
23966 const xmlChar *nsName;
23967 xmlChar *local, *prefix = NULL;
23968
23969 ret = xmlValidateQName(value, 1);
23970 if (ret != 0) {
23971 if (ret == -1) {
23972 VERROR_INT("xmlSchemaValidateQName",
23973 "calling xmlValidateQName()");
23974 return (-1);
23975 }
23976 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23977 }
23978 /*
23979 * NOTE: xmlSplitQName2 will always return a duplicated
23980 * strings.
23981 */
23982 local = xmlSplitQName2(value, &prefix);
23983 if (local == NULL)
23984 local = xmlStrdup(value);
23985 /*
23986 * OPTIMIZE TODO: Use flags for:
23987 * - is there any namespace binding?
23988 * - is there a default namespace?
23989 */
23990 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23991
23992 if (prefix != NULL) {
23993 xmlFree(prefix);
23994 /*
23995 * A namespace must be found if the prefix is
23996 * NOT NULL.
23997 */
23998 if (nsName == NULL) {
23999 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024000 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024001 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024002 "The QName value '%s' has no "
24003 "corresponding namespace declaration in "
24004 "scope", value, NULL);
24005 if (local != NULL)
24006 xmlFree(local);
24007 return (ret);
24008 }
24009 }
24010 if (valNeeded && val) {
24011 if (nsName != NULL)
24012 *val = xmlSchemaNewQNameValue(
24013 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24014 else
24015 *val = xmlSchemaNewQNameValue(NULL,
24016 BAD_CAST local);
24017 } else
24018 xmlFree(local);
24019 return (0);
24020}
24021
24022/*
24023* cvc-simple-type
24024*/
24025static int
24026xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24027 xmlNodePtr node,
24028 xmlSchemaTypePtr type,
24029 const xmlChar *value,
24030 xmlSchemaValPtr *retVal,
24031 int fireErrors,
24032 int normalize,
24033 int isNormalized)
24034{
24035 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24036 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024037 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024038 xmlChar *normValue = NULL;
24039
24040#define NORMALIZE(atype) \
24041 if ((! isNormalized) && \
24042 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24043 normValue = xmlSchemaNormalizeValue(atype, value); \
24044 if (normValue != NULL) \
24045 value = normValue; \
24046 isNormalized = 1; \
24047 }
24048
24049 if ((retVal != NULL) && (*retVal != NULL)) {
24050 xmlSchemaFreeValue(*retVal);
24051 *retVal = NULL;
24052 }
24053 /*
24054 * 3.14.4 Simple Type Definition Validation Rules
24055 * Validation Rule: String Valid
24056 */
24057 /*
24058 * 1 It is schema-valid with respect to that definition as defined
24059 * by Datatype Valid in [XML Schemas: Datatypes].
24060 */
24061 /*
24062 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24063 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
24064 * the string must be a ·declared entity name·.
24065 */
24066 /*
24067 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24068 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
24069 * then every whitespace-delimited substring of the string must be a ·declared
24070 * entity name·.
24071 */
24072 /*
24073 * 2.3 otherwise no further condition applies.
24074 */
24075 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24076 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024077 if (value == NULL)
24078 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024079 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024080 xmlSchemaTypePtr biType; /* The built-in type. */
24081 /*
24082 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
24083 * a literal in the ·lexical space· of {base type definition}"
24084 */
24085 /*
24086 * Whitespace-normalize.
24087 */
24088 NORMALIZE(type);
24089 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24090 /*
24091 * Get the built-in type.
24092 */
24093 biType = type->baseType;
24094 while ((biType != NULL) &&
24095 (biType->type != XML_SCHEMA_TYPE_BASIC))
24096 biType = biType->baseType;
24097
24098 if (biType == NULL) {
24099 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24100 "could not get the built-in type");
24101 goto internal_error;
24102 }
24103 } else
24104 biType = type;
24105 /*
24106 * NOTATIONs need to be processed here, since they need
24107 * to lookup in the hashtable of NOTATION declarations of the schema.
24108 */
24109 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24110 switch (biType->builtInType) {
24111 case XML_SCHEMAS_NOTATION:
24112 ret = xmlSchemaValidateNotation(
24113 (xmlSchemaValidCtxtPtr) actxt,
24114 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24115 NULL, value, &val, valNeeded);
24116 break;
24117 case XML_SCHEMAS_QNAME:
24118 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24119 value, &val, valNeeded);
24120 break;
24121 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024122 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024123 if (valNeeded)
24124 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24125 value, &val, NULL);
24126 else
24127 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24128 value, NULL, NULL);
24129 break;
24130 }
24131 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24132 switch (biType->builtInType) {
24133 case XML_SCHEMAS_NOTATION:
24134 ret = xmlSchemaValidateNotation(NULL,
24135 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24136 value, &val, valNeeded);
24137 break;
24138 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024139 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024140 if (valNeeded)
24141 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24142 value, &val, node);
24143 else
24144 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24145 value, NULL, node);
24146 break;
24147 }
24148 } else {
24149 /*
24150 * Validation via a public API is not implemented yet.
24151 */
24152 TODO
24153 goto internal_error;
24154 }
24155 if (ret != 0) {
24156 if (ret < 0) {
24157 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24158 "validating against a built-in type");
24159 goto internal_error;
24160 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024161 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024162 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24163 else
24164 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24165 }
24166 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24167 /*
24168 * Check facets.
24169 */
24170 ret = xmlSchemaValidateFacets(actxt, node, type,
24171 (xmlSchemaValType) biType->builtInType, value, val,
24172 0, fireErrors);
24173 if (ret != 0) {
24174 if (ret < 0) {
24175 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24176 "validating facets of atomic simple type");
24177 goto internal_error;
24178 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024179 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024180 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24181 else
24182 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24183 }
24184 }
24185 if (fireErrors && (ret > 0))
24186 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024187 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024188
24189 xmlSchemaTypePtr itemType;
24190 const xmlChar *cur, *end;
24191 xmlChar *tmpValue = NULL;
24192 unsigned long len = 0;
24193 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24194 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
24195 * of white space separated tokens, each of which ·match·es a literal
24196 * in the ·lexical space· of {item type definition}
24197 */
24198 /*
24199 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24200 * the list type has an enum or pattern facet.
24201 */
24202 NORMALIZE(type);
24203 /*
24204 * VAL TODO: Optimize validation of empty values.
24205 * VAL TODO: We do not have computed values for lists.
24206 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024207 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024208 cur = value;
24209 do {
24210 while (IS_BLANK_CH(*cur))
24211 cur++;
24212 end = cur;
24213 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24214 end++;
24215 if (end == cur)
24216 break;
24217 tmpValue = xmlStrndup(cur, end - cur);
24218 len++;
24219
24220 if (valNeeded)
24221 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24222 tmpValue, &curVal, fireErrors, 0, 1);
24223 else
24224 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24225 tmpValue, NULL, fireErrors, 0, 1);
24226 FREE_AND_NULL(tmpValue);
24227 if (curVal != NULL) {
24228 /*
24229 * Add to list of computed values.
24230 */
24231 if (val == NULL)
24232 val = curVal;
24233 else
24234 xmlSchemaValueAppend(prevVal, curVal);
24235 prevVal = curVal;
24236 curVal = NULL;
24237 }
24238 if (ret != 0) {
24239 if (ret < 0) {
24240 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24241 "validating an item of list simple type");
24242 goto internal_error;
24243 }
24244 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24245 break;
24246 }
24247 cur = end;
24248 } while (*cur != 0);
24249 FREE_AND_NULL(tmpValue);
24250 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24251 /*
24252 * Apply facets (pattern, enumeration).
24253 */
24254 ret = xmlSchemaValidateFacets(actxt, node, type,
24255 XML_SCHEMAS_UNKNOWN, value, val,
24256 len, fireErrors);
24257 if (ret != 0) {
24258 if (ret < 0) {
24259 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24260 "validating facets of list simple type");
24261 goto internal_error;
24262 }
24263 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24264 }
24265 }
24266 if (fireErrors && (ret > 0)) {
24267 /*
24268 * Report the normalized value.
24269 */
24270 normalize = 1;
24271 NORMALIZE(type);
24272 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24273 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024274 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024275 xmlSchemaTypeLinkPtr memberLink;
24276 /*
24277 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
24278 * not apply directly; however, the normalization behavior of ·union·
24279 * types is controlled by the value of whiteSpace on that one of the
24280 * ·memberTypes· against which the ·union· is successfully validated.
24281 *
24282 * This means that the value is normalized by the first validating
24283 * member type, then the facets of the union type are applied. This
24284 * needs changing of the value!
24285 */
24286
24287 /*
24288 * 1.2.3 if {variety} is ·union· then the string must ·match· a
24289 * literal in the ·lexical space· of at least one member of
24290 * {member type definitions}
24291 */
24292 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24293 if (memberLink == NULL) {
24294 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24295 "union simple type has no member types");
24296 goto internal_error;
24297 }
24298 /*
24299 * Always normalize union type values, since we currently
24300 * cannot store the whitespace information with the value
24301 * itself; otherwise a later value-comparison would be
24302 * not possible.
24303 */
24304 while (memberLink != NULL) {
24305 if (valNeeded)
24306 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24307 memberLink->type, value, &val, 0, 1, 0);
24308 else
24309 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24310 memberLink->type, value, NULL, 0, 1, 0);
24311 if (ret <= 0)
24312 break;
24313 memberLink = memberLink->next;
24314 }
24315 if (ret != 0) {
24316 if (ret < 0) {
24317 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24318 "validating members of union simple type");
24319 goto internal_error;
24320 }
24321 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24322 }
24323 /*
24324 * Apply facets (pattern, enumeration).
24325 */
24326 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24327 /*
24328 * The normalization behavior of ·union· types is controlled by
24329 * the value of whiteSpace on that one of the ·memberTypes·
24330 * against which the ·union· is successfully validated.
24331 */
24332 NORMALIZE(memberLink->type);
24333 ret = xmlSchemaValidateFacets(actxt, node, type,
24334 XML_SCHEMAS_UNKNOWN, value, val,
24335 0, fireErrors);
24336 if (ret != 0) {
24337 if (ret < 0) {
24338 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24339 "validating facets of union simple type");
24340 goto internal_error;
24341 }
24342 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24343 }
24344 }
24345 if (fireErrors && (ret > 0))
24346 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24347 }
24348
24349 if (normValue != NULL)
24350 xmlFree(normValue);
24351 if (ret == 0) {
24352 if (retVal != NULL)
24353 *retVal = val;
24354 else if (val != NULL)
24355 xmlSchemaFreeValue(val);
24356 } else if (val != NULL)
24357 xmlSchemaFreeValue(val);
24358 return (ret);
24359internal_error:
24360 if (normValue != NULL)
24361 xmlFree(normValue);
24362 if (val != NULL)
24363 xmlSchemaFreeValue(val);
24364 return (-1);
24365}
24366
24367static int
24368xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24369 const xmlChar *value,
24370 const xmlChar **nsName,
24371 const xmlChar **localName)
24372{
24373 int ret = 0;
24374
24375 if ((nsName == NULL) || (localName == NULL))
24376 return (-1);
24377 *nsName = NULL;
24378 *localName = NULL;
24379
24380 ret = xmlValidateQName(value, 1);
24381 if (ret == -1)
24382 return (-1);
24383 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024384 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024385 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24386 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24387 return (1);
24388 }
24389 {
24390 xmlChar *local = NULL;
24391 xmlChar *prefix;
24392
24393 /*
24394 * NOTE: xmlSplitQName2 will return a duplicated
24395 * string.
24396 */
24397 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024398 if (local == NULL)
24399 *localName = xmlDictLookup(vctxt->dict, value, -1);
24400 else {
24401 *localName = xmlDictLookup(vctxt->dict, local, -1);
24402 xmlFree(local);
24403 }
24404
24405 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24406
24407 if (prefix != NULL) {
24408 xmlFree(prefix);
24409 /*
24410 * A namespace must be found if the prefix is NOT NULL.
24411 */
24412 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024413 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024414 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024415 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024416 "The QName value '%s' has no "
24417 "corresponding namespace declaration in scope",
24418 value, NULL);
24419 return (2);
24420 }
24421 }
24422 }
24423 return (0);
24424}
24425
24426static int
24427xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24428 xmlSchemaAttrInfoPtr iattr,
24429 xmlSchemaTypePtr *localType,
24430 xmlSchemaElementPtr elemDecl)
24431{
24432 int ret = 0;
24433 /*
24434 * cvc-elt (3.3.4) : (4)
24435 * AND
24436 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24437 * (1.2.1.2.1) - (1.2.1.2.4)
24438 * Handle 'xsi:type'.
24439 */
24440 if (localType == NULL)
24441 return (-1);
24442 *localType = NULL;
24443 if (iattr == NULL)
24444 return (0);
24445 else {
24446 const xmlChar *nsName = NULL, *local = NULL;
24447 /*
24448 * TODO: We should report a *warning* that the type was overriden
24449 * by the instance.
24450 */
24451 ACTIVATE_ATTRIBUTE(iattr);
24452 /*
24453 * (cvc-elt) (3.3.4) : (4.1)
24454 * (cvc-assess-elt) (1.2.1.2.2)
24455 */
24456 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24457 &nsName, &local);
24458 if (ret != 0) {
24459 if (ret < 0) {
24460 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24461 "calling xmlSchemaQNameExpand() to validate the "
24462 "attribute 'xsi:type'");
24463 goto internal_error;
24464 }
24465 goto exit;
24466 }
24467 /*
24468 * (cvc-elt) (3.3.4) : (4.2)
24469 * (cvc-assess-elt) (1.2.1.2.3)
24470 */
24471 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24472 if (*localType == NULL) {
24473 xmlChar *str = NULL;
24474
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024475 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024476 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024477 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024478 "The QName value '%s' of the xsi:type attribute does not "
24479 "resolve to a type definition",
24480 xmlSchemaFormatQName(&str, nsName, local), NULL);
24481 FREE_AND_NULL(str);
24482 ret = vctxt->err;
24483 goto exit;
24484 }
24485 if (elemDecl != NULL) {
24486 int set = 0;
24487
24488 /*
24489 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24490 * "The ·local type definition· must be validly
24491 * derived from the {type definition} given the union of
24492 * the {disallowed substitutions} and the {type definition}'s
24493 * {prohibited substitutions}, as defined in
24494 * Type Derivation OK (Complex) (§3.4.6)
24495 * (if it is a complex type definition),
24496 * or given {disallowed substitutions} as defined in Type
24497 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24498 * definition)."
24499 *
24500 * {disallowed substitutions}: the "block" on the element decl.
24501 * {prohibited substitutions}: the "block" on the type def.
24502 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024503 /*
24504 * OPTIMIZE TODO: We could map types already evaluated
24505 * to be validly derived from other types to avoid checking
24506 * this over and over for the same types.
24507 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024508 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24509 (elemDecl->subtypes->flags &
24510 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24511 set |= SUBSET_EXTENSION;
24512
24513 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24514 (elemDecl->subtypes->flags &
24515 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24516 set |= SUBSET_RESTRICTION;
24517
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024518 /*
24519 * REMOVED and CHANGED since this produced a parser context
24520 * which adds to the string dict of the schema. So this would
24521 * change the schema and we don't want this. We don't need
24522 * the parser context anymore.
24523 *
24524 * if ((vctxt->pctxt == NULL) &&
24525 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24526 * return (-1);
24527 */
24528
24529 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024530 elemDecl->subtypes, set) != 0) {
24531 xmlChar *str = NULL;
24532
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024533 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024534 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24535 "The type definition '%s', specified by xsi:type, is "
24536 "blocked or not validly derived from the type definition "
24537 "of the element declaration",
24538 xmlSchemaFormatQName(&str,
24539 (*localType)->targetNamespace,
24540 (*localType)->name),
24541 NULL);
24542 FREE_AND_NULL(str);
24543 ret = vctxt->err;
24544 *localType = NULL;
24545 }
24546 }
24547 }
24548exit:
24549 ACTIVATE_ELEM;
24550 return (ret);
24551internal_error:
24552 ACTIVATE_ELEM;
24553 return (-1);
24554}
24555
24556static int
24557xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24558{
24559 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024560 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024561
24562 /*
24563 * cvc-elt (3.3.4) : 1
24564 */
24565 if (elemDecl == NULL) {
24566 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24567 "No matching declaration available");
24568 return (vctxt->err);
24569 }
24570 /*
24571 * cvc-elt (3.3.4) : 2
24572 */
24573 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24574 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24575 "The element declaration is abstract");
24576 return (vctxt->err);
24577 }
24578 if (actualType == NULL) {
24579 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24580 "The type definition is absent");
24581 return (XML_SCHEMAV_CVC_TYPE_1);
24582 }
24583 if (vctxt->nbAttrInfos != 0) {
24584 int ret;
24585 xmlSchemaAttrInfoPtr iattr;
24586 /*
24587 * cvc-elt (3.3.4) : 3
24588 * Handle 'xsi:nil'.
24589 */
24590 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24591 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24592 if (iattr) {
24593 ACTIVATE_ATTRIBUTE(iattr);
24594 /*
24595 * Validate the value.
24596 */
24597 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024598 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024599 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24600 iattr->value, &(iattr->val), 1, 0, 0);
24601 ACTIVATE_ELEM;
24602 if (ret < 0) {
24603 VERROR_INT("xmlSchemaValidateElemDecl",
24604 "calling xmlSchemaVCheckCVCSimpleType() to "
24605 "validate the attribute 'xsi:nil'");
24606 return (-1);
24607 }
24608 if (ret == 0) {
24609 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24610 /*
24611 * cvc-elt (3.3.4) : 3.1
24612 */
24613 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24614 "The element is not 'nillable'");
24615 /* Does not return an error on purpose. */
24616 } else {
24617 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24618 /*
24619 * cvc-elt (3.3.4) : 3.2.2
24620 */
24621 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24622 (elemDecl->value != NULL)) {
24623 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24624 "The element cannot be 'nilled' because "
24625 "there is a fixed value constraint defined "
24626 "for it");
24627 /* Does not return an error on purpose. */
24628 } else
24629 vctxt->inode->flags |=
24630 XML_SCHEMA_ELEM_INFO_NILLED;
24631 }
24632 }
24633 }
24634 }
24635 /*
24636 * cvc-elt (3.3.4) : 4
24637 * Handle 'xsi:type'.
24638 */
24639 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24640 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24641 if (iattr) {
24642 xmlSchemaTypePtr localType = NULL;
24643
24644 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24645 elemDecl);
24646 if (ret != 0) {
24647 if (ret == -1) {
24648 VERROR_INT("xmlSchemaValidateElemDecl",
24649 "calling xmlSchemaProcessXSIType() to "
24650 "process the attribute 'xsi:type'");
24651 return (-1);
24652 }
24653 /* Does not return an error on purpose. */
24654 }
24655 if (localType != NULL) {
24656 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24657 actualType = localType;
24658 }
24659 }
24660 }
24661 /*
24662 * IDC: Register identity-constraint XPath matchers.
24663 */
24664 if ((elemDecl->idcs != NULL) &&
24665 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24666 return (-1);
24667 /*
24668 * No actual type definition.
24669 */
24670 if (actualType == NULL) {
24671 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24672 "The type definition is absent");
24673 return (XML_SCHEMAV_CVC_TYPE_1);
24674 }
24675 /*
24676 * Remember the actual type definition.
24677 */
24678 vctxt->inode->typeDef = actualType;
24679
24680 return (0);
24681}
24682
24683static int
24684xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24685{
24686 xmlSchemaAttrInfoPtr iattr;
24687 int ret = 0, i;
24688
24689 /*
24690 * SPEC cvc-type (3.1.1)
24691 * "The attributes of must be empty, excepting those whose namespace
24692 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24693 * whose local name is one of type, nil, schemaLocation or
24694 * noNamespaceSchemaLocation."
24695 */
24696 if (vctxt->nbAttrInfos == 0)
24697 return (0);
24698 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24699 iattr = vctxt->attrInfos[i];
24700 if (! iattr->metaType) {
24701 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024702 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024703 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24704 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24705 }
24706 }
24707 ACTIVATE_ELEM
24708 return (ret);
24709}
24710
24711/*
24712* Cleanup currently used attribute infos.
24713*/
24714static void
24715xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24716{
24717 int i;
24718 xmlSchemaAttrInfoPtr attr;
24719
24720 if (vctxt->nbAttrInfos == 0)
24721 return;
24722 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24723 attr = vctxt->attrInfos[i];
24724 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24725 if (attr->localName != NULL)
24726 xmlFree((xmlChar *) attr->localName);
24727 if (attr->nsName != NULL)
24728 xmlFree((xmlChar *) attr->nsName);
24729 }
24730 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24731 if (attr->value != NULL)
24732 xmlFree((xmlChar *) attr->value);
24733 }
24734 if (attr->val != NULL) {
24735 xmlSchemaFreeValue(attr->val);
24736 attr->val = NULL;
24737 }
24738 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24739 }
24740 vctxt->nbAttrInfos = 0;
24741}
24742
24743/*
24744* 3.4.4 Complex Type Definition Validation Rules
24745* Element Locally Valid (Complex Type) (cvc-complex-type)
24746* 3.2.4 Attribute Declaration Validation Rules
24747* Validation Rule: Attribute Locally Valid (cvc-attribute)
24748* Attribute Locally Valid (Use) (cvc-au)
24749*
24750* Only "assessed" attribute information items will be visible to
24751* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24752*/
24753static int
24754xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24755{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024756 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24757 xmlSchemaItemListPtr attrUseList;
24758 xmlSchemaAttributeUsePtr attrUse = NULL;
24759 xmlSchemaAttributePtr attrDecl = NULL;
24760 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24761 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024762 int xpathRes = 0, res, wildIDs = 0, fixed;
24763
24764 /*
24765 * SPEC (cvc-attribute)
24766 * (1) "The declaration must not be ·absent· (see Missing
24767 * Sub-components (§5.3) for how this can fail to be
24768 * the case)."
24769 * (2) "Its {type definition} must not be absent."
24770 *
24771 * NOTE (1) + (2): This is not handled here, since we currently do not
24772 * allow validation against schemas which have missing sub-components.
24773 *
24774 * SPEC (cvc-complex-type)
24775 * (3) "For each attribute information item in the element information
24776 * item's [attributes] excepting those whose [namespace name] is
24777 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24778 * [local name] is one of type, nil, schemaLocation or
24779 * noNamespaceSchemaLocation, the appropriate case among the following
24780 * must be true:
24781 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024782 */
24783 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24784 /*
24785 * @nbAttrs is the number of attributes present in the instance.
24786 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024787 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024788 if (attrUseList != NULL)
24789 nbUses = attrUseList->nbItems;
24790 else
24791 nbUses = 0;
24792 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024793 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024794 attrUse = attrUseList->items[i];
24795 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24796 for (j = 0; j < nbAttrs; j++) {
24797 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024798 /*
24799 * SPEC (cvc-complex-type) (3)
24800 * Skip meta attributes.
24801 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024802 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024803 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024804 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024806 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024807 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024808 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024809 continue;
24810 found = 1;
24811 /*
24812 * SPEC (cvc-complex-type)
24813 * (3.1) "If there is among the {attribute uses} an attribute
24814 * use with an {attribute declaration} whose {name} matches
24815 * the attribute information item's [local name] and whose
24816 * {target namespace} is identical to the attribute information
24817 * item's [namespace name] (where an ·absent· {target namespace}
24818 * is taken to be identical to a [namespace name] with no value),
24819 * then the attribute information must be ·valid· with respect
24820 * to that attribute use as per Attribute Locally Valid (Use)
24821 * (§3.5.4). In this case the {attribute declaration} of that
24822 * attribute use is the ·context-determined declaration· for the
24823 * attribute information item with respect to Schema-Validity
24824 * Assessment (Attribute) (§3.2.4) and
24825 * Assessment Outcome (Attribute) (§3.2.5).
24826 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024827 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24828 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024829 /*
24830 * Context-determined declaration.
24831 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024832 iattr->decl = attrDecl;
24833 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024834 break;
24835 }
24836
24837 if (found)
24838 continue;
24839
24840 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24841 /*
24842 * Handle non-existent, required attributes.
24843 *
24844 * SPEC (cvc-complex-type)
24845 * (4) "The {attribute declaration} of each attribute use in
24846 * the {attribute uses} whose {required} is true matches one
24847 * of the attribute information items in the element information
24848 * item's [attributes] as per clause 3.1 above."
24849 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024850 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24851 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024852 VERROR_INT(
24853 "xmlSchemaVAttributesComplex",
24854 "calling xmlSchemaGetFreshAttrInfo()");
24855 return (-1);
24856 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024857 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24858 tmpiattr->use = attrUse;
24859 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024860 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24861 ((attrUse->defValue != NULL) ||
24862 (attrDecl->defValue != NULL))) {
24863 /*
24864 * Handle non-existent, optional, default/fixed attributes.
24865 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024866 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24867 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024868 VERROR_INT(
24869 "xmlSchemaVAttributesComplex",
24870 "calling xmlSchemaGetFreshAttrInfo()");
24871 return (-1);
24872 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024873 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24874 tmpiattr->use = attrUse;
24875 tmpiattr->decl = attrDecl;
24876 tmpiattr->typeDef = attrDecl->subtypes;
24877 tmpiattr->localName = attrDecl->name;
24878 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024879 }
24880 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024881
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024882 if (vctxt->nbAttrInfos == 0)
24883 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024884 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024885 /*
24886 * Validate against the wildcard.
24887 */
24888 if (type->attributeWildcard != NULL) {
24889 /*
24890 * SPEC (cvc-complex-type)
24891 * (3.2.1) "There must be an {attribute wildcard}."
24892 */
24893 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024894 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024895 /*
24896 * SPEC (cvc-complex-type) (3)
24897 * Skip meta attributes.
24898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024899 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024900 continue;
24901 /*
24902 * SPEC (cvc-complex-type)
24903 * (3.2.2) "The attribute information item must be ·valid· with
24904 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24905 *
24906 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24907 * "... its [namespace name] must be ·valid· with respect to
24908 * the wildcard constraint, as defined in Wildcard allows
24909 * Namespace Name (§3.10.4)."
24910 */
24911 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024912 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024913 /*
24914 * Handle processContents.
24915 *
24916 * SPEC (cvc-wildcard):
24917 * processContents | context-determined declaration:
24918 * "strict" "mustFind"
24919 * "lax" "none"
24920 * "skip" "skip"
24921 */
24922 if (type->attributeWildcard->processContents ==
24923 XML_SCHEMAS_ANY_SKIP) {
24924 /*
24925 * context-determined declaration = "skip"
24926 *
24927 * SPEC PSVI Assessment Outcome (Attribute)
24928 * [validity] = "notKnown"
24929 * [validation attempted] = "none"
24930 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024931 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024932 continue;
24933 }
24934 /*
24935 * Find an attribute declaration.
24936 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024937 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24938 iattr->localName, iattr->nsName);
24939 if (iattr->decl != NULL) {
24940 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024941 /*
24942 * SPEC (cvc-complex-type)
24943 * (5) "Let [Definition:] the wild IDs be the set of
24944 * all attribute information item to which clause 3.2
24945 * applied and whose ·validation· resulted in a
24946 * ·context-determined declaration· of mustFind or no
24947 * ·context-determined declaration· at all, and whose
24948 * [local name] and [namespace name] resolve (as
24949 * defined by QName resolution (Instance) (§3.15.4)) to
24950 * an attribute declaration whose {type definition} is
24951 * or is derived from ID. Then all of the following
24952 * must be true:"
24953 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024954 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024955 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024956 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024957 /*
24958 * SPEC (5.1) "There must be no more than one
24959 * item in ·wild IDs·."
24960 */
24961 if (wildIDs != 0) {
24962 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024963 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024964 TODO
24965 continue;
24966 }
24967 wildIDs++;
24968 /*
24969 * SPEC (cvc-complex-type)
24970 * (5.2) "If ·wild IDs· is non-empty, there must not
24971 * be any attribute uses among the {attribute uses}
24972 * whose {attribute declaration}'s {type definition}
24973 * is or is derived from ID."
24974 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024975 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024976 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024977 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024978 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024979 /* URGENT VAL TODO: implement */
24980 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024981 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024982 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024983 }
24984 }
24985 }
24986 } else if (type->attributeWildcard->processContents ==
24987 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024988 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024989 /*
24990 * SPEC PSVI Assessment Outcome (Attribute)
24991 * [validity] = "notKnown"
24992 * [validation attempted] = "none"
24993 */
24994 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024995 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024996 }
24997 }
24998 }
24999 }
25000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025001 if (vctxt->nbAttrInfos == 0)
25002 return (0);
25003
25004 /*
25005 * Validate values, create default attributes, evaluate IDCs.
25006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025007 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025008 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025009 /*
25010 * VAL TODO: Note that we won't try to resolve IDCs to
25011 * "lax" and "skip" validated attributes. Check what to
25012 * do in this case.
25013 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025014 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25015 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025016 continue;
25017 /*
25018 * VAL TODO: What to do if the type definition is missing?
25019 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025020 if (iattr->typeDef == NULL) {
25021 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025022 continue;
25023 }
25024
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025025 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025026 fixed = 0;
25027 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025028
25029 if (vctxt->xpathStates != NULL) {
25030 /*
25031 * Evaluate IDCs.
25032 */
25033 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25034 XML_ATTRIBUTE_NODE);
25035 if (xpathRes == -1) {
25036 VERROR_INT("xmlSchemaVAttributesComplex",
25037 "calling xmlSchemaXPathEvaluate()");
25038 goto internal_error;
25039 }
25040 }
25041
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025042 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025043 /*
25044 * Default/fixed attributes.
25045 */
25046 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025047 if (iattr->use->defValue != NULL) {
25048 iattr->value = (xmlChar *) iattr->use->defValue;
25049 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025050 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025051 iattr->value = (xmlChar *) iattr->decl->defValue;
25052 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025053 }
25054 /*
25055 * IDCs will consume the precomputed default value,
25056 * so we need to clone it.
25057 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025058 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025059 VERROR_INT("xmlSchemaVAttributesComplex",
25060 "default/fixed value on an attribute use was "
25061 "not precomputed");
25062 goto internal_error;
25063 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025064 iattr->val = xmlSchemaCopyValue(iattr->val);
25065 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025066 VERROR_INT("xmlSchemaVAttributesComplex",
25067 "calling xmlSchemaCopyValue()");
25068 goto internal_error;
25069 }
25070 }
25071 /*
25072 * PSVI: Add the default attribute to the current element.
25073 * VAL TODO: Should we use the *normalized* value? This currently
25074 * uses the *initial* value.
25075 */
25076 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025077 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025078 xmlChar *normValue;
25079 const xmlChar *value;
25080
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025081 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025082 /*
25083 * Normalize the value.
25084 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025085 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25086 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025087 if (normValue != NULL)
25088 value = BAD_CAST normValue;
25089
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025090 if (iattr->nsName == NULL) {
25091 if (xmlNewProp(iattr->node->parent,
25092 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025093 VERROR_INT("xmlSchemaVAttributesComplex",
25094 "callling xmlNewProp()");
25095 if (normValue != NULL)
25096 xmlFree(normValue);
25097 goto internal_error;
25098 }
25099 } else {
25100 xmlNsPtr ns;
25101
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025102 ns = xmlSearchNsByHref(iattr->node->doc,
25103 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025104 if (ns == NULL) {
25105 xmlChar prefix[12];
25106 int counter = 0;
25107
25108 /*
25109 * Create a namespace declaration on the validation
25110 * root node if no namespace declaration is in scope.
25111 */
25112 do {
25113 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025114 ns = xmlSearchNs(iattr->node->doc,
25115 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025116 if (counter > 1000) {
25117 VERROR_INT(
25118 "xmlSchemaVAttributesComplex",
25119 "could not compute a ns prefix for a "
25120 "default/fixed attribute");
25121 if (normValue != NULL)
25122 xmlFree(normValue);
25123 goto internal_error;
25124 }
25125 } while (ns != NULL);
25126 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025127 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025128 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025129 /*
25130 * TODO:
25131 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25132 * If we have QNames: do we need to ensure there's a
25133 * prefix defined for the QName?
25134 */
25135 xmlNewNsProp(iattr->node->parent, ns,
25136 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025137 }
25138 if (normValue != NULL)
25139 xmlFree(normValue);
25140 }
25141 /*
25142 * Go directly to IDC evaluation.
25143 */
25144 goto eval_idcs;
25145 }
25146 /*
25147 * Validate the value.
25148 */
25149 if (vctxt->value != NULL) {
25150 /*
25151 * Free last computed value; just for safety reasons.
25152 */
25153 xmlSchemaFreeValue(vctxt->value);
25154 vctxt->value = NULL;
25155 }
25156 /*
25157 * Note that the attribute *use* can be unavailable, if
25158 * the attribute was a wild attribute.
25159 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025160 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25161 ((iattr->use != NULL) &&
25162 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025163 fixed = 1;
25164 else
25165 fixed = 0;
25166 /*
25167 * SPEC (cvc-attribute)
25168 * (3) "The item's ·normalized value· must be locally ·valid·
25169 * with respect to that {type definition} as per
25170 * String Valid (§3.14.4)."
25171 *
25172 * VAL TODO: Do we already have the
25173 * "normalized attribute value" here?
25174 */
25175 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025176 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025177 /*
25178 * Request a computed value.
25179 */
25180 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025181 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025182 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025183 1, 1, 0);
25184 } else {
25185 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025186 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025187 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025188 1, 0, 0);
25189 }
25190
25191 if (res != 0) {
25192 if (res == -1) {
25193 VERROR_INT("xmlSchemaVAttributesComplex",
25194 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25195 goto internal_error;
25196 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025197 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025198 /*
25199 * SPEC PSVI Assessment Outcome (Attribute)
25200 * [validity] = "invalid"
25201 */
25202 goto eval_idcs;
25203 }
25204
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025205 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025206 /*
25207 * SPEC Attribute Locally Valid (Use) (cvc-au)
25208 * "For an attribute information item to be·valid·
25209 * with respect to an attribute use its *normalized*
25210 * value· must match the *canonical* lexical
25211 * representation of the attribute use's {value
25212 * constraint}value, if it is present and fixed."
25213 *
25214 * VAL TODO: The requirement for the *canonical* value
25215 * will be removed in XML Schema 1.1.
25216 */
25217 /*
25218 * SPEC Attribute Locally Valid (cvc-attribute)
25219 * (4) "The item's *actual* value· must match the *value* of
25220 * the {value constraint}, if it is present and fixed."
25221 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025222 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025223 /* VAL TODO: A value was not precomputed. */
25224 TODO
25225 goto eval_idcs;
25226 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025227 if ((iattr->use != NULL) &&
25228 (iattr->use->defValue != NULL)) {
25229 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025230 /* VAL TODO: A default value was not precomputed. */
25231 TODO
25232 goto eval_idcs;
25233 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025234 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025235 /*
25236 if (xmlSchemaCompareValuesWhtsp(attr->val,
25237 (xmlSchemaWhitespaceValueType) ws,
25238 attr->use->defVal,
25239 (xmlSchemaWhitespaceValueType) ws) != 0) {
25240 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025241 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25242 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025243 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025244 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025245 /* VAL TODO: A default value was not precomputed. */
25246 TODO
25247 goto eval_idcs;
25248 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025249 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025250 /*
25251 if (xmlSchemaCompareValuesWhtsp(attr->val,
25252 (xmlSchemaWhitespaceValueType) ws,
25253 attrDecl->defVal,
25254 (xmlSchemaWhitespaceValueType) ws) != 0) {
25255 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025256 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25257 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025258 }
25259 /*
25260 * [validity] = "valid"
25261 */
25262 }
25263eval_idcs:
25264 /*
25265 * Evaluate IDCs.
25266 */
25267 if (xpathRes) {
25268 if (xmlSchemaXPathProcessHistory(vctxt,
25269 vctxt->depth +1) == -1) {
25270 VERROR_INT("xmlSchemaVAttributesComplex",
25271 "calling xmlSchemaXPathEvaluate()");
25272 goto internal_error;
25273 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025274 } else if (vctxt->xpathStates != NULL)
25275 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025276 }
25277
25278 /*
25279 * Report errors.
25280 */
25281 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025282 iattr = vctxt->attrInfos[i];
25283 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25284 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25285 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25286 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025287 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025288 ACTIVATE_ATTRIBUTE(iattr);
25289 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025290 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25291 xmlChar *str = NULL;
25292 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025293 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025294 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25295 "The attribute '%s' is required but missing",
25296 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025297 iattr->decl->targetNamespace,
25298 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025299 NULL);
25300 FREE_AND_NULL(str)
25301 break;
25302 }
25303 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25304 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25305 "The type definition is absent");
25306 break;
25307 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025308 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025309 XML_SCHEMAV_CVC_AU, NULL, NULL,
25310 "The value '%s' does not match the fixed "
25311 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025312 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025313 break;
25314 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25315 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25316 "No matching global attribute declaration available, but "
25317 "demanded by the strict wildcard");
25318 break;
25319 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025320 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025321 break;
25322 /*
25323 * MAYBE VAL TODO: One might report different error messages
25324 * for the following errors.
25325 */
25326 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025327 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025328 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025329 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025330 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025331 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025332 }
25333 break;
25334 default:
25335 break;
25336 }
25337 }
25338
25339 ACTIVATE_ELEM;
25340 return (0);
25341internal_error:
25342 ACTIVATE_ELEM;
25343 return (-1);
25344}
25345
25346static int
25347xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25348 int *skip)
25349{
25350 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25351 /*
25352 * The namespace of the element was already identified to be
25353 * matching the wildcard.
25354 */
25355 if ((skip == NULL) || (wild == NULL) ||
25356 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25357 VERROR_INT("xmlSchemaValidateElemWildcard",
25358 "bad arguments");
25359 return (-1);
25360 }
25361 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025362 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25363 /*
25364 * URGENT VAL TODO: Either we need to position the stream to the
25365 * next sibling, or walk the whole subtree.
25366 */
25367 *skip = 1;
25368 return (0);
25369 }
25370 {
25371 xmlSchemaElementPtr decl = NULL;
25372
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025373 decl = xmlSchemaGetElem(vctxt->schema,
25374 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025375 if (decl != NULL) {
25376 vctxt->inode->decl = decl;
25377 return (0);
25378 }
25379 }
25380 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25381 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025382 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025383 "No matching global element declaration available, but "
25384 "demanded by the strict wildcard");
25385 return (vctxt->err);
25386 }
25387 if (vctxt->nbAttrInfos != 0) {
25388 xmlSchemaAttrInfoPtr iattr;
25389 /*
25390 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25391 * (1.2.1.2.1) - (1.2.1.2.3 )
25392 *
25393 * Use the xsi:type attribute for the type definition.
25394 */
25395 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25396 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25397 if (iattr != NULL) {
25398 if (xmlSchemaProcessXSIType(vctxt, iattr,
25399 &(vctxt->inode->typeDef), NULL) == -1) {
25400 VERROR_INT("xmlSchemaValidateElemWildcard",
25401 "calling xmlSchemaProcessXSIType() to "
25402 "process the attribute 'xsi:nil'");
25403 return (-1);
25404 }
25405 /*
25406 * Don't return an error on purpose.
25407 */
25408 return (0);
25409 }
25410 }
25411 /*
25412 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25413 *
25414 * Fallback to "anyType".
25415 */
25416 vctxt->inode->typeDef =
25417 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25418 return (0);
25419}
25420
25421/*
25422* xmlSchemaCheckCOSValidDefault:
25423*
25424* This will be called if: not nilled, no content and a default/fixed
25425* value is provided.
25426*/
25427
25428static int
25429xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25430 const xmlChar *value,
25431 xmlSchemaValPtr *val)
25432{
25433 int ret = 0;
25434 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25435
25436 /*
25437 * cos-valid-default:
25438 * Schema Component Constraint: Element Default Valid (Immediate)
25439 * For a string to be a valid default with respect to a type
25440 * definition the appropriate case among the following must be true:
25441 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025442 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025443 /*
25444 * Complex type.
25445 *
25446 * SPEC (2.1) "its {content type} must be a simple type definition
25447 * or mixed."
25448 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25449 * type}'s particle must be ·emptiable· as defined by
25450 * Particle Emptiable (§3.9.6)."
25451 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025452 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25453 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25454 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025455 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25456 /* NOTE that this covers (2.2.2) as well. */
25457 VERROR(ret, NULL,
25458 "For a string to be a valid default, the type definition "
25459 "must be a simple type or a complex type with simple content "
25460 "or mixed content and a particle emptiable");
25461 return(ret);
25462 }
25463 }
25464 /*
25465 * 1 If the type definition is a simple type definition, then the string
25466 * must be ·valid· with respect to that definition as defined by String
25467 * Valid (§3.14.4).
25468 *
25469 * AND
25470 *
25471 * 2.2.1 If the {content type} is a simple type definition, then the
25472 * string must be ·valid· with respect to that simple type definition
25473 * as defined by String Valid (§3.14.4).
25474 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025475 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025476
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025477 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025478 NULL, inode->typeDef, value, val, 1, 1, 0);
25479
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025480 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025481
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025482 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025483 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25484 }
25485 if (ret < 0) {
25486 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25487 "calling xmlSchemaVCheckCVCSimpleType()");
25488 }
25489 return (ret);
25490}
25491
25492static void
25493xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25494 const xmlChar * name ATTRIBUTE_UNUSED,
25495 xmlSchemaElementPtr item,
25496 xmlSchemaNodeInfoPtr inode)
25497{
25498 inode->decl = item;
25499#ifdef DEBUG_CONTENT
25500 {
25501 xmlChar *str = NULL;
25502
25503 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25504 xmlGenericError(xmlGenericErrorContext,
25505 "AUTOMATON callback for '%s' [declaration]\n",
25506 xmlSchemaFormatQName(&str,
25507 inode->localName, inode->nsName));
25508 } else {
25509 xmlGenericError(xmlGenericErrorContext,
25510 "AUTOMATON callback for '%s' [wildcard]\n",
25511 xmlSchemaFormatQName(&str,
25512 inode->localName, inode->nsName));
25513
25514 }
25515 FREE_AND_NULL(str)
25516 }
25517#endif
25518}
25519
25520static int
25521xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025522{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025523 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25524 if (vctxt->inode == NULL) {
25525 VERROR_INT("xmlSchemaValidatorPushElem",
25526 "calling xmlSchemaGetFreshElemInfo()");
25527 return (-1);
25528 }
25529 vctxt->nbAttrInfos = 0;
25530 return (0);
25531}
25532
25533static int
25534xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25535 xmlSchemaNodeInfoPtr inode,
25536 xmlSchemaTypePtr type,
25537 const xmlChar *value)
25538{
25539 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25540 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025541 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025542 type, value, &(inode->val), 1, 1, 0));
25543 else
25544 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025545 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025546 type, value, NULL, 1, 0, 0));
25547}
25548
25549
25550
25551/*
25552* Process END of element.
25553*/
25554static int
25555xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25556{
25557 int ret = 0;
25558 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25559
25560 if (vctxt->nbAttrInfos != 0)
25561 xmlSchemaClearAttrInfos(vctxt);
25562 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25563 /*
25564 * This element was not expected;
25565 * we will not validate child elements of broken parents.
25566 * Skip validation of all content of the parent.
25567 */
25568 vctxt->skipDepth = vctxt->depth -1;
25569 goto end_elem;
25570 }
25571 if ((inode->typeDef == NULL) ||
25572 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25573 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025574 * 1. the type definition might be missing if the element was
25575 * error prone
25576 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025577 */
25578 goto end_elem;
25579 }
25580 /*
25581 * Check the content model.
25582 */
25583 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25584 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25585
25586 /*
25587 * Workaround for "anyType".
25588 */
25589 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25590 goto character_content;
25591
25592 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25593 xmlChar *values[10];
25594 int terminal, nbval = 10, nbneg;
25595
25596 if (inode->regexCtxt == NULL) {
25597 /*
25598 * Create the regex context.
25599 */
25600 inode->regexCtxt =
25601 xmlRegNewExecCtxt(inode->typeDef->contModel,
25602 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25603 vctxt);
25604 if (inode->regexCtxt == NULL) {
25605 VERROR_INT("xmlSchemaValidatorPopElem",
25606 "failed to create a regex context");
25607 goto internal_error;
25608 }
25609#ifdef DEBUG_AUTOMATA
25610 xmlGenericError(xmlGenericErrorContext,
25611 "AUTOMATON create on '%s'\n", inode->localName);
25612#endif
25613 }
25614 /*
25615 * Get hold of the still expected content, since a further
25616 * call to xmlRegExecPushString() will loose this information.
25617 */
25618 xmlRegExecNextValues(inode->regexCtxt,
25619 &nbval, &nbneg, &values[0], &terminal);
25620 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25621 if (ret <= 0) {
25622 /*
25623 * Still missing something.
25624 */
25625 ret = 1;
25626 inode->flags |=
25627 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025628 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025629 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25630 "Missing child element(s)",
25631 nbval, nbneg, values);
25632#ifdef DEBUG_AUTOMATA
25633 xmlGenericError(xmlGenericErrorContext,
25634 "AUTOMATON missing ERROR on '%s'\n",
25635 inode->localName);
25636#endif
25637 } else {
25638 /*
25639 * Content model is satisfied.
25640 */
25641 ret = 0;
25642#ifdef DEBUG_AUTOMATA
25643 xmlGenericError(xmlGenericErrorContext,
25644 "AUTOMATON succeeded on '%s'\n",
25645 inode->localName);
25646#endif
25647 }
25648
25649 }
25650 }
25651 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25652 goto end_elem;
25653
25654character_content:
25655
25656 if (vctxt->value != NULL) {
25657 xmlSchemaFreeValue(vctxt->value);
25658 vctxt->value = NULL;
25659 }
25660 /*
25661 * Check character content.
25662 */
25663 if (inode->decl == NULL) {
25664 /*
25665 * Speedup if no declaration exists.
25666 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025667 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025668 ret = xmlSchemaVCheckINodeDataType(vctxt,
25669 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025670 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025671 ret = xmlSchemaVCheckINodeDataType(vctxt,
25672 inode, inode->typeDef->contentTypeDef,
25673 inode->value);
25674 }
25675 if (ret < 0) {
25676 VERROR_INT("xmlSchemaValidatorPopElem",
25677 "calling xmlSchemaVCheckCVCSimpleType()");
25678 goto internal_error;
25679 }
25680 goto end_elem;
25681 }
25682 /*
25683 * cvc-elt (3.3.4) : 5
25684 * The appropriate case among the following must be true:
25685 */
25686 /*
25687 * cvc-elt (3.3.4) : 5.1
25688 * If the declaration has a {value constraint},
25689 * the item has neither element nor character [children] and
25690 * clause 3.2 has not applied, then all of the following must be true:
25691 */
25692 if ((inode->decl->value != NULL) &&
25693 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25694 (! INODE_NILLED(inode))) {
25695 /*
25696 * cvc-elt (3.3.4) : 5.1.1
25697 * If the ·actual type definition· is a ·local type definition·
25698 * then the canonical lexical representation of the {value constraint}
25699 * value must be a valid default for the ·actual type definition· as
25700 * defined in Element Default Valid (Immediate) (§3.3.6).
25701 */
25702 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025703 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025704 * NOTE: Although the *canonical* value is stated, it is not
25705 * relevant if canonical or not. Additionally XML Schema 1.1
25706 * will removed this requirement as well.
25707 */
25708 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25709
25710 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25711 inode->decl->value, &(inode->val));
25712 if (ret != 0) {
25713 if (ret < 0) {
25714 VERROR_INT("xmlSchemaValidatorPopElem",
25715 "calling xmlSchemaCheckCOSValidDefault()");
25716 goto internal_error;
25717 }
25718 goto end_elem;
25719 }
25720 /*
25721 * Stop here, to avoid redundant validation of the value
25722 * (see following).
25723 */
25724 goto default_psvi;
25725 }
25726 /*
25727 * cvc-elt (3.3.4) : 5.1.2
25728 * The element information item with the canonical lexical
25729 * representation of the {value constraint} value used as its
25730 * ·normalized value· must be ·valid· with respect to the
25731 * ·actual type definition· as defined by Element Locally Valid (Type)
25732 * (§3.3.4).
25733 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025734 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025735 ret = xmlSchemaVCheckINodeDataType(vctxt,
25736 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025737 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025738 ret = xmlSchemaVCheckINodeDataType(vctxt,
25739 inode, inode->typeDef->contentTypeDef,
25740 inode->decl->value);
25741 }
25742 if (ret != 0) {
25743 if (ret < 0) {
25744 VERROR_INT("xmlSchemaValidatorPopElem",
25745 "calling xmlSchemaVCheckCVCSimpleType()");
25746 goto internal_error;
25747 }
25748 goto end_elem;
25749 }
25750
25751default_psvi:
25752 /*
25753 * PSVI: Create a text node on the instance element.
25754 */
25755 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25756 (inode->node != NULL)) {
25757 xmlNodePtr textChild;
25758 xmlChar *normValue;
25759 /*
25760 * VAL TODO: Normalize the value.
25761 */
25762 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25763 inode->decl->value);
25764 if (normValue != NULL) {
25765 textChild = xmlNewText(BAD_CAST normValue);
25766 xmlFree(normValue);
25767 } else
25768 textChild = xmlNewText(inode->decl->value);
25769 if (textChild == NULL) {
25770 VERROR_INT("xmlSchemaValidatorPopElem",
25771 "calling xmlNewText()");
25772 goto internal_error;
25773 } else
25774 xmlAddChild(inode->node, textChild);
25775 }
25776
25777 } else if (! INODE_NILLED(inode)) {
25778 /*
25779 * 5.2.1 The element information item must be ·valid· with respect
25780 * to the ·actual type definition· as defined by Element Locally
25781 * Valid (Type) (§3.3.4).
25782 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025783 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025784 /*
25785 * SPEC (cvc-type) (3.1)
25786 * "If the type definition is a simple type definition, ..."
25787 * (3.1.3) "If clause 3.2 of Element Locally Valid
25788 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25789 * must be ·valid· with respect to the type definition as defined
25790 * by String Valid (§3.14.4).
25791 */
25792 ret = xmlSchemaVCheckINodeDataType(vctxt,
25793 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025794 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025795 /*
25796 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25797 * definition, then the element information item must be
25798 * ·valid· with respect to the type definition as per
25799 * Element Locally Valid (Complex Type) (§3.4.4);"
25800 *
25801 * SPEC (cvc-complex-type) (2.2)
25802 * "If the {content type} is a simple type definition, ...
25803 * the ·normalized value· of the element information item is
25804 * ·valid· with respect to that simple type definition as
25805 * defined by String Valid (§3.14.4)."
25806 */
25807 ret = xmlSchemaVCheckINodeDataType(vctxt,
25808 inode, inode->typeDef->contentTypeDef, inode->value);
25809 }
25810 if (ret != 0) {
25811 if (ret < 0) {
25812 VERROR_INT("xmlSchemaValidatorPopElem",
25813 "calling xmlSchemaVCheckCVCSimpleType()");
25814 goto internal_error;
25815 }
25816 goto end_elem;
25817 }
25818 /*
25819 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25820 * not applied, all of the following must be true:
25821 */
25822 if ((inode->decl->value != NULL) &&
25823 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25824
25825 /*
25826 * TODO: We will need a computed value, when comparison is
25827 * done on computed values.
25828 */
25829 /*
25830 * 5.2.2.1 The element information item must have no element
25831 * information item [children].
25832 */
25833 if (inode->flags &
25834 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25835 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25836 VERROR(ret, NULL,
25837 "The content must not containt element nodes since "
25838 "there is a fixed value constraint");
25839 goto end_elem;
25840 } else {
25841 /*
25842 * 5.2.2.2 The appropriate case among the following must
25843 * be true:
25844 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025845 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025846 /*
25847 * 5.2.2.2.1 If the {content type} of the ·actual type
25848 * definition· is mixed, then the *initial value* of the
25849 * item must match the canonical lexical representation
25850 * of the {value constraint} value.
25851 *
25852 * ... the *initial value* of an element information
25853 * item is the string composed of, in order, the
25854 * [character code] of each character information item in
25855 * the [children] of that element information item.
25856 */
25857 if (! xmlStrEqual(inode->value, inode->decl->value)){
25858 /*
25859 * VAL TODO: Report invalid & expected values as well.
25860 * VAL TODO: Implement the canonical stuff.
25861 */
25862 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025863 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025864 ret, NULL, NULL,
25865 "The initial value '%s' does not match the fixed "
25866 "value constraint '%s'",
25867 inode->value, inode->decl->value);
25868 goto end_elem;
25869 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025870 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025871 /*
25872 * 5.2.2.2.2 If the {content type} of the ·actual type
25873 * definition· is a simple type definition, then the
25874 * *actual value* of the item must match the canonical
25875 * lexical representation of the {value constraint} value.
25876 */
25877 /*
25878 * VAL TODO: *actual value* is the normalized value, impl.
25879 * this.
25880 * VAL TODO: Report invalid & expected values as well.
25881 * VAL TODO: Implement a comparison with the computed values.
25882 */
25883 if (! xmlStrEqual(inode->value,
25884 inode->decl->value)) {
25885 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025886 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025887 ret, NULL, NULL,
25888 "The actual value '%s' does not match the fixed "
25889 "value constraint '%s'",
25890 inode->value,
25891 inode->decl->value);
25892 goto end_elem;
25893 }
25894 }
25895 }
25896 }
25897 }
25898
25899end_elem:
25900 if (vctxt->depth < 0) {
25901 /* TODO: raise error? */
25902 return (0);
25903 }
25904 if (vctxt->depth == vctxt->skipDepth)
25905 vctxt->skipDepth = -1;
25906 /*
25907 * Evaluate the history of XPath state objects.
25908 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000025909 if (inode->appliedXPath &&
25910 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025911 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025912 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025913 * MAYBE TODO:
25914 * SPEC (6) "The element information item must be ·valid· with
25915 * respect to each of the {identity-constraint definitions} as per
25916 * Identity-constraint Satisfied (§3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025917 */
25918 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025919 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
25920 * need to be built in any case.
25921 * We will currently build IDC node-tables and bubble them only if
25922 * keyrefs do exist.
25923 */
25924
25925 /*
25926 * Add the current IDC target-nodes to the IDC node-tables.
25927 */
25928 if ((inode->idcMatchers != NULL) &&
25929 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25930 {
25931 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
25932 goto internal_error;
25933 }
25934 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025935 * Validate IDC keyrefs.
25936 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025937 if (vctxt->inode->hasKeyrefs)
25938 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25939 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025940 /*
25941 * Merge/free the IDC table.
25942 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025943 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025944#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025945 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025946 inode->nsName,
25947 inode->localName,
25948 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025949#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025950 if ((vctxt->depth > 0) &&
25951 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
25952 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025953 /*
25954 * Merge the IDC node table with the table of the parent node.
25955 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025956 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25957 goto internal_error;
25958 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025959 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025960 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025961 * Clear the current ielem.
25962 * VAL TODO: Don't free the PSVI IDC tables if they are
25963 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025965 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025966 /*
25967 * Skip further processing if we are on the validation root.
25968 */
25969 if (vctxt->depth == 0) {
25970 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025971 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025972 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025973 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025974 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025975 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025976 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025977 if (vctxt->aidcs != NULL) {
25978 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25979 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025980 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025981 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025982 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025983 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025984 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025985 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000025986 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025987 }
25988 aidc = aidc->next;
25989 } while (aidc != NULL);
25990 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025991 vctxt->depth--;
25992 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025993 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025994 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025995 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25996 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025997 return (ret);
25998
25999internal_error:
26000 vctxt->err = -1;
26001 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026002}
26003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026004/*
26005* 3.4.4 Complex Type Definition Validation Rules
26006* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26007*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026008static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026009xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026010{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026011 xmlSchemaNodeInfoPtr pielem;
26012 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026013 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026014
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026015 if (vctxt->depth <= 0) {
26016 VERROR_INT("xmlSchemaValidateChildElem",
26017 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026018 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026019 }
26020 pielem = vctxt->elemInfos[vctxt->depth -1];
26021 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26022 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026023 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026024 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026025 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026026 if (INODE_NILLED(pielem)) {
26027 /*
26028 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26029 */
26030 ACTIVATE_PARENT_ELEM;
26031 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26032 VERROR(ret, NULL,
26033 "Neither character nor element content is allowed, "
26034 "because the element was 'nilled'");
26035 ACTIVATE_ELEM;
26036 goto unexpected_elem;
26037 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026038
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026039 ptype = pielem->typeDef;
26040
26041 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26042 /*
26043 * Workaround for "anyType": we have currently no content model
26044 * assigned for "anyType", so handle it explicitely.
26045 * "anyType" has an unbounded, lax "any" wildcard.
26046 */
26047 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26048 vctxt->inode->localName,
26049 vctxt->inode->nsName);
26050
26051 if (vctxt->inode->decl == NULL) {
26052 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026053 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026054 * Process "xsi:type".
26055 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026056 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026057 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26058 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26059 if (iattr != NULL) {
26060 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26061 &(vctxt->inode->typeDef), NULL);
26062 if (ret != 0) {
26063 if (ret == -1) {
26064 VERROR_INT("xmlSchemaValidateChildElem",
26065 "calling xmlSchemaProcessXSIType() to "
26066 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026067 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026069 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026071 } else {
26072 /*
26073 * Fallback to "anyType".
26074 *
26075 * SPEC (cvc-assess-elt)
26076 * "If the item cannot be ·strictly assessed·, [...]
26077 * an element information item's schema validity may be laxly
26078 * assessed if its ·context-determined declaration· is not
26079 * skip by ·validating· with respect to the ·ur-type
26080 * definition· as per Element Locally Valid (Type) (§3.3.4)."
26081 */
26082 vctxt->inode->typeDef =
26083 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026084 }
26085 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026086 return (0);
26087 }
26088
26089 switch (ptype->contentType) {
26090 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026091 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026092 * SPEC (2.1) "If the {content type} is empty, then the
26093 * element information item has no character or element
26094 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026096 ACTIVATE_PARENT_ELEM
26097 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26098 VERROR(ret, NULL,
26099 "Element content is not allowed, "
26100 "because the content type is empty");
26101 ACTIVATE_ELEM
26102 goto unexpected_elem;
26103 break;
26104
26105 case XML_SCHEMA_CONTENT_MIXED:
26106 case XML_SCHEMA_CONTENT_ELEMENTS: {
26107 xmlRegExecCtxtPtr regexCtxt;
26108 xmlChar *values[10];
26109 int terminal, nbval = 10, nbneg;
26110
26111 /* VAL TODO: Optimized "anyType" validation.*/
26112
26113 if (ptype->contModel == NULL) {
26114 VERROR_INT("xmlSchemaValidateChildElem",
26115 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026116 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026118 /*
26119 * Safety belf for evaluation if the cont. model was already
26120 * examined to be invalid.
26121 */
26122 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26123 VERROR_INT("xmlSchemaValidateChildElem",
26124 "validating elem, but elem content is already invalid");
26125 return (-1);
26126 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026127
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026128 regexCtxt = pielem->regexCtxt;
26129 if (regexCtxt == NULL) {
26130 /*
26131 * Create the regex context.
26132 */
26133 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26134 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26135 vctxt);
26136 if (regexCtxt == NULL) {
26137 VERROR_INT("xmlSchemaValidateChildElem",
26138 "failed to create a regex context");
26139 return (-1);
26140 }
26141 pielem->regexCtxt = regexCtxt;
26142#ifdef DEBUG_AUTOMATA
26143 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26144 pielem->localName);
26145#endif
26146 }
26147
26148 /*
26149 * SPEC (2.4) "If the {content type} is element-only or mixed,
26150 * then the sequence of the element information item's
26151 * element information item [children], if any, taken in
26152 * order, is ·valid· with respect to the {content type}'s
26153 * particle, as defined in Element Sequence Locally Valid
26154 * (Particle) (§3.9.4)."
26155 */
26156 ret = xmlRegExecPushString2(regexCtxt,
26157 vctxt->inode->localName,
26158 vctxt->inode->nsName,
26159 vctxt->inode);
26160#ifdef DEBUG_AUTOMATA
26161 if (ret < 0)
26162 xmlGenericError(xmlGenericErrorContext,
26163 "AUTOMATON push ERROR for '%s' on '%s'\n",
26164 vctxt->inode->localName, pielem->localName);
26165 else
26166 xmlGenericError(xmlGenericErrorContext,
26167 "AUTOMATON push OK for '%s' on '%s'\n",
26168 vctxt->inode->localName, pielem->localName);
26169#endif
26170 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26171 VERROR_INT("xmlSchemaValidateChildElem",
26172 "calling xmlRegExecPushString2()");
26173 return (-1);
26174 }
26175 if (ret < 0) {
26176 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26177 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026178 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026179 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26180 "This element is not expected",
26181 nbval, nbneg, values);
26182 ret = vctxt->err;
26183 goto unexpected_elem;
26184 } else
26185 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026186 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026187 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026188 case XML_SCHEMA_CONTENT_SIMPLE:
26189 case XML_SCHEMA_CONTENT_BASIC:
26190 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026191 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026192 /*
26193 * SPEC (cvc-complex-type) (2.2)
26194 * "If the {content type} is a simple type definition, then
26195 * the element information item has no element information
26196 * item [children], ..."
26197 */
26198 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26199 VERROR(ret, NULL, "Element content is not allowed, "
26200 "because the content type is a simple type definition");
26201 } else {
26202 /*
26203 * SPEC (cvc-type) (3.1.2) "The element information item must
26204 * have no element information item [children]."
26205 */
26206 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26207 VERROR(ret, NULL, "Element content is not allowed, "
26208 "because the type definition is simple");
26209 }
26210 ACTIVATE_ELEM
26211 ret = vctxt->err;
26212 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026213 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026214
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026215 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026216 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026217 }
26218 return (ret);
26219unexpected_elem:
26220 /*
26221 * Pop this element and set the skipDepth to skip
26222 * all further content of the parent element.
26223 */
26224 vctxt->skipDepth = vctxt->depth;
26225 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26226 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26227 return (ret);
26228}
26229
26230#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26231#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26232#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26233
26234static int
26235xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26236 int nodeType, const xmlChar *value, int len,
26237 int mode, int *consumed)
26238{
26239 /*
26240 * Unfortunately we have to duplicate the text sometimes.
26241 * OPTIMIZE: Maybe we could skip it, if:
26242 * 1. content type is simple
26243 * 2. whitespace is "collapse"
26244 * 3. it consists of whitespace only
26245 *
26246 * Process character content.
26247 */
26248 if (consumed != NULL)
26249 *consumed = 0;
26250 if (INODE_NILLED(vctxt->inode)) {
26251 /*
26252 * SPEC cvc-elt (3.3.4 - 3.2.1)
26253 * "The element information item must have no character or
26254 * element information item [children]."
26255 */
26256 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26257 "Neither character nor element content is allowed "
26258 "because the element is 'nilled'");
26259 return (vctxt->err);
26260 }
26261 /*
26262 * SPEC (2.1) "If the {content type} is empty, then the
26263 * element information item has no character or element
26264 * information item [children]."
26265 */
26266 if (vctxt->inode->typeDef->contentType ==
26267 XML_SCHEMA_CONTENT_EMPTY) {
26268 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26269 "Character content is not allowed, "
26270 "because the content type is empty");
26271 return (vctxt->err);
26272 }
26273
26274 if (vctxt->inode->typeDef->contentType ==
26275 XML_SCHEMA_CONTENT_ELEMENTS) {
26276 if ((nodeType != XML_TEXT_NODE) ||
26277 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26278 /*
26279 * SPEC cvc-complex-type (2.3)
26280 * "If the {content type} is element-only, then the
26281 * element information item has no character information
26282 * item [children] other than those whose [character
26283 * code] is defined as a white space in [XML 1.0 (Second
26284 * Edition)]."
26285 */
26286 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26287 "Character content other than whitespace is not allowed "
26288 "because the content type is 'element-only'");
26289 return (vctxt->err);
26290 }
26291 return (0);
26292 }
26293
26294 if ((value == NULL) || (value[0] == 0))
26295 return (0);
26296 /*
26297 * Save the value.
26298 * NOTE that even if the content type is *mixed*, we need the
26299 * *initial value* for default/fixed value constraints.
26300 */
26301 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26302 ((vctxt->inode->decl == NULL) ||
26303 (vctxt->inode->decl->value == NULL)))
26304 return (0);
26305
26306 if (vctxt->inode->value == NULL) {
26307 /*
26308 * Set the value.
26309 */
26310 switch (mode) {
26311 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26312 /*
26313 * When working on a tree.
26314 */
26315 vctxt->inode->value = value;
26316 break;
26317 case XML_SCHEMA_PUSH_TEXT_CREATED:
26318 /*
26319 * When working with the reader.
26320 * The value will be freed by the element info.
26321 */
26322 vctxt->inode->value = value;
26323 if (consumed != NULL)
26324 *consumed = 1;
26325 vctxt->inode->flags |=
26326 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26327 break;
26328 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26329 /*
26330 * When working with SAX.
26331 * The value will be freed by the element info.
26332 */
26333 if (len != -1)
26334 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26335 else
26336 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26337 vctxt->inode->flags |=
26338 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26339 break;
26340 default:
26341 break;
26342 }
26343 } else {
26344 /*
26345 * Concat the value.
26346 */
26347 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026348 vctxt->inode->value = BAD_CAST xmlStrncat(
26349 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026350 } else {
26351 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026352 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026353 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26354 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026355 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026356
26357 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026358}
26359
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026360static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026361xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026362{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026363 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026364
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026365 if ((vctxt->skipDepth != -1) &&
26366 (vctxt->depth >= vctxt->skipDepth)) {
26367 VERROR_INT("xmlSchemaValidateElem",
26368 "in skip-state");
26369 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026370 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026371 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026372 /*
26373 * URGENT TODO: Better to fully stop validation
26374 * if there was an error during dynamic schema construction.
26375 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026376 if (xmlSchemaAssembleByXSI(vctxt) == -1)
26377 goto internal_error;
26378 }
26379 if (vctxt->depth > 0) {
26380 /*
26381 * Validate this element against the content model
26382 * of the parent.
26383 */
26384 ret = xmlSchemaValidateChildElem(vctxt);
26385 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026386 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026387 VERROR_INT("xmlSchemaValidateElem",
26388 "calling xmlSchemaStreamValidateChildElement()");
26389 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026390 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026391 goto exit;
26392 }
26393 if (vctxt->depth == vctxt->skipDepth)
26394 goto exit;
26395 if ((vctxt->inode->decl == NULL) &&
26396 (vctxt->inode->typeDef == NULL)) {
26397 VERROR_INT("xmlSchemaValidateElem",
26398 "the child element was valid but neither the "
26399 "declaration nor the type was set");
26400 goto internal_error;
26401 }
26402 } else {
26403 /*
26404 * Get the declaration of the validation root.
26405 */
26406 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26407 vctxt->inode->localName,
26408 vctxt->inode->nsName);
26409 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026410 ret = XML_SCHEMAV_CVC_ELT_1;
26411 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026412 "No matching global declaration available "
26413 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026414 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026415 }
26416 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026417
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026418 if (vctxt->inode->decl == NULL)
26419 goto type_validation;
26420
26421 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26422 int skip;
26423 /*
26424 * Wildcards.
26425 */
26426 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26427 if (ret != 0) {
26428 if (ret < 0) {
26429 VERROR_INT("xmlSchemaValidateElem",
26430 "calling xmlSchemaValidateElemWildcard()");
26431 goto internal_error;
26432 }
26433 goto exit;
26434 }
26435 if (skip) {
26436 vctxt->skipDepth = vctxt->depth;
26437 goto exit;
26438 }
26439 /*
26440 * The declaration might be set by the wildcard validation,
26441 * when the processContents is "lax" or "strict".
26442 */
26443 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26444 /*
26445 * Clear the "decl" field to not confuse further processing.
26446 */
26447 vctxt->inode->decl = NULL;
26448 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026449 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026450 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026451 /*
26452 * Validate against the declaration.
26453 */
26454 ret = xmlSchemaValidateElemDecl(vctxt);
26455 if (ret != 0) {
26456 if (ret < 0) {
26457 VERROR_INT("xmlSchemaValidateElem",
26458 "calling xmlSchemaValidateElemDecl()");
26459 goto internal_error;
26460 }
26461 goto exit;
26462 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026463 /*
26464 * Validate against the type definition.
26465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026466type_validation:
26467
26468 if (vctxt->inode->typeDef == NULL) {
26469 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26470 ret = XML_SCHEMAV_CVC_TYPE_1;
26471 VERROR(ret, NULL,
26472 "The type definition is absent");
26473 goto exit;
26474 }
26475 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26476 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26477 ret = XML_SCHEMAV_CVC_TYPE_2;
26478 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026479 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026480 goto exit;
26481 }
26482 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026483 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026484 * during validation against the declaration. This must be done
26485 * _before_ attribute validation.
26486 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026487 if (vctxt->xpathStates != NULL) {
26488 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026489 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026490 if (ret == -1) {
26491 VERROR_INT("xmlSchemaValidateElem",
26492 "calling xmlSchemaXPathEvaluate()");
26493 goto internal_error;
26494 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026495 }
26496 /*
26497 * Validate attributes.
26498 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026499 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026500 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026501 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026502
26503 ret = xmlSchemaVAttributesComplex(vctxt);
26504 }
26505 } else if (vctxt->nbAttrInfos != 0) {
26506
26507 ret = xmlSchemaVAttributesSimple(vctxt);
26508 }
26509 /*
26510 * Clear registered attributes.
26511 */
26512 if (vctxt->nbAttrInfos != 0)
26513 xmlSchemaClearAttrInfos(vctxt);
26514 if (ret == -1) {
26515 VERROR_INT("xmlSchemaValidateElem",
26516 "calling attributes validation");
26517 goto internal_error;
26518 }
26519 /*
26520 * Don't return an error if attributes are invalid on purpose.
26521 */
26522 ret = 0;
26523
26524exit:
26525 if (ret != 0)
26526 vctxt->skipDepth = vctxt->depth;
26527 return (ret);
26528internal_error:
26529 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026530}
26531
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026532#ifdef XML_SCHEMA_READER_ENABLED
26533static int
26534xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026535{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026536 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26537 int depth, nodeType, ret = 0, consumed;
26538 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026539
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026540 vctxt->depth = -1;
26541 ret = xmlTextReaderRead(vctxt->reader);
26542 /*
26543 * Move to the document element.
26544 */
26545 while (ret == 1) {
26546 nodeType = xmlTextReaderNodeType(vctxt->reader);
26547 if (nodeType == XML_ELEMENT_NODE)
26548 goto root_found;
26549 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026550 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026551 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026552
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026553root_found:
26554
26555 do {
26556 depth = xmlTextReaderDepth(vctxt->reader);
26557 nodeType = xmlTextReaderNodeType(vctxt->reader);
26558
26559 if (nodeType == XML_ELEMENT_NODE) {
26560
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026561 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026562 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26563 VERROR_INT("xmlSchemaVReaderWalk",
26564 "calling xmlSchemaValidatorPushElem()");
26565 goto internal_error;
26566 }
26567 ielem = vctxt->inode;
26568 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26569 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26570 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26571 /*
26572 * Is the element empty?
26573 */
26574 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26575 if (ret == -1) {
26576 VERROR_INT("xmlSchemaVReaderWalk",
26577 "calling xmlTextReaderIsEmptyElement()");
26578 goto internal_error;
26579 }
26580 if (ret) {
26581 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26582 }
26583 /*
26584 * Register attributes.
26585 */
26586 vctxt->nbAttrInfos = 0;
26587 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26588 if (ret == -1) {
26589 VERROR_INT("xmlSchemaVReaderWalk",
26590 "calling xmlTextReaderMoveToFirstAttribute()");
26591 goto internal_error;
26592 }
26593 if (ret == 1) {
26594 do {
26595 /*
26596 * VAL TODO: How do we know that the reader works on a
26597 * node tree, to be able to pass a node here?
26598 */
26599 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26600 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26601 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26602 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26603
26604 VERROR_INT("xmlSchemaVReaderWalk",
26605 "calling xmlSchemaValidatorPushAttribute()");
26606 goto internal_error;
26607 }
26608 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26609 if (ret == -1) {
26610 VERROR_INT("xmlSchemaVReaderWalk",
26611 "calling xmlTextReaderMoveToFirstAttribute()");
26612 goto internal_error;
26613 }
26614 } while (ret == 1);
26615 /*
26616 * Back to element position.
26617 */
26618 ret = xmlTextReaderMoveToElement(vctxt->reader);
26619 if (ret == -1) {
26620 VERROR_INT("xmlSchemaVReaderWalk",
26621 "calling xmlTextReaderMoveToElement()");
26622 goto internal_error;
26623 }
26624 }
26625 /*
26626 * Validate the element.
26627 */
26628 ret= xmlSchemaValidateElem(vctxt);
26629 if (ret != 0) {
26630 if (ret == -1) {
26631 VERROR_INT("xmlSchemaVReaderWalk",
26632 "calling xmlSchemaValidateElem()");
26633 goto internal_error;
26634 }
26635 goto exit;
26636 }
26637 if (vctxt->depth == vctxt->skipDepth) {
26638 int curDepth;
26639 /*
26640 * Skip all content.
26641 */
26642 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26643 ret = xmlTextReaderRead(vctxt->reader);
26644 curDepth = xmlTextReaderDepth(vctxt->reader);
26645 while ((ret == 1) && (curDepth != depth)) {
26646 ret = xmlTextReaderRead(vctxt->reader);
26647 curDepth = xmlTextReaderDepth(vctxt->reader);
26648 }
26649 if (ret < 0) {
26650 /*
26651 * VAL TODO: A reader error occured; what to do here?
26652 */
26653 ret = 1;
26654 goto exit;
26655 }
26656 }
26657 goto leave_elem;
26658 }
26659 /*
26660 * READER VAL TODO: Is an END_ELEM really never called
26661 * if the elem is empty?
26662 */
26663 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26664 goto leave_elem;
26665 } else if (nodeType == END_ELEM) {
26666 /*
26667 * Process END of element.
26668 */
26669leave_elem:
26670 ret = xmlSchemaValidatorPopElem(vctxt);
26671 if (ret != 0) {
26672 if (ret < 0) {
26673 VERROR_INT("xmlSchemaVReaderWalk",
26674 "calling xmlSchemaValidatorPopElem()");
26675 goto internal_error;
26676 }
26677 goto exit;
26678 }
26679 if (vctxt->depth >= 0)
26680 ielem = vctxt->inode;
26681 else
26682 ielem = NULL;
26683 } else if ((nodeType == XML_TEXT_NODE) ||
26684 (nodeType == XML_CDATA_SECTION_NODE) ||
26685 (nodeType == WHTSP) ||
26686 (nodeType == SIGN_WHTSP)) {
26687 /*
26688 * Process character content.
26689 */
26690 xmlChar *value;
26691
26692 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26693 nodeType = XML_TEXT_NODE;
26694
26695 value = xmlTextReaderValue(vctxt->reader);
26696 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26697 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26698 if (! consumed)
26699 xmlFree(value);
26700 if (ret == -1) {
26701 VERROR_INT("xmlSchemaVReaderWalk",
26702 "calling xmlSchemaVPushText()");
26703 goto internal_error;
26704 }
26705 } else if ((nodeType == XML_ENTITY_NODE) ||
26706 (nodeType == XML_ENTITY_REF_NODE)) {
26707 /*
26708 * VAL TODO: What to do with entities?
26709 */
26710 TODO
26711 }
26712 /*
26713 * Read next node.
26714 */
26715 ret = xmlTextReaderRead(vctxt->reader);
26716 } while (ret == 1);
26717
26718exit:
26719 return (ret);
26720internal_error:
26721 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026722}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026723#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026724
26725/************************************************************************
26726 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026727 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026728 * *
26729 ************************************************************************/
26730
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026731/*
26732* Process text content.
26733*/
26734static void
26735xmlSchemaSAXHandleText(void *ctx,
26736 const xmlChar * ch,
26737 int len)
26738{
26739 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26740
26741 if (vctxt->depth < 0)
26742 return;
26743 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26744 return;
26745 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26746 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26747 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26748 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26749 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26750 "calling xmlSchemaVPushText()");
26751 vctxt->err = -1;
26752 xmlStopParser(vctxt->parserCtxt);
26753 }
26754}
26755
26756/*
26757* Process CDATA content.
26758*/
26759static void
26760xmlSchemaSAXHandleCDataSection(void *ctx,
26761 const xmlChar * ch,
26762 int len)
26763{
26764 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26765
26766 if (vctxt->depth < 0)
26767 return;
26768 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26769 return;
26770 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26771 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26772 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26773 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26774 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26775 "calling xmlSchemaVPushText()");
26776 vctxt->err = -1;
26777 xmlStopParser(vctxt->parserCtxt);
26778 }
26779}
26780
26781static void
26782xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26783 const xmlChar * name ATTRIBUTE_UNUSED)
26784{
26785 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26786
26787 if (vctxt->depth < 0)
26788 return;
26789 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26790 return;
26791 /* SAX VAL TODO: What to do here? */
26792 TODO
26793}
26794
26795static void
26796xmlSchemaSAXHandleStartElementNs(void *ctx,
26797 const xmlChar * localname,
26798 const xmlChar * prefix ATTRIBUTE_UNUSED,
26799 const xmlChar * URI,
26800 int nb_namespaces,
26801 const xmlChar ** namespaces,
26802 int nb_attributes,
26803 int nb_defaulted ATTRIBUTE_UNUSED,
26804 const xmlChar ** attributes)
26805{
26806 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26807 int ret;
26808 xmlSchemaNodeInfoPtr ielem;
26809 int i, j;
26810
26811 /*
26812 * SAX VAL TODO: What to do with nb_defaulted?
26813 */
26814 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026815 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026816 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026817 vctxt->depth++;
26818 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026819 return;
26820 /*
26821 * Push the element.
26822 */
26823 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26824 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26825 "calling xmlSchemaValidatorPushElem()");
26826 goto internal_error;
26827 }
26828 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026829 /*
26830 * TODO: Is this OK?
26831 */
26832 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026833 ielem->localName = localname;
26834 ielem->nsName = URI;
26835 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26836 /*
26837 * Register namespaces on the elem info.
26838 */
26839 if (nb_namespaces != 0) {
26840 /*
26841 * Although the parser builds its own namespace list,
26842 * we have no access to it, so we'll use an own one.
26843 */
26844 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26845 /*
26846 * Store prefix and namespace name.
26847 */
26848 if (ielem->nsBindings == NULL) {
26849 ielem->nsBindings =
26850 (const xmlChar **) xmlMalloc(10 *
26851 sizeof(const xmlChar *));
26852 if (ielem->nsBindings == NULL) {
26853 xmlSchemaVErrMemory(vctxt,
26854 "allocating namespace bindings for SAX validation",
26855 NULL);
26856 goto internal_error;
26857 }
26858 ielem->nbNsBindings = 0;
26859 ielem->sizeNsBindings = 5;
26860 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26861 ielem->sizeNsBindings *= 2;
26862 ielem->nsBindings =
26863 (const xmlChar **) xmlRealloc(
26864 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026865 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026866 if (ielem->nsBindings == NULL) {
26867 xmlSchemaVErrMemory(vctxt,
26868 "re-allocating namespace bindings for SAX validation",
26869 NULL);
26870 goto internal_error;
26871 }
26872 }
26873
26874 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26875 if (namespaces[j+1][0] == 0) {
26876 /*
26877 * Handle xmlns="".
26878 */
26879 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26880 } else
26881 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26882 namespaces[j+1];
26883 ielem->nbNsBindings++;
26884 }
26885 }
26886 /*
26887 * Register attributes.
26888 * SAX VAL TODO: We are not adding namespace declaration
26889 * attributes yet.
26890 */
26891 if (nb_attributes != 0) {
26892 xmlChar *value;
26893
26894 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26895 /*
26896 * Duplicate the value.
26897 */
26898 value = xmlStrndup(attributes[j+3],
26899 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026900 /*
26901 * TODO: Set the node line.
26902 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026903 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026904 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026905 value, 1);
26906 if (ret == -1) {
26907 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26908 "calling xmlSchemaValidatorPushAttribute()");
26909 goto internal_error;
26910 }
26911 }
26912 }
26913 /*
26914 * Validate the element.
26915 */
26916 ret = xmlSchemaValidateElem(vctxt);
26917 if (ret != 0) {
26918 if (ret == -1) {
26919 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26920 "calling xmlSchemaValidateElem()");
26921 goto internal_error;
26922 }
26923 goto exit;
26924 }
26925
26926exit:
26927 return;
26928internal_error:
26929 vctxt->err = -1;
26930 xmlStopParser(vctxt->parserCtxt);
26931 return;
26932}
26933
26934static void
26935xmlSchemaSAXHandleEndElementNs(void *ctx,
26936 const xmlChar * localname ATTRIBUTE_UNUSED,
26937 const xmlChar * prefix ATTRIBUTE_UNUSED,
26938 const xmlChar * URI ATTRIBUTE_UNUSED)
26939{
26940 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26941 int res;
26942
26943 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026944 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026945 */
26946 if (vctxt->skipDepth != -1) {
26947 if (vctxt->depth > vctxt->skipDepth) {
26948 vctxt->depth--;
26949 return;
26950 } else
26951 vctxt->skipDepth = -1;
26952 }
26953 /*
26954 * SAX VAL TODO: Just a temporary check.
26955 */
26956 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26957 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26958 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26959 "elem pop mismatch");
26960 }
26961 res = xmlSchemaValidatorPopElem(vctxt);
26962 if (res != 0) {
26963 if (res < 0) {
26964 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26965 "calling xmlSchemaValidatorPopElem()");
26966 goto internal_error;
26967 }
26968 goto exit;
26969 }
26970exit:
26971 return;
26972internal_error:
26973 vctxt->err = -1;
26974 xmlStopParser(vctxt->parserCtxt);
26975 return;
26976}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026977
Daniel Veillard4255d502002-04-16 15:50:10 +000026978/************************************************************************
26979 * *
26980 * Validation interfaces *
26981 * *
26982 ************************************************************************/
26983
26984/**
26985 * xmlSchemaNewValidCtxt:
26986 * @schema: a precompiled XML Schemas
26987 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026988 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026989 *
26990 * Returns the validation context or NULL in case of error
26991 */
26992xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026993xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
26994{
Daniel Veillard4255d502002-04-16 15:50:10 +000026995 xmlSchemaValidCtxtPtr ret;
26996
26997 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
26998 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026999 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027000 return (NULL);
27001 }
27002 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027003 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027004 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027005 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027006 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027007 return (ret);
27008}
27009
27010/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027011 * xmlSchemaClearValidCtxt:
27012 * @ctxt: the schema validation context
27013 *
27014 * Free the resources associated to the schema validation context;
27015 * leaves some fields alive intended for reuse of the context.
27016 */
27017static void
27018xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27019{
27020 if (vctxt == NULL)
27021 return;
27022
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027023 /*
27024 * TODO: Should we clear the flags?
27025 * Might be problematic if one reuses the context
27026 * and assumes that the options remain the same.
27027 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027028 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027029 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027030 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027031#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027032 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027033#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027034 vctxt->hasKeyrefs = 0;
27035
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027036 if (vctxt->value != NULL) {
27037 xmlSchemaFreeValue(vctxt->value);
27038 vctxt->value = NULL;
27039 }
27040 /*
27041 * Augmented IDC information.
27042 */
27043 if (vctxt->aidcs != NULL) {
27044 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27045 do {
27046 next = cur->next;
27047 xmlFree(cur);
27048 cur = next;
27049 } while (cur != NULL);
27050 vctxt->aidcs = NULL;
27051 }
27052 if (vctxt->idcNodes != NULL) {
27053 int i;
27054 xmlSchemaPSVIIDCNodePtr item;
27055
27056 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027057 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027058 xmlFree(item->keys);
27059 xmlFree(item);
27060 }
27061 xmlFree(vctxt->idcNodes);
27062 vctxt->idcNodes = NULL;
27063 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027064 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027065 * Note that we won't delete the XPath state pool here.
27066 */
27067 if (vctxt->xpathStates != NULL) {
27068 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27069 vctxt->xpathStates = NULL;
27070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027071 /*
27072 * Attribute info.
27073 */
27074 if (vctxt->nbAttrInfos != 0) {
27075 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027077 /*
27078 * Element info.
27079 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027080 if (vctxt->elemInfos != NULL) {
27081 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027082 xmlSchemaNodeInfoPtr ei;
27083
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027084 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027085 ei = vctxt->elemInfos[i];
27086 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027087 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027088 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027089 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027090 }
27091 xmlSchemaItemListClear(vctxt->nodeQNames);
27092 /* Recreate the dict. */
27093 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027094 /*
27095 * TODO: Is is save to recreate it? Do we have a scenario
27096 * where the user provides the dict?
27097 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027098 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027099}
27100
27101/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027102 * xmlSchemaFreeValidCtxt:
27103 * @ctxt: the schema validation context
27104 *
27105 * Free the resources associated to the schema validation context
27106 */
27107void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027108xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27109{
Daniel Veillard4255d502002-04-16 15:50:10 +000027110 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027111 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027112 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027113 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027114 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027115 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027116 if (ctxt->idcNodes != NULL) {
27117 int i;
27118 xmlSchemaPSVIIDCNodePtr item;
27119
27120 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027121 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027122 xmlFree(item->keys);
27123 xmlFree(item);
27124 }
27125 xmlFree(ctxt->idcNodes);
27126 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027127 if (ctxt->idcKeys != NULL) {
27128 int i;
27129 for (i = 0; i < ctxt->nbIdcKeys; i++)
27130 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27131 xmlFree(ctxt->idcKeys);
27132 }
27133
27134 if (ctxt->xpathStates != NULL)
27135 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27136 if (ctxt->xpathStatePool != NULL)
27137 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27138
27139 /*
27140 * Augmented IDC information.
27141 */
27142 if (ctxt->aidcs != NULL) {
27143 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27144 do {
27145 next = cur->next;
27146 xmlFree(cur);
27147 cur = next;
27148 } while (cur != NULL);
27149 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027150 if (ctxt->attrInfos != NULL) {
27151 int i;
27152 xmlSchemaAttrInfoPtr attr;
27153
27154 /* Just a paranoid call to the cleanup. */
27155 if (ctxt->nbAttrInfos != 0)
27156 xmlSchemaClearAttrInfos(ctxt);
27157 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27158 attr = ctxt->attrInfos[i];
27159 xmlFree(attr);
27160 }
27161 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027162 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027163 if (ctxt->elemInfos != NULL) {
27164 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027165 xmlSchemaNodeInfoPtr ei;
27166
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027167 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027168 ei = ctxt->elemInfos[i];
27169 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027170 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027171 xmlSchemaClearElemInfo(ei);
27172 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027173 }
27174 xmlFree(ctxt->elemInfos);
27175 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027176 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027177 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027178 if (ctxt->dict != NULL)
27179 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000027180 xmlFree(ctxt);
27181}
27182
27183/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027184 * xmlSchemaIsValid:
27185 * @ctxt: the schema validation context
27186 *
27187 * Check if any error was detected during validation.
27188 *
27189 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27190 * of internal error.
27191 */
27192int
27193xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27194{
27195 if (ctxt == NULL)
27196 return(-1);
27197 return(ctxt->err == 0);
27198}
27199
27200/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027201 * xmlSchemaSetValidErrors:
27202 * @ctxt: a schema validation context
27203 * @err: the error function
27204 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027205 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027206 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027207 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027208 */
27209void
27210xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027211 xmlSchemaValidityErrorFunc err,
27212 xmlSchemaValidityWarningFunc warn, void *ctx)
27213{
Daniel Veillard4255d502002-04-16 15:50:10 +000027214 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027215 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027216 ctxt->error = err;
27217 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027218 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027219 if (ctxt->pctxt != NULL)
27220 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027221}
27222
27223/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027224 * xmlSchemaSetValidStructuredErrors:
27225 * @ctxt: a schema validation context
27226 * @serror: the structured error function
27227 * @ctx: the functions context
27228 *
27229 * Set the structured error callback
27230 */
27231void
27232xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027233 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027234{
27235 if (ctxt == NULL)
27236 return;
27237 ctxt->serror = serror;
27238 ctxt->error = NULL;
27239 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027240 ctxt->errCtxt = ctx;
27241 if (ctxt->pctxt != NULL)
27242 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027243}
27244
27245/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027246 * xmlSchemaGetValidErrors:
27247 * @ctxt: a XML-Schema validation context
27248 * @err: the error function result
27249 * @warn: the warning function result
27250 * @ctx: the functions context result
27251 *
27252 * Get the error and warning callback informations
27253 *
27254 * Returns -1 in case of error and 0 otherwise
27255 */
27256int
27257xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027258 xmlSchemaValidityErrorFunc * err,
27259 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027260{
27261 if (ctxt == NULL)
27262 return (-1);
27263 if (err != NULL)
27264 *err = ctxt->error;
27265 if (warn != NULL)
27266 *warn = ctxt->warning;
27267 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027268 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027269 return (0);
27270}
27271
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027272
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027273/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027274 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027275 * @ctxt: a schema validation context
27276 * @options: a combination of xmlSchemaValidOption
27277 *
27278 * Sets the options to be used during the validation.
27279 *
27280 * Returns 0 in case of success, -1 in case of an
27281 * API error.
27282 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027283int
27284xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27285 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027286
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027287{
27288 int i;
27289
27290 if (ctxt == NULL)
27291 return (-1);
27292 /*
27293 * WARNING: Change the start value if adding to the
27294 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027295 * TODO: Is there an other, more easy to maintain,
27296 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027297 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027298 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027299 if (options & 1<<i)
27300 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027301 }
27302 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027303 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027304}
27305
27306/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027307 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027308 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027309 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027310 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027311 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027312 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027313 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027314int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027315xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027316
27317{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027318 if (ctxt == NULL)
27319 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027320 else
27321 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027322}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027323
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027324static int
27325xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27326{
27327 xmlAttrPtr attr;
27328 int ret = 0;
27329 xmlSchemaNodeInfoPtr ielem = NULL;
27330 xmlNodePtr node, valRoot;
27331 const xmlChar *nsName;
27332
27333 /* DOC VAL TODO: Move this to the start function. */
27334 valRoot = xmlDocGetRootElement(vctxt->doc);
27335 if (valRoot == NULL) {
27336 /* VAL TODO: Error code? */
27337 VERROR(1, NULL, "The document has no document element");
27338 return (1);
27339 }
27340 vctxt->depth = -1;
27341 vctxt->validationRoot = valRoot;
27342 node = valRoot;
27343 while (node != NULL) {
27344 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27345 goto next_sibling;
27346 if (node->type == XML_ELEMENT_NODE) {
27347
27348 /*
27349 * Init the node-info.
27350 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027351 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027352 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27353 goto internal_error;
27354 ielem = vctxt->inode;
27355 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027356 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027357 ielem->localName = node->name;
27358 if (node->ns != NULL)
27359 ielem->nsName = node->ns->href;
27360 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27361 /*
27362 * Register attributes.
27363 * DOC VAL TODO: We do not register namespace declaration
27364 * attributes yet.
27365 */
27366 vctxt->nbAttrInfos = 0;
27367 if (node->properties != NULL) {
27368 attr = node->properties;
27369 do {
27370 if (attr->ns != NULL)
27371 nsName = attr->ns->href;
27372 else
27373 nsName = NULL;
27374 ret = xmlSchemaValidatorPushAttribute(vctxt,
27375 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027376 /*
27377 * Note that we give it the line number of the
27378 * parent element.
27379 */
27380 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027381 attr->name, nsName, 0,
27382 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27383 if (ret == -1) {
27384 VERROR_INT("xmlSchemaDocWalk",
27385 "calling xmlSchemaValidatorPushAttribute()");
27386 goto internal_error;
27387 }
27388 attr = attr->next;
27389 } while (attr);
27390 }
27391 /*
27392 * Validate the element.
27393 */
27394 ret = xmlSchemaValidateElem(vctxt);
27395 if (ret != 0) {
27396 if (ret == -1) {
27397 VERROR_INT("xmlSchemaDocWalk",
27398 "calling xmlSchemaValidateElem()");
27399 goto internal_error;
27400 }
27401 /*
27402 * Don't stop validation; just skip the content
27403 * of this element.
27404 */
27405 goto leave_node;
27406 }
27407 if ((vctxt->skipDepth != -1) &&
27408 (vctxt->depth >= vctxt->skipDepth))
27409 goto leave_node;
27410 } else if ((node->type == XML_TEXT_NODE) ||
27411 (node->type == XML_CDATA_SECTION_NODE)) {
27412 /*
27413 * Process character content.
27414 */
27415 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27416 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27417 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27418 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27419 if (ret < 0) {
27420 VERROR_INT("xmlSchemaVDocWalk",
27421 "calling xmlSchemaVPushText()");
27422 goto internal_error;
27423 }
27424 /*
27425 * DOC VAL TODO: Should we skip further validation of the
27426 * element content here?
27427 */
27428 } else if ((node->type == XML_ENTITY_NODE) ||
27429 (node->type == XML_ENTITY_REF_NODE)) {
27430 /*
27431 * DOC VAL TODO: What to do with entities?
27432 */
27433 TODO
27434 } else {
27435 goto leave_node;
27436 /*
27437 * DOC VAL TODO: XInclude nodes, etc.
27438 */
27439 }
27440 /*
27441 * Walk the doc.
27442 */
27443 if (node->children != NULL) {
27444 node = node->children;
27445 continue;
27446 }
27447leave_node:
27448 if (node->type == XML_ELEMENT_NODE) {
27449 /*
27450 * Leaving the scope of an element.
27451 */
27452 if (node != vctxt->inode->node) {
27453 VERROR_INT("xmlSchemaVDocWalk",
27454 "element position mismatch");
27455 goto internal_error;
27456 }
27457 ret = xmlSchemaValidatorPopElem(vctxt);
27458 if (ret != 0) {
27459 if (ret < 0) {
27460 VERROR_INT("xmlSchemaVDocWalk",
27461 "calling xmlSchemaValidatorPopElem()");
27462 goto internal_error;
27463 }
27464 }
27465 if (node == valRoot)
27466 goto exit;
27467 }
27468next_sibling:
27469 if (node->next != NULL)
27470 node = node->next;
27471 else {
27472 node = node->parent;
27473 goto leave_node;
27474 }
27475 }
27476
27477exit:
27478 return (ret);
27479internal_error:
27480 return (-1);
27481}
27482
27483static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000027484xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027485 /*
27486 * Some initialization.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027488 vctxt->err = 0;
27489 vctxt->nberrors = 0;
27490 vctxt->depth = -1;
27491 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027492 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027493 vctxt->hasKeyrefs = 0;
27494#ifdef ENABLE_IDC_NODE_TABLES
27495 vctxt->createIDCNodeTables = 1;
27496#else
27497 vctxt->createIDCNodeTables = 0;
27498#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027499 /*
27500 * Create a schema + parser if necessary.
27501 */
27502 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027503 xmlSchemaParserCtxtPtr pctxt;
27504
27505 vctxt->xsiAssemble = 1;
27506 /*
27507 * If not schema was given then we will create a schema
27508 * dynamically using XSI schema locations.
27509 *
27510 * Create the schema parser context.
27511 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027512 if ((vctxt->pctxt == NULL) &&
27513 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27514 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027515 pctxt = vctxt->pctxt;
27516 pctxt->xsiAssemble = 1;
27517 /*
27518 * Create the schema.
27519 */
27520 vctxt->schema = xmlSchemaNewSchema(pctxt);
27521 if (vctxt->schema == NULL)
27522 return (-1);
27523 /*
27524 * Create the schema construction context.
27525 */
27526 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27527 if (pctxt->constructor == NULL)
27528 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027529 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027530 /*
27531 * Take ownership of the constructor to be able to free it.
27532 */
27533 pctxt->ownsConstructor = 1;
27534 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027535 /*
27536 * Augment the IDC definitions.
27537 */
27538 if (vctxt->schema->idcDef != NULL) {
27539 xmlHashScan(vctxt->schema->idcDef,
27540 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27541 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000027542 return(0);
27543}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027544
Daniel Veillardf10ae122005-07-10 19:03:16 +000027545static void
27546xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027547 if (vctxt->xsiAssemble) {
27548 if (vctxt->schema != NULL) {
27549 xmlSchemaFree(vctxt->schema);
27550 vctxt->schema = NULL;
27551 }
27552 }
27553 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027554}
27555
27556static int
27557xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27558{
27559 int ret = 0;
27560
27561 if (xmlSchemaPreRun(vctxt) < 0)
27562 return(-1);
27563
27564 if (vctxt->doc != NULL) {
27565 /*
27566 * Tree validation.
27567 */
27568 ret = xmlSchemaVDocWalk(vctxt);
27569#ifdef LIBXML_READER_ENABLED
27570 } else if (vctxt->reader != NULL) {
27571 /*
27572 * XML Reader validation.
27573 */
27574#ifdef XML_SCHEMA_READER_ENABLED
27575 ret = xmlSchemaVReaderWalk(vctxt);
27576#endif
27577#endif
27578 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27579 /*
27580 * SAX validation.
27581 */
27582 ret = xmlParseDocument(vctxt->parserCtxt);
27583 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027584 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027585 "no instance to validate");
27586 ret = -1;
27587 }
27588
27589 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027590 if (ret == 0)
27591 ret = vctxt->err;
27592 return (ret);
27593}
27594
27595/**
27596 * xmlSchemaValidateOneElement:
27597 * @ctxt: a schema validation context
27598 * @elem: an element node
27599 *
27600 * Validate a branch of a tree, starting with the given @elem.
27601 *
27602 * Returns 0 if the element and its subtree is valid, a positive error
27603 * code number otherwise and -1 in case of an internal or API error.
27604 */
27605int
27606xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27607{
27608 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27609 return (-1);
27610
27611 if (ctxt->schema == NULL)
27612 return (-1);
27613
27614 ctxt->doc = elem->doc;
27615 ctxt->node = elem;
27616 ctxt->validationRoot = elem;
27617 return(xmlSchemaVStart(ctxt));
27618}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027619
Daniel Veillard259f0df2004-08-18 09:13:18 +000027620/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027621 * xmlSchemaValidateDoc:
27622 * @ctxt: a schema validation context
27623 * @doc: a parsed document tree
27624 *
27625 * Validate a document tree in memory.
27626 *
27627 * Returns 0 if the document is schemas valid, a positive error code
27628 * number otherwise and -1 in case of internal or API error.
27629 */
27630int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027631xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27632{
Daniel Veillard4255d502002-04-16 15:50:10 +000027633 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027634 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027635
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027636 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027637 ctxt->node = xmlDocGetRootElement(doc);
27638 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027639 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027640 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27641 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027642 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027643 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027644 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027645 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027646 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027647}
27648
Daniel Veillardcdc82732005-07-08 15:04:06 +000027649
27650/************************************************************************
27651 * *
27652 * Function and data for SAX streaming API *
27653 * *
27654 ************************************************************************/
27655typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27656typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27657
27658struct _xmlSchemaSplitSAXData {
27659 xmlSAXHandlerPtr user_sax;
27660 void *user_data;
27661 xmlSchemaValidCtxtPtr ctxt;
27662 xmlSAXHandlerPtr schemas_sax;
27663};
27664
Daniel Veillard971771e2005-07-09 17:32:57 +000027665#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27666
27667struct _xmlSchemaSAXPlug {
27668 unsigned int magic;
27669
27670 /* the original callbacks informations */
27671 xmlSAXHandlerPtr *user_sax_ptr;
27672 xmlSAXHandlerPtr user_sax;
27673 void **user_data_ptr;
27674 void *user_data;
27675
27676 /* the block plugged back and validation informations */
27677 xmlSAXHandler schemas_sax;
27678 xmlSchemaValidCtxtPtr ctxt;
27679};
27680
Daniel Veillardcdc82732005-07-08 15:04:06 +000027681/* All those functions just bounces to the user provided SAX handlers */
27682static void
27683internalSubsetSplit(void *ctx, const xmlChar *name,
27684 const xmlChar *ExternalID, const xmlChar *SystemID)
27685{
Daniel Veillard971771e2005-07-09 17:32:57 +000027686 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027687 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27688 (ctxt->user_sax->internalSubset != NULL))
27689 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27690 SystemID);
27691}
27692
27693static int
27694isStandaloneSplit(void *ctx)
27695{
Daniel Veillard971771e2005-07-09 17:32:57 +000027696 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027697 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27698 (ctxt->user_sax->isStandalone != NULL))
27699 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27700 return(0);
27701}
27702
27703static int
27704hasInternalSubsetSplit(void *ctx)
27705{
Daniel Veillard971771e2005-07-09 17:32:57 +000027706 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027707 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27708 (ctxt->user_sax->hasInternalSubset != NULL))
27709 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27710 return(0);
27711}
27712
27713static int
27714hasExternalSubsetSplit(void *ctx)
27715{
Daniel Veillard971771e2005-07-09 17:32:57 +000027716 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027717 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27718 (ctxt->user_sax->hasExternalSubset != NULL))
27719 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27720 return(0);
27721}
27722
27723static void
27724externalSubsetSplit(void *ctx, const xmlChar *name,
27725 const xmlChar *ExternalID, const xmlChar *SystemID)
27726{
Daniel Veillard971771e2005-07-09 17:32:57 +000027727 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027728 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27729 (ctxt->user_sax->internalSubset != NULL))
27730 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27731 SystemID);
27732}
27733
27734static xmlParserInputPtr
27735resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27736{
Daniel Veillard971771e2005-07-09 17:32:57 +000027737 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027738 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27739 (ctxt->user_sax->resolveEntity != NULL))
27740 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27741 systemId));
27742 return(NULL);
27743}
27744
27745static xmlEntityPtr
27746getEntitySplit(void *ctx, const xmlChar *name)
27747{
Daniel Veillard971771e2005-07-09 17:32:57 +000027748 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027749 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27750 (ctxt->user_sax->getEntity != NULL))
27751 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27752 return(NULL);
27753}
27754
27755static xmlEntityPtr
27756getParameterEntitySplit(void *ctx, const xmlChar *name)
27757{
Daniel Veillard971771e2005-07-09 17:32:57 +000027758 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027759 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27760 (ctxt->user_sax->getParameterEntity != NULL))
27761 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27762 return(NULL);
27763}
27764
27765
27766static void
27767entityDeclSplit(void *ctx, const xmlChar *name, int type,
27768 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27769{
Daniel Veillard971771e2005-07-09 17:32:57 +000027770 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027771 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27772 (ctxt->user_sax->entityDecl != NULL))
27773 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27774 systemId, content);
27775}
27776
27777static void
27778attributeDeclSplit(void *ctx, const xmlChar * elem,
27779 const xmlChar * name, int type, int def,
27780 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27781{
Daniel Veillard971771e2005-07-09 17:32:57 +000027782 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027783 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27784 (ctxt->user_sax->attributeDecl != NULL)) {
27785 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27786 def, defaultValue, tree);
27787 } else {
27788 xmlFreeEnumeration(tree);
27789 }
27790}
27791
27792static void
27793elementDeclSplit(void *ctx, const xmlChar *name, int type,
27794 xmlElementContentPtr content)
27795{
Daniel Veillard971771e2005-07-09 17:32:57 +000027796 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027797 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27798 (ctxt->user_sax->elementDecl != NULL))
27799 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27800}
27801
27802static void
27803notationDeclSplit(void *ctx, const xmlChar *name,
27804 const xmlChar *publicId, const xmlChar *systemId)
27805{
Daniel Veillard971771e2005-07-09 17:32:57 +000027806 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027807 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27808 (ctxt->user_sax->notationDecl != NULL))
27809 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27810 systemId);
27811}
27812
27813static void
27814unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27815 const xmlChar *publicId, const xmlChar *systemId,
27816 const xmlChar *notationName)
27817{
Daniel Veillard971771e2005-07-09 17:32:57 +000027818 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027819 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27820 (ctxt->user_sax->unparsedEntityDecl != NULL))
27821 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27822 systemId, notationName);
27823}
27824
27825static void
27826setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27827{
Daniel Veillard971771e2005-07-09 17:32:57 +000027828 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027829 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27830 (ctxt->user_sax->setDocumentLocator != NULL))
27831 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27832}
27833
27834static void
27835startDocumentSplit(void *ctx)
27836{
Daniel Veillard971771e2005-07-09 17:32:57 +000027837 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027838 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27839 (ctxt->user_sax->startDocument != NULL))
27840 ctxt->user_sax->startDocument(ctxt->user_data);
27841}
27842
27843static void
27844endDocumentSplit(void *ctx)
27845{
Daniel Veillard971771e2005-07-09 17:32:57 +000027846 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027847 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27848 (ctxt->user_sax->endDocument != NULL))
27849 ctxt->user_sax->endDocument(ctxt->user_data);
27850}
27851
27852static void
27853processingInstructionSplit(void *ctx, const xmlChar *target,
27854 const xmlChar *data)
27855{
Daniel Veillard971771e2005-07-09 17:32:57 +000027856 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027857 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27858 (ctxt->user_sax->processingInstruction != NULL))
27859 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27860}
27861
27862static void
27863commentSplit(void *ctx, const xmlChar *value)
27864{
Daniel Veillard971771e2005-07-09 17:32:57 +000027865 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027866 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27867 (ctxt->user_sax->comment != NULL))
27868 ctxt->user_sax->comment(ctxt->user_data, value);
27869}
27870
27871/*
27872 * Varargs error callbacks to the user application, harder ...
27873 */
27874
Daniel Veillardffa3c742005-07-21 13:24:09 +000027875static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027876warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027877 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027878 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27879 (ctxt->user_sax->warning != NULL)) {
27880 TODO
27881 }
27882}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027883static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027884errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027885 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027886 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27887 (ctxt->user_sax->error != NULL)) {
27888 TODO
27889 }
27890}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027891static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027892fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027893 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027894 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27895 (ctxt->user_sax->fatalError != NULL)) {
27896 TODO
27897 }
27898}
27899
27900/*
27901 * Those are function where both the user handler and the schemas handler
27902 * need to be called.
27903 */
27904static void
27905charactersSplit(void *ctx, const xmlChar *ch, int len)
27906{
Daniel Veillard971771e2005-07-09 17:32:57 +000027907 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027908 if (ctxt == NULL)
27909 return;
27910 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27911 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27912 if (ctxt->ctxt != NULL)
27913 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27914}
27915
27916static void
27917ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27918{
Daniel Veillard971771e2005-07-09 17:32:57 +000027919 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027920 if (ctxt == NULL)
27921 return;
27922 if ((ctxt->user_sax != NULL) &&
27923 (ctxt->user_sax->ignorableWhitespace != NULL))
27924 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27925 if (ctxt->ctxt != NULL)
27926 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27927}
27928
27929static void
27930cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27931{
Daniel Veillard971771e2005-07-09 17:32:57 +000027932 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027933 if (ctxt == NULL)
27934 return;
27935 if ((ctxt->user_sax != NULL) &&
27936 (ctxt->user_sax->ignorableWhitespace != NULL))
27937 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27938 if (ctxt->ctxt != NULL)
27939 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27940}
27941
27942static void
27943referenceSplit(void *ctx, const xmlChar *name)
27944{
Daniel Veillard971771e2005-07-09 17:32:57 +000027945 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027946 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27947 (ctxt->user_sax->reference != NULL))
27948 ctxt->user_sax->reference(ctxt->user_data, name);
27949 if (ctxt->ctxt != NULL)
27950 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27951}
27952
27953static void
27954startElementNsSplit(void *ctx, const xmlChar * localname,
27955 const xmlChar * prefix, const xmlChar * URI,
27956 int nb_namespaces, const xmlChar ** namespaces,
27957 int nb_attributes, int nb_defaulted,
27958 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027959 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027960 if (ctxt == NULL)
27961 return;
27962 if ((ctxt->user_sax != NULL) &&
27963 (ctxt->user_sax->startElementNs != NULL))
27964 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27965 URI, nb_namespaces, namespaces,
27966 nb_attributes, nb_defaulted,
27967 attributes);
27968 if (ctxt->ctxt != NULL)
27969 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27970 URI, nb_namespaces, namespaces,
27971 nb_attributes, nb_defaulted,
27972 attributes);
27973}
27974
27975static void
27976endElementNsSplit(void *ctx, const xmlChar * localname,
27977 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027978 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027979 if (ctxt == NULL)
27980 return;
27981 if ((ctxt->user_sax != NULL) &&
27982 (ctxt->user_sax->endElementNs != NULL))
27983 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27984 if (ctxt->ctxt != NULL)
27985 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27986}
27987
Daniel Veillard4255d502002-04-16 15:50:10 +000027988/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027989 * xmlSchemaSAXPlug:
27990 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000027991 * @sax: a pointer to the original xmlSAXHandlerPtr
27992 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000027993 *
27994 * Plug a SAX based validation layer in a SAX parsing event flow.
27995 * The original @saxptr and @dataptr data are replaced by new pointers
27996 * but the calls to the original will be maintained.
27997 *
27998 * Returns a pointer to a data structure needed to unplug the validation layer
27999 * or NULL in case of errors.
28000 */
28001xmlSchemaSAXPlugPtr
28002xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28003 xmlSAXHandlerPtr *sax, void **user_data)
28004{
28005 xmlSchemaSAXPlugPtr ret;
28006 xmlSAXHandlerPtr old_sax;
28007
28008 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28009 return(NULL);
28010
28011 /*
28012 * We only allow to plug into SAX2 event streams
28013 */
28014 old_sax = *sax;
28015 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28016 return(NULL);
28017 if ((old_sax != NULL) &&
28018 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28019 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28020 return(NULL);
28021
28022 /*
28023 * everything seems right allocate the local data needed for that layer
28024 */
28025 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28026 if (ret == NULL) {
28027 return(NULL);
28028 }
28029 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28030 ret->magic = XML_SAX_PLUG_MAGIC;
28031 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28032 ret->ctxt = ctxt;
28033 ret->user_sax_ptr = sax;
28034 ret->user_sax = old_sax;
28035 if (old_sax == NULL) {
28036 /*
28037 * go direct, no need for the split block and functions.
28038 */
28039 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28040 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28041 /*
28042 * Note that we use the same text-function for both, to prevent
28043 * the parser from testing for ignorable whitespace.
28044 */
28045 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28046 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28047
28048 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28049 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28050
28051 ret->user_data = ctxt;
28052 *user_data = ctxt;
28053 } else {
28054 /*
28055 * for each callback unused by Schemas initialize it to the Split
28056 * routine only if non NULL in the user block, this can speed up
28057 * things at the SAX level.
28058 */
28059 if (old_sax->internalSubset != NULL)
28060 ret->schemas_sax.internalSubset = internalSubsetSplit;
28061 if (old_sax->isStandalone != NULL)
28062 ret->schemas_sax.isStandalone = isStandaloneSplit;
28063 if (old_sax->hasInternalSubset != NULL)
28064 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28065 if (old_sax->hasExternalSubset != NULL)
28066 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28067 if (old_sax->resolveEntity != NULL)
28068 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28069 if (old_sax->getEntity != NULL)
28070 ret->schemas_sax.getEntity = getEntitySplit;
28071 if (old_sax->entityDecl != NULL)
28072 ret->schemas_sax.entityDecl = entityDeclSplit;
28073 if (old_sax->notationDecl != NULL)
28074 ret->schemas_sax.notationDecl = notationDeclSplit;
28075 if (old_sax->attributeDecl != NULL)
28076 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28077 if (old_sax->elementDecl != NULL)
28078 ret->schemas_sax.elementDecl = elementDeclSplit;
28079 if (old_sax->unparsedEntityDecl != NULL)
28080 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28081 if (old_sax->setDocumentLocator != NULL)
28082 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28083 if (old_sax->startDocument != NULL)
28084 ret->schemas_sax.startDocument = startDocumentSplit;
28085 if (old_sax->endDocument != NULL)
28086 ret->schemas_sax.endDocument = endDocumentSplit;
28087 if (old_sax->processingInstruction != NULL)
28088 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28089 if (old_sax->comment != NULL)
28090 ret->schemas_sax.comment = commentSplit;
28091 if (old_sax->warning != NULL)
28092 ret->schemas_sax.warning = warningSplit;
28093 if (old_sax->error != NULL)
28094 ret->schemas_sax.error = errorSplit;
28095 if (old_sax->fatalError != NULL)
28096 ret->schemas_sax.fatalError = fatalErrorSplit;
28097 if (old_sax->getParameterEntity != NULL)
28098 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28099 if (old_sax->externalSubset != NULL)
28100 ret->schemas_sax.externalSubset = externalSubsetSplit;
28101
28102 /*
28103 * the 6 schemas callback have to go to the splitter functions
28104 * Note that we use the same text-function for ignorableWhitespace
28105 * if possible, to prevent the parser from testing for ignorable
28106 * whitespace.
28107 */
28108 ret->schemas_sax.characters = charactersSplit;
28109 if ((old_sax->ignorableWhitespace != NULL) &&
28110 (old_sax->ignorableWhitespace != old_sax->characters))
28111 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28112 else
28113 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28114 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28115 ret->schemas_sax.reference = referenceSplit;
28116 ret->schemas_sax.startElementNs = startElementNsSplit;
28117 ret->schemas_sax.endElementNs = endElementNsSplit;
28118
28119 ret->user_data_ptr = user_data;
28120 ret->user_data = *user_data;
28121 *user_data = ret;
28122 }
28123
28124 /*
28125 * plug the pointers back.
28126 */
28127 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028128 ctxt->sax = *sax;
28129 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28130 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028131 return(ret);
28132}
28133
28134/**
28135 * xmlSchemaSAXUnplug:
28136 * @plug: a data structure returned by xmlSchemaSAXPlug
28137 *
28138 * Unplug a SAX based validation layer in a SAX parsing event flow.
28139 * The original pointers used in the call are restored.
28140 *
28141 * Returns 0 in case of success and -1 in case of failure.
28142 */
28143int
28144xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28145{
28146 xmlSAXHandlerPtr *sax;
28147 void **user_data;
28148
28149 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28150 return(-1);
28151 plug->magic = 0;
28152
Daniel Veillardf10ae122005-07-10 19:03:16 +000028153 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028154 /* restore the data */
28155 sax = plug->user_sax_ptr;
28156 *sax = plug->user_sax;
28157 if (plug->user_sax != NULL) {
28158 user_data = plug->user_data_ptr;
28159 *user_data = plug->user_data;
28160 }
28161
28162 /* free and return */
28163 xmlFree(plug);
28164 return(0);
28165}
28166
28167/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028168 * xmlSchemaValidateStream:
28169 * @ctxt: a schema validation context
28170 * @input: the input to use for reading the data
28171 * @enc: an optional encoding information
28172 * @sax: a SAX handler for the resulting events
28173 * @user_data: the context to provide to the SAX handler.
28174 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028175 * Validate an input based on a flow of SAX event from the parser
28176 * and forward the events to the @sax handler with the provided @user_data
28177 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028178 *
28179 * Returns 0 if the document is schemas valid, a positive error code
28180 * number otherwise and -1 in case of internal or API error.
28181 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028182int
Daniel Veillard4255d502002-04-16 15:50:10 +000028183xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028184 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28185 xmlSAXHandlerPtr sax, void *user_data)
28186{
Daniel Veillard971771e2005-07-09 17:32:57 +000028187 xmlSchemaSAXPlugPtr plug = NULL;
28188 xmlSAXHandlerPtr old_sax = NULL;
28189 xmlParserCtxtPtr pctxt = NULL;
28190 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028191 int ret;
28192
Daniel Veillard4255d502002-04-16 15:50:10 +000028193 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028194 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028195
Daniel Veillardcdc82732005-07-08 15:04:06 +000028196 /*
28197 * prepare the parser
28198 */
28199 pctxt = xmlNewParserCtxt();
28200 if (pctxt == NULL)
28201 return (-1);
28202 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028203 pctxt->sax = sax;
28204 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028205#if 0
28206 if (options)
28207 xmlCtxtUseOptions(pctxt, options);
28208#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000028209 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028210
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028211 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028212 if (inputStream == NULL) {
28213 ret = -1;
28214 goto done;
28215 }
28216 inputPush(pctxt, inputStream);
28217 ctxt->parserCtxt = pctxt;
28218 ctxt->input = input;
28219
28220 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028221 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028222 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028223 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28224 if (plug == NULL) {
28225 ret = -1;
28226 goto done;
28227 }
28228 ctxt->input = input;
28229 ctxt->enc = enc;
28230 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028231 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28232 ret = xmlSchemaVStart(ctxt);
28233
28234 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28235 ret = ctxt->parserCtxt->errNo;
28236 if (ret == 0)
28237 ret = 1;
28238 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028239
28240done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028241 ctxt->parserCtxt = NULL;
28242 ctxt->sax = NULL;
28243 ctxt->input = NULL;
28244 if (plug != NULL) {
28245 xmlSchemaSAXUnplug(plug);
28246 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028247 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028248 if (pctxt != NULL) {
28249 pctxt->sax = old_sax;
28250 xmlFreeParserCtxt(pctxt);
28251 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028252 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028253}
28254
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028255/**
28256 * xmlSchemaValidateFile:
28257 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028258 * @filename: the URI of the instance
28259 * @options: a future set of options, currently unused
28260 *
28261 * Do a schemas validation of the given resource, it will use the
28262 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028263 *
28264 * Returns 0 if the document is valid, a positive error code
28265 * number otherwise and -1 in case of an internal or API error.
28266 */
28267int
28268xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028269 const char * filename,
28270 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028271{
28272 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028273 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028274
28275 if ((ctxt == NULL) || (filename == NULL))
28276 return (-1);
28277
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028278 input = xmlParserInputBufferCreateFilename(filename,
28279 XML_CHAR_ENCODING_NONE);
28280 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028281 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028282 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28283 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028284 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028285}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028286
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028287#define bottom_xmlschemas
28288#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028289#endif /* LIBXML_SCHEMAS_ENABLED */