blob: 1dcd87f74a3d577f4fb9507dc50e836c4c574164 [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 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024 * PROBLEMS:
25 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
26 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
27 * XPath will have trouble to resolve to this namespace, since not known.
28 *
29 *
30 * CONSTRAINTS:
31 *
32 * Schema Component Constraint:
33 * All Group Limited (cos-all-limited)
34 * Status: complete
35 * (1.2)
36 * In xmlSchemaGroupDefReferenceTermFixup() and
37 * (2)
38 * In xmlSchemaParseModelGroup()
39 * TODO: Actually this should go to component-level checks,
40 * but is done here due to performance. Move it to an other layer
41 * is schema construction via an API is implemented.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000042 */
Daniel Veillard4255d502002-04-16 15:50:10 +000043#define IN_LIBXML
44#include "libxml.h"
45
46#ifdef LIBXML_SCHEMAS_ENABLED
47
48#include <string.h>
49#include <libxml/xmlmemory.h>
50#include <libxml/parser.h>
51#include <libxml/parserInternals.h>
52#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000053#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000054#include <libxml/xmlschemas.h>
55#include <libxml/schemasInternals.h>
56#include <libxml/xmlschemastypes.h>
57#include <libxml/xmlautomata.h>
58#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000059#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000060#include <libxml/encoding.h>
61#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000062#ifdef LIBXML_PATTERN_ENABLED
63#include <libxml/pattern.h>
64#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000065#ifdef LIBXML_READER_ENABLED
66#include <libxml/xmlreader.h>
67#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000068
Daniel Veillarda84c0b32003-06-02 16:58:46 +000069/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000070
Daniel Veillard82bbbd42003-05-11 20:16:09 +000071/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000072
Daniel Veillard82bbbd42003-05-11 20:16:09 +000073/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000074
Daniel Veillard118aed72002-09-24 14:13:13 +000075/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077/* #define DEBUG_AUTOMATA 1 */
78
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000079#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000080
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000081/* #define DEBUG_IDC 1 */
82
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000083/* #define ENABLE_PARTICLE_RESTRICTION 1 */
84
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000085#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000086
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000087/* #define ENABLE_NAMED_LOCALS */
88
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000089#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000090
91#ifdef LIBXML_READER_ENABLED
92/* #define XML_SCHEMA_READER_ENABLED */
93#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000094
Daniel Veillard4255d502002-04-16 15:50:10 +000095#define UNBOUNDED (1 << 30)
96#define TODO \
97 xmlGenericError(xmlGenericErrorContext, \
98 "Unimplemented block at %s:%d\n", \
99 __FILE__, __LINE__);
100
William M. Brack2f2a6632004-08-20 23:09:47 +0000101#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000102
Daniel Veillard4255d502002-04-16 15:50:10 +0000103/*
104 * The XML Schemas namespaces
105 */
106static const xmlChar *xmlSchemaNs = (const xmlChar *)
107 "http://www.w3.org/2001/XMLSchema";
108
109static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
110 "http://www.w3.org/2001/XMLSchema-instance";
111
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000112static const xmlChar *xmlNamespaceNs = (const xmlChar *)
113 "http://www.w3.org/2000/xmlns/";
114
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000115/*
116* Come casting macros.
117*/
118#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
119#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
120#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
121#define WXS_PTC_CAST (xmlSchemaParticlePtr)
122#define WXS_TYPE_CAST (xmlSchemaTypePtr)
123#define WXS_ELEM_CAST (xmlSchemaElementPtr)
124#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
125#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
126#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
127#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
128#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
129#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
130#define WXS_IDC_CAST (xmlSchemaIDCPtr)
131#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
132#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000133
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000134/*
135* Macros to query common properties of components.
136*/
137#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000138
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000139#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
140/*
141* Macros for element declarations.
142*/
143#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000144
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000145#define WXS_SUBST_HEAD(item) (item)->refDecl
146/*
147* Macros for attribute declarations.
148*/
149#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
150/*
151* Macros for attribute uses.
152*/
153#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000154
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000155#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000156
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000157#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
158
159#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
160/*
161* Macros for attribute groups.
162*/
163#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
164#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
165/*
166* Macros for particles.
167*/
168#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
169
170#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
171
172#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
173/*
174* Macros for model groups definitions.
175*/
176#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
177/*
178* Macros for model groups.
179*/
180#define WXS_IS_MODEL_GROUP(i) \
181 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
182 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
183 ((i)->type == XML_SCHEMA_TYPE_ALL))
184
185#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
186/*
187* Macros for schema buckets.
188*/
189#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
190 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
191
192#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
193 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
194
195#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
196
197#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
198/*
199* Macros for complex/simple types.
200*/
201#define WXS_IS_ANYTYPE(i) \
202 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
203 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
204
205#define WXS_IS_COMPLEX(i) \
206 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
207 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
208
209#define WXS_IS_SIMPLE(item) \
210 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
211 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000212 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000213
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000214#define WXS_IS_ANY_SIMPLE_TYPE(i) \
215 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
216 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000217
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000218#define WXS_IS_RESTRICTION(t) \
219 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000220
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000221#define WXS_IS_EXTENSION(t) \
222 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
223
224#define WXS_IS_TYPE_NOT_FIXED(i) \
225 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
226 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
227
228#define WXS_IS_TYPE_NOT_FIXED_1(item) \
229 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000230 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000231/*
232* Macros for exclusively for complex types.
233*/
234#define WXS_HAS_COMPLEX_CONTENT(item) \
235 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
236 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000237 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
238
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000239#define WXS_HAS_SIMPLE_CONTENT(item) \
240 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000241 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
242
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000243#define WXS_HAS_MIXED_CONTENT(item) \
244 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000245
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000246#define WXS_EMPTIABLE(t) \
247 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000248
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000249#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000250
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000251#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000253#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
254/*
255* Macros for exclusively for simple types.
256*/
257#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000258
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000259#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000260
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000261#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000262
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000263#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
264/*
265* Misc parser context macros.
266*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000267#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
268
269#define WXS_HAS_BUCKETS(ctx) \
270( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
271(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
272
273#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
274
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000275#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000276
277#define WXS_SCHEMA(ctx) (ctx)->schema
278
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000279#define WXS_ADD_LOCAL(ctx, item) \
280 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000281
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000282#define WXS_ADD_GLOBAL(ctx, item) \
283 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000284
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000285#define WXS_ADD_PENDING(ctx, item) \
286 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
287/*
288* Misc macros.
289*/
290#define IS_SCHEMA(node, type) \
291 ((node != NULL) && (node->ns != NULL) && \
292 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
293 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000294
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000295#define FREE_AND_NULL(str) if (str != NULL) { xmlFree((xmlChar *) str); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000296
297/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000298* Since we put the default/fixed values into the dict, we can
299* use pointer comparison for those values.
300* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000301*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000302#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000303
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000304#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000305
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000306#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000307
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000308#define HFAILURE if (res == -1) goto exit_failure;
309
310#define HERROR if (res != 0) goto exit_error;
311
312#define HSTOP(ctx) if ((ctx)->stop) goto exit;
313/*
314* Some flags used for various schema constraints.
315*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000316#define SUBSET_RESTRICTION 1<<0
317#define SUBSET_EXTENSION 1<<1
318#define SUBSET_SUBSTITUTION 1<<2
319#define SUBSET_LIST 1<<3
320#define SUBSET_UNION 1<<4
321
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000322typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
323typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000324
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000325typedef struct _xmlSchemaItemList xmlSchemaItemList;
326typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000327struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000328 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 int nbItems; /* used for dynamic addition of schemata */
330 int sizeItems; /* used for dynamic addition of schemata */
331};
332
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000333#define XML_SCHEMA_CTXT_PARSER 1
334#define XML_SCHEMA_CTXT_VALIDATOR 2
335
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000336typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
337typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
338struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000339 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000340};
341
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000342typedef struct _xmlSchemaBucket xmlSchemaBucket;
343typedef xmlSchemaBucket *xmlSchemaBucketPtr;
344
345#define XML_SCHEMA_SCHEMA_MAIN 0
346#define XML_SCHEMA_SCHEMA_IMPORT 1
347#define XML_SCHEMA_SCHEMA_INCLUDE 2
348#define XML_SCHEMA_SCHEMA_REDEFINE 3
349
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000350/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000351 * xmlSchemaSchemaRelation:
352 *
353 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000354 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000355typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
356typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
357struct _xmlSchemaSchemaRelation {
358 xmlSchemaSchemaRelationPtr next;
359 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
360 const xmlChar *importNamespace;
361 xmlSchemaBucketPtr bucket;
362};
363
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000364#define XML_SCHEMA_BUCKET_MARKED 1<<0
365#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
366
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000367struct _xmlSchemaBucket {
368 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000369 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000370 const xmlChar *schemaLocation;
371 const xmlChar *origTargetNamespace;
372 const xmlChar *targetNamespace;
373 xmlDocPtr doc;
374 xmlSchemaSchemaRelationPtr relations;
375 int located;
376 int parsed;
377 int imported;
378 int preserveDoc;
379 xmlSchemaItemListPtr globals; /* Global components. */
380 xmlSchemaItemListPtr locals; /* Local components. */
381};
382
383/**
384 * xmlSchemaImport:
385 * (extends xmlSchemaBucket)
386 *
387 * Reflects a schema. Holds some information
388 * about the schema and its toplevel components. Duplicate
389 * toplevel components are not checked at this level.
390 */
391typedef struct _xmlSchemaImport xmlSchemaImport;
392typedef xmlSchemaImport *xmlSchemaImportPtr;
393struct _xmlSchemaImport {
394 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000395 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000396 const xmlChar *schemaLocation; /* The URI of the schema document. */
397 /* For chameleon includes, @origTargetNamespace will be NULL */
398 const xmlChar *origTargetNamespace;
399 /*
400 * For chameleon includes, @targetNamespace will be the
401 * targetNamespace of the including schema.
402 */
403 const xmlChar *targetNamespace;
404 xmlDocPtr doc; /* The schema node-tree. */
405 /* @relations will hold any included/imported/redefined schemas. */
406 xmlSchemaSchemaRelationPtr relations;
407 int located;
408 int parsed;
409 int imported;
410 int preserveDoc;
411 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000412 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000413 /* The imported schema. */
414 xmlSchemaPtr schema;
415};
416
417/*
418* (extends xmlSchemaBucket)
419*/
420typedef struct _xmlSchemaInclude xmlSchemaInclude;
421typedef xmlSchemaInclude *xmlSchemaIncludePtr;
422struct _xmlSchemaInclude {
423 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000424 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000425 const xmlChar *schemaLocation;
426 const xmlChar *origTargetNamespace;
427 const xmlChar *targetNamespace;
428 xmlDocPtr doc;
429 xmlSchemaSchemaRelationPtr relations;
430 int located;
431 int parsed;
432 int imported;
433 int preserveDoc;
434 xmlSchemaItemListPtr globals; /* Global components. */
435 xmlSchemaItemListPtr locals; /* Local components. */
436
437 /* The owning main or import schema bucket. */
438 xmlSchemaImportPtr ownerImport;
439};
440
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000441/**
442 * xmlSchemaBasicItem:
443 *
444 * The abstract base type for schema components.
445 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000446typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
447typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
448struct _xmlSchemaBasicItem {
449 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000450};
451
452/**
453 * xmlSchemaAnnotItem:
454 *
455 * The abstract base type for annotated schema components.
456 * (Extends xmlSchemaBasicItem)
457 */
458typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
459typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
460struct _xmlSchemaAnnotItem {
461 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000462 xmlSchemaAnnotPtr annot;
463};
464
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000465/**
466 * xmlSchemaTreeItem:
467 *
468 * The abstract base type for tree-like structured schema components.
469 * (Extends xmlSchemaAnnotItem)
470 */
471typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
472typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
473struct _xmlSchemaTreeItem {
474 xmlSchemaTypeType type;
475 xmlSchemaAnnotPtr annot;
476 xmlSchemaTreeItemPtr next;
477 xmlSchemaTreeItemPtr children;
478};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000479
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000480
481#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
482/**
483 * xmlSchemaAttributeUsePtr:
484 *
485 * The abstract base type for tree-like structured schema components.
486 * (Extends xmlSchemaTreeItem)
487 */
488typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
489typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
490struct _xmlSchemaAttributeUse {
491 xmlSchemaTypeType type;
492 xmlSchemaAnnotPtr annot;
493 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
494 /*
495 * The attr. decl. OR a QName-ref. to an attr. decl. OR
496 * a QName-ref. to an attribute group definition.
497 */
498 xmlSchemaAttributePtr attrDecl;
499
500 int flags;
501 xmlNodePtr node;
502 int occurs; /* required, optional */
503 const xmlChar * defValue;
504 xmlSchemaValPtr defVal;
505};
506
507/**
508 * xmlSchemaAttributeUseProhibPtr:
509 *
510 * A helper component to reflect attribute prohibitions.
511 * (Extends xmlSchemaBasicItem)
512 */
513typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
514typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
515struct _xmlSchemaAttributeUseProhib {
516 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
517 xmlNodePtr node;
518 const xmlChar *name;
519 const xmlChar *targetNamespace;
520 int isRef;
521};
522
523/**
524 * xmlSchemaRedef:
525 */
526typedef struct _xmlSchemaRedef xmlSchemaRedef;
527typedef xmlSchemaRedef *xmlSchemaRedefPtr;
528struct _xmlSchemaRedef {
529 xmlSchemaRedefPtr next;
530 xmlSchemaBasicItemPtr item; /* The redefining component. */
531 xmlSchemaBasicItemPtr reference; /* The referencing component. */
532 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
533 const xmlChar *refName; /* The name of the to-be-redefined component. */
534 const xmlChar *refTargetNs; /* The target namespace of the
535 to-be-redefined comp. */
536 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
537};
538
539/**
540 * xmlSchemaConstructionCtxt:
541 */
542typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
543typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
544struct _xmlSchemaConstructionCtxt {
545 xmlSchemaPtr mainSchema; /* The main schema. */
546 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
547 xmlDictPtr dict;
548 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
549 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
550 xmlSchemaBucketPtr bucket; /* The current schema bucket */
551 xmlSchemaItemListPtr pending; /* All Components of all schemas that
552 need to be fixed. */
553 xmlHashTablePtr substGroups;
554 xmlSchemaRedefPtr redefs;
555 xmlSchemaRedefPtr lastRedef;
556};
557
558#define XML_SCHEMAS_PARSE_ERROR 1
559#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
560
561struct _xmlSchemaParserCtxt {
562 int type;
563 void *userData; /* user specific data block */
564 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
565 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
566 xmlSchemaValidError err;
567 int nberrors;
568 xmlStructuredErrorFunc serror;
569
570 xmlSchemaConstructionCtxtPtr constructor;
571 int ownsConstructor; /* TODO: Move this to parser *flags*. */
572
573 /* xmlSchemaPtr topschema; */
574 /* xmlHashTablePtr namespaces; */
575
576 xmlSchemaPtr schema; /* The main schema in use */
577 int counter;
578
579 const xmlChar *URL;
580 xmlDocPtr doc;
581 int preserve; /* Whether the doc should be freed */
582
583 const char *buffer;
584 int size;
585
586 /*
587 * Used to build complex element content models
588 */
589 xmlAutomataPtr am;
590 xmlAutomataStatePtr start;
591 xmlAutomataStatePtr end;
592 xmlAutomataStatePtr state;
593
594 xmlDictPtr dict; /* dictionnary for interned string names */
595 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
596 int options;
597 xmlSchemaValidCtxtPtr vctxt;
598 int isS4S;
599 int isRedefine;
600 int xsiAssemble;
601 int stop; /* If the parser should stop; i.e. a critical error. */
602 const xmlChar *targetNamespace;
603 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
604
605 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
606 int redefCounter; /* Used for redefinitions. */
607 xmlSchemaItemListPtr attrProhibs;
608};
609
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000610/**
611 * xmlSchemaQNameRef:
612 *
613 * A component reference item (not a schema component)
614 * (Extends xmlSchemaBasicItem)
615 */
616typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
617typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
618struct _xmlSchemaQNameRef {
619 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000620 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000621 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000622 const xmlChar *name;
623 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000624 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000625};
626
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000627/**
628 * xmlSchemaParticle:
629 *
630 * A particle component.
631 * (Extends xmlSchemaTreeItem)
632 */
633typedef struct _xmlSchemaParticle xmlSchemaParticle;
634typedef xmlSchemaParticle *xmlSchemaParticlePtr;
635struct _xmlSchemaParticle {
636 xmlSchemaTypeType type;
637 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000638 xmlSchemaTreeItemPtr next; /* next particle */
639 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
640 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
641 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000642 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000643 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000644 xmlNodePtr node;
645};
646
647/**
648 * xmlSchemaModelGroup:
649 *
650 * A model group component.
651 * (Extends xmlSchemaTreeItem)
652 */
653typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
654typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
655struct _xmlSchemaModelGroup {
656 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
657 xmlSchemaAnnotPtr annot;
658 xmlSchemaTreeItemPtr next; /* not used */
659 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
660 xmlNodePtr node;
661};
662
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000663#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000664#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000665/**
666 * xmlSchemaModelGroupDef:
667 *
668 * A model group definition component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
672typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
673struct _xmlSchemaModelGroupDef {
674 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
675 xmlSchemaAnnotPtr annot;
676 xmlSchemaTreeItemPtr next; /* not used */
677 xmlSchemaTreeItemPtr children; /* the "model group" */
678 const xmlChar *name;
679 const xmlChar *targetNamespace;
680 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000681 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000682};
683
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000684typedef struct _xmlSchemaIDC xmlSchemaIDC;
685typedef xmlSchemaIDC *xmlSchemaIDCPtr;
686
687/**
688 * xmlSchemaIDCSelect:
689 *
690 * The identity-constraint "field" and "selector" item, holding the
691 * XPath expression.
692 */
693typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
694typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000695struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000696 xmlSchemaIDCSelectPtr next;
697 xmlSchemaIDCPtr idc;
698 int index; /* an index position if significant for IDC key-sequences */
699 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000700 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000701};
702
703/**
704 * xmlSchemaIDC:
705 *
706 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000707 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000708 */
709
710struct _xmlSchemaIDC {
711 xmlSchemaTypeType type;
712 xmlSchemaAnnotPtr annot;
713 xmlSchemaIDCPtr next;
714 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000715 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000716 const xmlChar *targetNamespace;
717 xmlSchemaIDCSelectPtr selector;
718 xmlSchemaIDCSelectPtr fields;
719 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000720 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000721};
722
723/**
724 * xmlSchemaIDCAug:
725 *
726 * The augmented IDC information used for validation.
727 */
728typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
729typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
730struct _xmlSchemaIDCAug {
731 xmlSchemaIDCAugPtr next; /* next in a list */
732 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000733 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000734 tables need to be bubbled upwards */
735};
736
737/**
738 * xmlSchemaPSVIIDCKeySequence:
739 *
740 * The key sequence of a node table item.
741 */
742typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
743typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
744struct _xmlSchemaPSVIIDCKey {
745 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000746 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000747};
748
749/**
750 * xmlSchemaPSVIIDCNode:
751 *
752 * The node table item of a node table.
753 */
754typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
755typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
756struct _xmlSchemaPSVIIDCNode {
757 xmlNodePtr node;
758 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000759 int nodeLine;
760 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000761
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000762};
763
764/**
765 * xmlSchemaPSVIIDCBinding:
766 *
767 * The identity-constraint binding item of the [identity-constraint table].
768 */
769typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
770typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
771struct _xmlSchemaPSVIIDCBinding {
772 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
773 xmlSchemaIDCPtr definition; /* the IDC definition */
774 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
775 int nbNodes; /* number of entries in the node table */
776 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000777 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000778 table */
779 /* int nbKeys; number of keys in each key-sequence */
780};
781
782#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
783#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
784
785#define XPATH_STATE_OBJ_MATCHES -2
786#define XPATH_STATE_OBJ_BLOCKED -3
787
788typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
789typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
790
791/**
792 * xmlSchemaIDCStateObj:
793 *
794 * The state object used to evaluate XPath expressions.
795 */
796typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
797typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
798struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000799 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000800 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000801 int depth; /* depth of creation */
802 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000803 int nbHistory;
804 int sizeHistory;
805 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
806 matcher */
807 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000808 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000809};
810
811#define IDC_MATCHER 0
812
813/**
814 * xmlSchemaIDCMatcher:
815 *
816 * Used to IDC selectors (and fields) successively.
817 */
818struct _xmlSchemaIDCMatcher {
819 int type;
820 int depth; /* the tree depth at creation time */
821 xmlSchemaIDCMatcherPtr next; /* next in the list */
822 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
823 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
824 elements */
825 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000826 int targetDepth;
827};
828
829/*
830* Element info flags.
831*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000832#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
833#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
834#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
835#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
836
837#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
838#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
839#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
840
841#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
842#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
843#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
844#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000845
846/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000847 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000848 *
849 * Holds information of an element node.
850 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000851struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000852 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000853 xmlNodePtr node;
854 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000855 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000856 const xmlChar *nsName;
857 const xmlChar *value;
858 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000859 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000860
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000861 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000862
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000863 int valNeeded;
864 int normVal;
865
866 xmlSchemaElementPtr decl; /* the element/attribute declaration */
867 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000868 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
869 for the scope element*/
870 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
871 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000872 xmlRegExecCtxtPtr regexCtxt;
873
874 const xmlChar **nsBindings; /* Namespace bindings on this element */
875 int nbNsBindings;
876 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000877};
878
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000879#define XML_SCHEMAS_ATTR_UNKNOWN 1
880#define XML_SCHEMAS_ATTR_ASSESSED 2
881#define XML_SCHEMAS_ATTR_PROHIBITED 3
882#define XML_SCHEMAS_ATTR_ERR_MISSING 4
883#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
884#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
885#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
886#define XML_SCHEMAS_ATTR_DEFAULT 8
887#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
888#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
889#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
890#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
891#define XML_SCHEMAS_ATTR_WILD_SKIP 13
892#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
893#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
894#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
895#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000896/*
897* @metaType values of xmlSchemaAttrInfo.
898*/
899#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
900#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
901#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
902#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
903#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000904
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000905typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
906typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
907struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000908 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000909 xmlNodePtr node;
910 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000911 const xmlChar *localName;
912 const xmlChar *nsName;
913 const xmlChar *value;
914 xmlSchemaValPtr val; /* the pre-computed value if any */
915 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
916 int flags; /* combination of node info flags */
917
918 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000919 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000920 int state;
921 int metaType;
922 const xmlChar *vcValue; /* the value constraint value */
923 xmlSchemaNodeInfoPtr parent;
924};
925
926
927#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000928/**
929 * xmlSchemaValidCtxt:
930 *
931 * A Schemas validation context
932 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000933struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000934 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000935 void *userData; /* user specific data block */
936 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000937 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000938 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000939
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000940 xmlSchemaPtr schema; /* The schema in use */
941 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000942 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000943 xmlCharEncoding enc;
944 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000945 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000946 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000947
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000948 int err;
949 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000950
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000951 xmlNodePtr node;
952 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000953 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000954
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000955 xmlRegExecCtxtPtr regexp;
956 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000957
Daniel Veillardc0826a72004-08-10 14:17:33 +0000958 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000959 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000960 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000961 xmlSchemaParserCtxtPtr pctxt;
962 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000963
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000964 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000965 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000966 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000967 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000968
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000969 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
970
971 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
972 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000973
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000974 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
975 int nbIdcNodes;
976 int sizeIdcNodes;
977
978 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
979 int nbIdcKeys;
980 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000981
982 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000983
984 xmlDictPtr dict;
985
Daniel Veillard39e5c892005-07-03 22:48:50 +0000986#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000987 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000988#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000989
990 xmlSchemaAttrInfoPtr *attrInfos;
991 int nbAttrInfos;
992 int sizeAttrInfos;
993
994 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000995 xmlSchemaItemListPtr nodeQNames;
Daniel Veillard4255d502002-04-16 15:50:10 +0000996};
997
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000998/**
999 * xmlSchemaSubstGroup:
1000 *
1001 *
1002 */
1003typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1004typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1005struct _xmlSchemaSubstGroup {
1006 xmlSchemaElementPtr head;
1007 xmlSchemaItemListPtr members;
1008};
1009
Daniel Veillard4255d502002-04-16 15:50:10 +00001010/************************************************************************
1011 * *
1012 * Some predeclarations *
1013 * *
1014 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001015
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001016static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1017 xmlSchemaPtr schema,
1018 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001019static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1020 xmlSchemaPtr schema,
1021 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001022static int
1023xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1024 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001025static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001026xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1027static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001028xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1029 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001030static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001031xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1032 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001033static void
1034xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001035static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001036xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001037static xmlSchemaTreeItemPtr
1038xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1039 xmlNodePtr node, xmlSchemaTypeType type,
1040 int withParticle);
1041static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001042xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001043static xmlSchemaTypeLinkPtr
1044xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001045static void
1046xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1047 const char *funcName,
1048 const char *message);
1049static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001050xmlSchemaCheckCOSSTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
1051 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001052 xmlSchemaTypePtr baseType,
1053 int subset);
1054static void
1055xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001056 xmlSchemaParserCtxtPtr ctxt);
1057static void
1058xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001059static xmlSchemaQNameRefPtr
1060xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1061 xmlSchemaPtr schema,
1062 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001063
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001064/************************************************************************
1065 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001066 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001067 * *
1068 ************************************************************************/
1069
1070/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001071 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001072 * @type: the type of the schema item
1073 *
1074 * Returns the component name of a schema item.
1075 */
1076static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001077xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001078{
1079 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001080 case XML_SCHEMA_TYPE_BASIC:
1081 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001082 case XML_SCHEMA_TYPE_SIMPLE:
1083 return(BAD_CAST "simple type definition");
1084 case XML_SCHEMA_TYPE_COMPLEX:
1085 return(BAD_CAST "complex type definition");
1086 case XML_SCHEMA_TYPE_ELEMENT:
1087 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001088 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1089 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001090 case XML_SCHEMA_TYPE_ATTRIBUTE:
1091 return(BAD_CAST "attribute declaration");
1092 case XML_SCHEMA_TYPE_GROUP:
1093 return(BAD_CAST "model group definition");
1094 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1095 return(BAD_CAST "attribute group definition");
1096 case XML_SCHEMA_TYPE_NOTATION:
1097 return(BAD_CAST "notation declaration");
1098 case XML_SCHEMA_TYPE_SEQUENCE:
1099 return(BAD_CAST "model group (sequence)");
1100 case XML_SCHEMA_TYPE_CHOICE:
1101 return(BAD_CAST "model group (choice)");
1102 case XML_SCHEMA_TYPE_ALL:
1103 return(BAD_CAST "model group (all)");
1104 case XML_SCHEMA_TYPE_PARTICLE:
1105 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001106 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001107 return(BAD_CAST "unique identity-constraint");
1108 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001109 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001110 return(BAD_CAST "key identity-constraint");
1111 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001112 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001113 return(BAD_CAST "keyref identity-constraint");
1114 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001115 case XML_SCHEMA_TYPE_ANY:
1116 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001117 case XML_SCHEMA_EXTRA_QNAMEREF:
1118 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001119 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1120 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001121 default:
1122 return(BAD_CAST "Not a schema component");
1123 }
1124}
1125
1126/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001127 * xmlSchemaGetComponentTypeStr:
1128 * @type: the type of the schema item
1129 *
1130 * Returns the component name of a schema item.
1131 */
1132static const xmlChar *
1133xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1134{
1135 switch (item->type) {
1136 case XML_SCHEMA_TYPE_BASIC:
1137 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1138 return(BAD_CAST "complex type definition");
1139 else
1140 return(BAD_CAST "simple type definition");
1141 default:
1142 return(xmlSchemaItemTypeToStr(item->type));
1143 }
1144}
1145
1146/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001147 * xmlSchemaGetComponentNode:
1148 * @item: a schema component
1149 *
1150 * Returns node associated with the schema component.
1151 * NOTE that such a node need not be available; plus, a component's
1152 * node need not to reflect the component directly, since there is no
1153 * one-to-one relationship between the XML Schema representation and
1154 * the component representation.
1155 */
1156static xmlNodePtr
1157xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1158{
1159 switch (item->type) {
1160 case XML_SCHEMA_TYPE_ELEMENT:
1161 return (((xmlSchemaElementPtr) item)->node);
1162 case XML_SCHEMA_TYPE_ATTRIBUTE:
1163 return (((xmlSchemaAttributePtr) item)->node);
1164 case XML_SCHEMA_TYPE_COMPLEX:
1165 case XML_SCHEMA_TYPE_SIMPLE:
1166 return (((xmlSchemaTypePtr) item)->node);
1167 case XML_SCHEMA_TYPE_ANY:
1168 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1169 return (((xmlSchemaWildcardPtr) item)->node);
1170 case XML_SCHEMA_TYPE_PARTICLE:
1171 return (((xmlSchemaParticlePtr) item)->node);
1172 case XML_SCHEMA_TYPE_SEQUENCE:
1173 case XML_SCHEMA_TYPE_CHOICE:
1174 case XML_SCHEMA_TYPE_ALL:
1175 return (((xmlSchemaModelGroupPtr) item)->node);
1176 case XML_SCHEMA_TYPE_GROUP:
1177 return (((xmlSchemaModelGroupDefPtr) item)->node);
1178 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1179 return (((xmlSchemaAttributeGroupPtr) item)->node);
1180 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1181 case XML_SCHEMA_TYPE_IDC_KEY:
1182 case XML_SCHEMA_TYPE_IDC_KEYREF:
1183 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001184 case XML_SCHEMA_EXTRA_QNAMEREF:
1185 return(((xmlSchemaQNameRefPtr) item)->node);
1186 /* TODO: What to do with NOTATIONs?
1187 case XML_SCHEMA_TYPE_NOTATION:
1188 return (((xmlSchemaNotationPtr) item)->node);
1189 */
1190 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1191 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001192 default:
1193 return (NULL);
1194 }
1195}
1196
1197#if 0
1198/**
1199 * xmlSchemaGetNextComponent:
1200 * @item: a schema component
1201 *
1202 * Returns the next sibling of the schema component.
1203 */
1204static xmlSchemaBasicItemPtr
1205xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1206{
1207 switch (item->type) {
1208 case XML_SCHEMA_TYPE_ELEMENT:
1209 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1210 case XML_SCHEMA_TYPE_ATTRIBUTE:
1211 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1212 case XML_SCHEMA_TYPE_COMPLEX:
1213 case XML_SCHEMA_TYPE_SIMPLE:
1214 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1215 case XML_SCHEMA_TYPE_ANY:
1216 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1217 return (NULL);
1218 case XML_SCHEMA_TYPE_PARTICLE:
1219 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1220 case XML_SCHEMA_TYPE_SEQUENCE:
1221 case XML_SCHEMA_TYPE_CHOICE:
1222 case XML_SCHEMA_TYPE_ALL:
1223 return (NULL);
1224 case XML_SCHEMA_TYPE_GROUP:
1225 return (NULL);
1226 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1227 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1228 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1229 case XML_SCHEMA_TYPE_IDC_KEY:
1230 case XML_SCHEMA_TYPE_IDC_KEYREF:
1231 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1232 default:
1233 return (NULL);
1234 }
1235}
1236#endif
1237
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001238
1239/**
1240 * xmlSchemaFormatQName:
1241 * @buf: the string buffer
1242 * @namespaceName: the namespace name
1243 * @localName: the local name
1244 *
1245 * Returns the given QName in the format "{namespaceName}localName" or
1246 * just "localName" if @namespaceName is NULL.
1247 *
1248 * Returns the localName if @namespaceName is NULL, a formatted
1249 * string otherwise.
1250 */
1251static const xmlChar*
1252xmlSchemaFormatQName(xmlChar **buf,
1253 const xmlChar *namespaceName,
1254 const xmlChar *localName)
1255{
1256 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001257 if (namespaceName != NULL) {
1258 *buf = xmlStrdup(BAD_CAST "{");
1259 *buf = xmlStrcat(*buf, namespaceName);
1260 *buf = xmlStrcat(*buf, BAD_CAST "}");
1261 }
1262 if (localName != NULL) {
1263 if (namespaceName == NULL)
1264 return(localName);
1265 *buf = xmlStrcat(*buf, localName);
1266 } else {
1267 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1268 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001269 return ((const xmlChar *) *buf);
1270}
1271
1272static const xmlChar*
1273xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1274{
1275 if (ns != NULL)
1276 return (xmlSchemaFormatQName(buf, ns->href, localName));
1277 else
1278 return (xmlSchemaFormatQName(buf, NULL, localName));
1279}
1280
1281static const xmlChar *
1282xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1283{
1284 switch (item->type) {
1285 case XML_SCHEMA_TYPE_ELEMENT:
1286 return (((xmlSchemaElementPtr) item)->name);
1287 case XML_SCHEMA_TYPE_ATTRIBUTE:
1288 return (((xmlSchemaAttributePtr) item)->name);
1289 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1290 return (((xmlSchemaAttributeGroupPtr) item)->name);
1291 case XML_SCHEMA_TYPE_BASIC:
1292 case XML_SCHEMA_TYPE_SIMPLE:
1293 case XML_SCHEMA_TYPE_COMPLEX:
1294 return (((xmlSchemaTypePtr) item)->name);
1295 case XML_SCHEMA_TYPE_GROUP:
1296 return (((xmlSchemaModelGroupDefPtr) item)->name);
1297 case XML_SCHEMA_TYPE_IDC_KEY:
1298 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1299 case XML_SCHEMA_TYPE_IDC_KEYREF:
1300 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001301 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1302 if (WXS_ATTRUSE_DECL(item) != NULL) {
1303 return(xmlSchemaGetComponentName(
1304 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1305 } else
1306 return(NULL);
1307 case XML_SCHEMA_EXTRA_QNAMEREF:
1308 return (((xmlSchemaQNameRefPtr) item)->name);
1309 case XML_SCHEMA_TYPE_NOTATION:
1310 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001311 default:
1312 /*
1313 * Other components cannot have names.
1314 */
1315 break;
1316 }
1317 return (NULL);
1318}
1319
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001320#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1321#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1322/*
1323static const xmlChar *
1324xmlSchemaGetQNameRefName(void *ref)
1325{
1326 return(((xmlSchemaQNameRefPtr) ref)->name);
1327}
1328
1329static const xmlChar *
1330xmlSchemaGetQNameRefTargetNs(void *ref)
1331{
1332 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1333}
1334*/
1335
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001336static const xmlChar *
1337xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1338{
1339 switch (item->type) {
1340 case XML_SCHEMA_TYPE_ELEMENT:
1341 return (((xmlSchemaElementPtr) item)->targetNamespace);
1342 case XML_SCHEMA_TYPE_ATTRIBUTE:
1343 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1344 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1345 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1346 case XML_SCHEMA_TYPE_BASIC:
1347 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1348 case XML_SCHEMA_TYPE_SIMPLE:
1349 case XML_SCHEMA_TYPE_COMPLEX:
1350 return (((xmlSchemaTypePtr) item)->targetNamespace);
1351 case XML_SCHEMA_TYPE_GROUP:
1352 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1353 case XML_SCHEMA_TYPE_IDC_KEY:
1354 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1355 case XML_SCHEMA_TYPE_IDC_KEYREF:
1356 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001357 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1358 if (WXS_ATTRUSE_DECL(item) != NULL) {
1359 return(xmlSchemaGetComponentTargetNs(
1360 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1361 }
1362 /* TODO: Will returning NULL break something? */
1363 break;
1364 case XML_SCHEMA_EXTRA_QNAMEREF:
1365 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1366 case XML_SCHEMA_TYPE_NOTATION:
1367 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001368 default:
1369 /*
1370 * Other components cannot have names.
1371 */
1372 break;
1373 }
1374 return (NULL);
1375}
1376
1377static const xmlChar*
1378xmlSchemaGetComponentQName(xmlChar **buf,
1379 void *item)
1380{
1381 return (xmlSchemaFormatQName(buf,
1382 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1383 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1384}
1385
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001386static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001387xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001388{
1389 xmlChar *str = NULL;
1390
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001391 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001392 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001393 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1394 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001395 *buf = xmlStrcat(*buf, BAD_CAST "'");
1396 FREE_AND_NULL(str);
1397 return(*buf);
1398}
1399
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001400static const xmlChar*
1401xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1402{
1403 return(xmlSchemaGetComponentDesignation(buf, idc));
1404}
1405
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001406/**
1407 * xmlSchemaWildcardPCToString:
1408 * @pc: the type of processContents
1409 *
1410 * Returns a string representation of the type of
1411 * processContents.
1412 */
1413static const xmlChar *
1414xmlSchemaWildcardPCToString(int pc)
1415{
1416 switch (pc) {
1417 case XML_SCHEMAS_ANY_SKIP:
1418 return (BAD_CAST "skip");
1419 case XML_SCHEMAS_ANY_LAX:
1420 return (BAD_CAST "lax");
1421 case XML_SCHEMAS_ANY_STRICT:
1422 return (BAD_CAST "strict");
1423 default:
1424 return (BAD_CAST "invalid process contents");
1425 }
1426}
1427
1428/**
1429 * xmlSchemaGetCanonValueWhtspExt:
1430 * @val: the precomputed value
1431 * @retValue: the returned value
1432 * @ws: the whitespace type of the value
1433 *
1434 * Get a the cononical representation of the value.
1435 * The caller has to free the returned retValue.
1436 *
1437 * Returns 0 if the value could be built and -1 in case of
1438 * API errors or if the value type is not supported yet.
1439 */
1440static int
1441xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1442 xmlSchemaWhitespaceValueType ws,
1443 xmlChar **retValue)
1444{
1445 int list;
1446 xmlSchemaValType valType;
1447 const xmlChar *value, *value2 = NULL;
1448
1449
1450 if ((retValue == NULL) || (val == NULL))
1451 return (-1);
1452 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1453 *retValue = NULL;
1454 do {
1455 value = NULL;
1456 valType = xmlSchemaGetValType(val);
1457 switch (valType) {
1458 case XML_SCHEMAS_STRING:
1459 case XML_SCHEMAS_NORMSTRING:
1460 case XML_SCHEMAS_ANYSIMPLETYPE:
1461 value = xmlSchemaValueGetAsString(val);
1462 if (value != NULL) {
1463 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1464 value2 = xmlSchemaCollapseString(value);
1465 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1466 value2 = xmlSchemaWhiteSpaceReplace(value);
1467 if (value2 != NULL)
1468 value = value2;
1469 }
1470 break;
1471 default:
1472 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1473 if (value2 != NULL)
1474 xmlFree((xmlChar *) value2);
1475 goto internal_error;
1476 }
1477 value = value2;
1478 }
1479 if (*retValue == NULL)
1480 if (value == NULL) {
1481 if (! list)
1482 *retValue = xmlStrdup(BAD_CAST "");
1483 } else
1484 *retValue = xmlStrdup(value);
1485 else if (value != NULL) {
1486 /* List. */
1487 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1488 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1489 }
1490 FREE_AND_NULL(value2)
1491 val = xmlSchemaValueGetNext(val);
1492 } while (val != NULL);
1493
1494 return (0);
1495internal_error:
1496 if (*retValue != NULL)
1497 xmlFree((xmlChar *) (*retValue));
1498 if (value2 != NULL)
1499 xmlFree((xmlChar *) value2);
1500 return (-1);
1501}
1502
1503/**
1504 * xmlSchemaFormatItemForReport:
1505 * @buf: the string buffer
1506 * @itemDes: the designation of the item
1507 * @itemName: the name of the item
1508 * @item: the item as an object
1509 * @itemNode: the node of the item
1510 * @local: the local name
1511 * @parsing: if the function is used during the parse
1512 *
1513 * Returns a representation of the given item used
1514 * for error reports.
1515 *
1516 * The following order is used to build the resulting
1517 * designation if the arguments are not NULL:
1518 * 1a. If itemDes not NULL -> itemDes
1519 * 1b. If (itemDes not NULL) and (itemName not NULL)
1520 * -> itemDes + itemName
1521 * 2. If the preceding was NULL and (item not NULL) -> item
1522 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1523 *
1524 * If the itemNode is an attribute node, the name of the attribute
1525 * will be appended to the result.
1526 *
1527 * Returns the formatted string and sets @buf to the resulting value.
1528 */
1529static xmlChar*
1530xmlSchemaFormatItemForReport(xmlChar **buf,
1531 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001532 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001533 xmlNodePtr itemNode)
1534{
1535 xmlChar *str = NULL;
1536 int named = 1;
1537
1538 if (*buf != NULL) {
1539 xmlFree(*buf);
1540 *buf = NULL;
1541 }
1542
1543 if (itemDes != NULL) {
1544 *buf = xmlStrdup(itemDes);
1545 } else if (item != NULL) {
1546 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001547 case XML_SCHEMA_TYPE_BASIC: {
1548 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1549
1550 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001552 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001553 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001554 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001555 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1556 else
1557 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001558 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001559 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001560 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001561 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001562 case XML_SCHEMA_TYPE_SIMPLE: {
1563 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1564
1565 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001566 *buf = xmlStrdup(BAD_CAST"");
1567 } else {
1568 *buf = xmlStrdup(BAD_CAST "local ");
1569 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001570 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001572 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001573 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001574 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001575 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1576 else
1577 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001578 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 *buf = xmlStrcat(*buf, BAD_CAST "'");
1582 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001583 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001585 case XML_SCHEMA_TYPE_COMPLEX: {
1586 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1587
1588 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001589 *buf = xmlStrdup(BAD_CAST "");
1590 else
1591 *buf = xmlStrdup(BAD_CAST "local ");
1592 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001593 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001595 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001596 *buf = xmlStrcat(*buf, BAD_CAST "'");
1597 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001598 }
1599 break;
1600 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1601 xmlSchemaAttributeUsePtr ause;
1602
1603 ause = WXS_ATTR_USE_CAST item;
1604 *buf = xmlStrdup(BAD_CAST "attribute use ");
1605 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1606 *buf = xmlStrcat(*buf, BAD_CAST "'");
1607 *buf = xmlStrcat(*buf,
1608 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1609 FREE_AND_NULL(str)
1610 *buf = xmlStrcat(*buf, BAD_CAST "'");
1611 } else {
1612 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1613 }
1614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001615 break;
1616 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1617 xmlSchemaAttributePtr attr;
1618
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001619 attr = (xmlSchemaAttributePtr) item;
1620 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1621 *buf = xmlStrcat(*buf, BAD_CAST " '");
1622 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1623 attr->targetNamespace, attr->name));
1624 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001625 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001626 }
1627 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001628 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1629 xmlSchemaGetComponentDesignation(buf, item);
1630 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 case XML_SCHEMA_TYPE_ELEMENT: {
1632 xmlSchemaElementPtr elem;
1633
1634 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001635 *buf = xmlStrdup(BAD_CAST "element decl.");
1636 *buf = xmlStrcat(*buf, BAD_CAST " '");
1637 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1638 elem->targetNamespace, elem->name));
1639 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001640 }
1641 break;
1642 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1643 case XML_SCHEMA_TYPE_IDC_KEY:
1644 case XML_SCHEMA_TYPE_IDC_KEYREF:
1645 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1646 *buf = xmlStrdup(BAD_CAST "unique '");
1647 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1648 *buf = xmlStrdup(BAD_CAST "key '");
1649 else
1650 *buf = xmlStrdup(BAD_CAST "keyRef '");
1651 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1652 *buf = xmlStrcat(*buf, BAD_CAST "'");
1653 break;
1654 case XML_SCHEMA_TYPE_ANY:
1655 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1656 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1657 ((xmlSchemaWildcardPtr) item)->processContents));
1658 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1659 break;
1660 case XML_SCHEMA_FACET_MININCLUSIVE:
1661 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1662 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1663 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1664 case XML_SCHEMA_FACET_TOTALDIGITS:
1665 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1666 case XML_SCHEMA_FACET_PATTERN:
1667 case XML_SCHEMA_FACET_ENUMERATION:
1668 case XML_SCHEMA_FACET_WHITESPACE:
1669 case XML_SCHEMA_FACET_LENGTH:
1670 case XML_SCHEMA_FACET_MAXLENGTH:
1671 case XML_SCHEMA_FACET_MINLENGTH:
1672 *buf = xmlStrdup(BAD_CAST "facet '");
1673 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1674 *buf = xmlStrcat(*buf, BAD_CAST "'");
1675 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001676 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001677 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001678 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001679 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001680 *buf = xmlStrcat(*buf, BAD_CAST "'");
1681 FREE_AND_NULL(str)
1682 }
1683 break;
1684 case XML_SCHEMA_TYPE_SEQUENCE:
1685 case XML_SCHEMA_TYPE_CHOICE:
1686 case XML_SCHEMA_TYPE_ALL:
1687 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001688 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1689 break;
1690 case XML_SCHEMA_TYPE_NOTATION: {
1691 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1692 *buf = xmlStrcat(*buf, BAD_CAST " '");
1693 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1694 *buf = xmlStrcat(*buf, BAD_CAST "'");
1695 FREE_AND_NULL(str);
1696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697 default:
1698 named = 0;
1699 }
1700 } else
1701 named = 0;
1702
1703 if ((named == 0) && (itemNode != NULL)) {
1704 xmlNodePtr elem;
1705
1706 if (itemNode->type == XML_ATTRIBUTE_NODE)
1707 elem = itemNode->parent;
1708 else
1709 elem = itemNode;
1710 *buf = xmlStrdup(BAD_CAST "Element '");
1711 if (elem->ns != NULL) {
1712 *buf = xmlStrcat(*buf,
1713 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1714 FREE_AND_NULL(str)
1715 } else
1716 *buf = xmlStrcat(*buf, elem->name);
1717 *buf = xmlStrcat(*buf, BAD_CAST "'");
1718
1719 }
1720 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1721 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1722 if (itemNode->ns != NULL) {
1723 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1724 itemNode->ns->href, itemNode->name));
1725 FREE_AND_NULL(str)
1726 } else
1727 *buf = xmlStrcat(*buf, itemNode->name);
1728 *buf = xmlStrcat(*buf, BAD_CAST "'");
1729 }
1730 FREE_AND_NULL(str)
1731
1732 return (*buf);
1733}
1734
1735/**
1736 * xmlSchemaFormatFacetEnumSet:
1737 * @buf: the string buffer
1738 * @type: the type holding the enumeration facets
1739 *
1740 * Builds a string consisting of all enumeration elements.
1741 *
1742 * Returns a string of all enumeration elements.
1743 */
1744static const xmlChar *
1745xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlChar **buf, xmlSchemaTypePtr type)
1747{
1748 xmlSchemaFacetPtr facet;
1749 xmlSchemaWhitespaceValueType ws;
1750 xmlChar *value = NULL;
1751 int res;
1752
1753 if (*buf != NULL)
1754 xmlFree(*buf);
1755 *buf = NULL;
1756
1757 do {
1758 /*
1759 * Use the whitespace type of the base type.
1760 */
1761 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1762 for (facet = type->facets; facet != NULL; facet = facet->next) {
1763 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1764 continue;
1765 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1766 ws, &value);
1767 if (res == -1) {
1768 xmlSchemaInternalErr(actxt,
1769 "xmlSchemaFormatFacetEnumSet",
1770 "compute the canonical lexical representation");
1771 if (*buf != NULL)
1772 xmlFree(*buf);
1773 *buf = NULL;
1774 return (NULL);
1775 }
1776 if (*buf == NULL)
1777 *buf = xmlStrdup(BAD_CAST "'");
1778 else
1779 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1780 *buf = xmlStrcat(*buf, BAD_CAST value);
1781 *buf = xmlStrcat(*buf, BAD_CAST "'");
1782 if (value != NULL) {
1783 xmlFree((xmlChar *)value);
1784 value = NULL;
1785 }
1786 }
1787 type = type->baseType;
1788 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1789
1790 return ((const xmlChar *) *buf);
1791}
1792
1793/************************************************************************
1794 * *
1795 * Error functions *
1796 * *
1797 ************************************************************************/
1798
1799#if 0
1800static void
1801xmlSchemaErrMemory(const char *msg)
1802{
1803 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1804 msg);
1805}
1806#endif
1807
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001808static void
1809xmlSchemaPSimpleErr(const char *msg)
1810{
1811 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1812 msg);
1813}
1814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001815/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 * xmlSchemaPErrMemory:
1817 * @node: a context node
1818 * @extra: extra informations
1819 *
1820 * Handle an out of memory condition
1821 */
1822static void
1823xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1824 const char *extra, xmlNodePtr node)
1825{
1826 if (ctxt != NULL)
1827 ctxt->nberrors++;
1828 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1829 extra);
1830}
1831
1832/**
1833 * xmlSchemaPErr:
1834 * @ctxt: the parsing context
1835 * @node: the context node
1836 * @error: the error code
1837 * @msg: the error message
1838 * @str1: extra data
1839 * @str2: extra data
1840 *
1841 * Handle a parser error
1842 */
1843static void
1844xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1845 const char *msg, const xmlChar * str1, const xmlChar * str2)
1846{
1847 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001848 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001849 void *data = NULL;
1850
1851 if (ctxt != NULL) {
1852 ctxt->nberrors++;
1853 channel = ctxt->error;
1854 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001855 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001856 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001857 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001858 error, XML_ERR_ERROR, NULL, 0,
1859 (const char *) str1, (const char *) str2, NULL, 0, 0,
1860 msg, str1, str2);
1861}
1862
1863/**
1864 * xmlSchemaPErr2:
1865 * @ctxt: the parsing context
1866 * @node: the context node
1867 * @node: the current child
1868 * @error: the error code
1869 * @msg: the error message
1870 * @str1: extra data
1871 * @str2: extra data
1872 *
1873 * Handle a parser error
1874 */
1875static void
1876xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1877 xmlNodePtr child, int error,
1878 const char *msg, const xmlChar * str1, const xmlChar * str2)
1879{
1880 if (child != NULL)
1881 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1882 else
1883 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1884}
1885
Daniel Veillard01fa6152004-06-29 17:04:39 +00001886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001887/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001888 * xmlSchemaPErrExt:
1889 * @ctxt: the parsing context
1890 * @node: the context node
1891 * @error: the error code
1892 * @strData1: extra data
1893 * @strData2: extra data
1894 * @strData3: extra data
1895 * @msg: the message
1896 * @str1: extra parameter for the message display
1897 * @str2: extra parameter for the message display
1898 * @str3: extra parameter for the message display
1899 * @str4: extra parameter for the message display
1900 * @str5: extra parameter for the message display
1901 *
1902 * Handle a parser error
1903 */
1904static void
1905xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1906 const xmlChar * strData1, const xmlChar * strData2,
1907 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1908 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1909 const xmlChar * str5)
1910{
1911
1912 xmlGenericErrorFunc channel = NULL;
1913 xmlStructuredErrorFunc schannel = NULL;
1914 void *data = NULL;
1915
1916 if (ctxt != NULL) {
1917 ctxt->nberrors++;
1918 channel = ctxt->error;
1919 data = ctxt->userData;
1920 schannel = ctxt->serror;
1921 }
1922 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1923 error, XML_ERR_ERROR, NULL, 0,
1924 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001925 (const char *) strData3, 0, 0, msg, str1, str2,
1926 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001927}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001928
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001929/************************************************************************
1930 * *
1931 * Allround error functions *
1932 * *
1933 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001934
1935/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001936 * xmlSchemaVTypeErrMemory:
1937 * @node: a context node
1938 * @extra: extra informations
1939 *
1940 * Handle an out of memory condition
1941 */
1942static void
1943xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1944 const char *extra, xmlNodePtr node)
1945{
1946 if (ctxt != NULL) {
1947 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001948 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001949 }
1950 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1951 extra);
1952}
1953
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001954static void
1955xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1956 const char *msg, const xmlChar *str)
1957{
1958 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1959 msg, (const char *) str);
1960}
1961
1962#define WXS_ERROR_TYPE_ERROR 1
1963#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001964/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001965 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001966 * @ctxt: the validation context
1967 * @node: the context node
1968 * @error: the error code
1969 * @msg: the error message
1970 * @str1: extra data
1971 * @str2: extra data
1972 * @str3: extra data
1973 *
1974 * Handle a validation error
1975 */
1976static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001977xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001978 xmlErrorLevel errorLevel,
1979 int error, xmlNodePtr node, int line, const char *msg,
1980 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001981 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001982{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001983 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001984 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001985 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001986
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001987 if (ctxt != NULL) {
1988 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1989 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001990 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001991 if (errorLevel != XML_ERR_WARNING) {
1992 vctxt->nberrors++;
1993 vctxt->err = error;
1994 channel = vctxt->error;
1995 } else {
1996 channel = vctxt->warning;
1997 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001998 schannel = vctxt->serror;
1999 data = vctxt->userData;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002000
2001 /*
2002 * Error node. If we specify a line number, then
2003 * do not channel any node to the error function.
2004 */
2005 if (line == 0) {
2006 if ((node == NULL) &&
2007 (vctxt->depth >= 0) &&
2008 (vctxt->inode != NULL)) {
2009 node = vctxt->inode->node;
2010 }
2011 /*
2012 * Get filename and line if no node-tree.
2013 */
2014 if ((node == NULL) &&
2015 (vctxt->parserCtxt != NULL) &&
2016 (vctxt->parserCtxt->input != NULL)) {
2017 file = vctxt->parserCtxt->input->filename;
2018 line = vctxt->parserCtxt->input->line;
2019 }
2020 } else {
2021 /*
2022 * Override the given node's (if any) position
2023 * and channel only the given line number.
2024 */
2025 node = NULL;
2026 /*
2027 * Get filename.
2028 */
2029 if (vctxt->doc != NULL)
2030 file = (const char *) vctxt->doc->URL;
2031 else if ((vctxt->parserCtxt != NULL) &&
2032 (vctxt->parserCtxt->input != NULL))
2033 file = vctxt->parserCtxt->input->filename;
2034 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002035 __xmlRaiseError(schannel, channel, data, ctxt,
2036 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002037 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002038 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002039 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002040
2041 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2042 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002043 if (errorLevel != XML_ERR_WARNING) {
2044 pctxt->nberrors++;
2045 pctxt->err = error;
2046 channel = pctxt->error;
2047 } else {
2048 channel = pctxt->warning;
2049 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002050 schannel = pctxt->serror;
2051 data = pctxt->userData;
2052 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002053 node, XML_FROM_SCHEMASP, error,
2054 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002055 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002056 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002057 } else {
2058 TODO
2059 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002060 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002061}
2062
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002063/**
2064 * xmlSchemaErr3:
2065 * @ctxt: the validation context
2066 * @node: the context node
2067 * @error: the error code
2068 * @msg: the error message
2069 * @str1: extra data
2070 * @str2: extra data
2071 * @str3: extra data
2072 *
2073 * Handle a validation error
2074 */
2075static void
2076xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2077 int error, xmlNodePtr node, const char *msg,
2078 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2079{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002080 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2081 msg, str1, str2, str3, NULL);
2082}
2083
2084static void
2085xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2086 int error, xmlNodePtr node, const char *msg,
2087 const xmlChar *str1, const xmlChar *str2,
2088 const xmlChar *str3, const xmlChar *str4)
2089{
2090 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2091 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002092}
2093
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002094static void
2095xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2096 int error, xmlNodePtr node, const char *msg,
2097 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002098{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002099 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002100}
2101
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002102static xmlChar *
2103xmlSchemaFormatNodeForError(xmlChar ** msg,
2104 xmlSchemaAbstractCtxtPtr actxt,
2105 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002106{
2107 xmlChar *str = NULL;
2108
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002109 *msg = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002110 if (node != NULL) {
2111 /*
2112 * Work on tree nodes.
2113 */
2114 if (node->type == XML_ATTRIBUTE_NODE) {
2115 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 *msg = xmlStrdup(BAD_CAST "Element '");
2118 if (elem->ns != NULL)
2119 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2120 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002121 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002122 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2123 NULL, elem->name));
2124 FREE_AND_NULL(str);
2125 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2126 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2127 } else {
2128 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002129 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130 if (node->ns != NULL)
2131 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2132 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002133 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002134 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2135 NULL, node->name));
2136 FREE_AND_NULL(str);
2137 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2138 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2139 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2140 /*
2141 * Work on node infos.
2142 */
2143 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2144 xmlSchemaNodeInfoPtr ielem =
2145 vctxt->elemInfos[vctxt->depth];
2146
2147 *msg = xmlStrdup(BAD_CAST "Element '");
2148 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2149 ielem->nsName, ielem->localName));
2150 FREE_AND_NULL(str);
2151 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2152 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2153 } else {
2154 *msg = xmlStrdup(BAD_CAST "Element '");
2155 }
2156 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2157 vctxt->inode->nsName, vctxt->inode->localName));
2158 FREE_AND_NULL(str);
2159 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002160 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2161 /*
2162 * Hmm, no node while parsing?
2163 * Return an empty string, in case NULL will break something.
2164 */
2165 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 } else {
2167 TODO
2168 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002170 /*
2171 * VAL TODO: The output of the given schema component is currently
2172 * disabled.
2173 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002174#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002175 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2176 *msg = xmlStrcat(*msg, BAD_CAST " [");
2177 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2178 NULL, type, NULL, 0));
2179 FREE_AND_NULL(str)
2180 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182#endif
2183 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002184}
2185
Daniel Veillardc0826a72004-08-10 14:17:33 +00002186static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002187xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002188 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002189 const char *message,
2190 const xmlChar *str1,
2191 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002192{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlChar *msg = NULL;
2194
2195 msg = xmlStrdup(BAD_CAST "Internal error: ");
2196 msg = xmlStrcat(msg, BAD_CAST funcName);
2197 msg = xmlStrcat(msg, BAD_CAST ", ");
2198 msg = xmlStrcat(msg, BAD_CAST message);
2199 msg = xmlStrcat(msg, BAD_CAST ".\n");
2200
2201 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2202 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002203 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002204
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002205 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002206 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002207 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208
2209 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002210}
2211
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002212static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002213xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2214 const char *funcName,
2215 const char *message)
2216{
2217 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2218}
2219
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002220#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002221static void
2222xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2223 const char *funcName,
2224 const char *message,
2225 const xmlChar *str1,
2226 const xmlChar *str2)
2227{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002228 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002229 str1, str2);
2230}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002231#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002232
2233static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002234xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2235 xmlParserErrors error,
2236 xmlNodePtr node,
2237 xmlSchemaBasicItemPtr item,
2238 const char *message,
2239 const xmlChar *str1, const xmlChar *str2,
2240 const xmlChar *str3, const xmlChar *str4)
2241{
2242 xmlChar *msg = NULL;
2243
2244 if ((node == NULL) && (item != NULL) &&
2245 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2246 node = WXS_ITEM_NODE(item);
2247 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2248 msg = xmlStrcat(msg, BAD_CAST ": ");
2249 } else
2250 xmlSchemaFormatNodeForError(&msg, actxt, node);
2251 msg = xmlStrcat(msg, (const xmlChar *) message);
2252 msg = xmlStrcat(msg, BAD_CAST ".\n");
2253 xmlSchemaErr4(actxt, error, node,
2254 (const char *) msg, str1, str2, str3, str4);
2255 FREE_AND_NULL(msg)
2256}
2257
2258static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002259xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2260 xmlParserErrors error,
2261 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002262 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002263 const char *message,
2264 const xmlChar *str1,
2265 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002266{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002267 xmlSchemaCustomErr4(actxt, error, node, item,
2268 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002269}
2270
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002271
2272
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002273static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002274xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2275 xmlParserErrors error,
2276 xmlNodePtr node,
2277 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2278 const char *message,
2279 const xmlChar *str1,
2280 const xmlChar *str2,
2281 const xmlChar *str3)
2282{
2283 xmlChar *msg = NULL;
2284
2285 xmlSchemaFormatNodeForError(&msg, actxt, node);
2286 msg = xmlStrcat(msg, (const xmlChar *) message);
2287 msg = xmlStrcat(msg, BAD_CAST ".\n");
2288
2289 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002290 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2291 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002292
2293 FREE_AND_NULL(msg)
2294}
2295
2296
2297
2298static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002299xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2300 xmlParserErrors error,
2301 xmlSchemaPSVIIDCNodePtr idcNode,
2302 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2303 const char *message,
2304 const xmlChar *str1,
2305 const xmlChar *str2)
2306{
2307 xmlChar *msg = NULL, *qname = NULL;
2308
2309 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2310 msg = xmlStrcat(msg, (const xmlChar *) message);
2311 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002312 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002313 error, NULL, idcNode->nodeLine, (const char *) msg,
2314 xmlSchemaFormatQName(&qname,
2315 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2316 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002317 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002318 FREE_AND_NULL(qname);
2319 FREE_AND_NULL(msg);
2320}
2321
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002322static int
2323xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2324 xmlNodePtr node)
2325{
2326 if (node != NULL)
2327 return (node->type);
2328 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2329 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2330 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2331 return (-1);
2332}
2333
2334static int
2335xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2336{
2337 switch (item->type) {
2338 case XML_SCHEMA_TYPE_COMPLEX:
2339 case XML_SCHEMA_TYPE_SIMPLE:
2340 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2341 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002342 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002343 case XML_SCHEMA_TYPE_GROUP:
2344 return (1);
2345 case XML_SCHEMA_TYPE_ELEMENT:
2346 if ( ((xmlSchemaElementPtr) item)->flags &
2347 XML_SCHEMAS_ELEM_GLOBAL)
2348 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002349 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350 case XML_SCHEMA_TYPE_ATTRIBUTE:
2351 if ( ((xmlSchemaAttributePtr) item)->flags &
2352 XML_SCHEMAS_ATTR_GLOBAL)
2353 return(1);
2354 break;
2355 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002356 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002357 return(1);
2358 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002359 return (0);
2360}
2361
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002362static void
2363xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2364 xmlParserErrors error,
2365 xmlNodePtr node,
2366 const xmlChar *value,
2367 xmlSchemaTypePtr type,
2368 int displayValue)
2369{
2370 xmlChar *msg = NULL;
2371
2372 xmlSchemaFormatNodeForError(&msg, actxt, node);
2373
2374 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2375 XML_ATTRIBUTE_NODE))
2376 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2377 else
2378 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2379 "value of ");
2380
2381 if (! xmlSchemaIsGlobalItem(type))
2382 msg = xmlStrcat(msg, BAD_CAST "the local ");
2383 else
2384 msg = xmlStrcat(msg, BAD_CAST "the ");
2385
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002386 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002387 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002388 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002390 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002391 msg = xmlStrcat(msg, BAD_CAST "union type");
2392
2393 if (xmlSchemaIsGlobalItem(type)) {
2394 xmlChar *str = NULL;
2395 msg = xmlStrcat(msg, BAD_CAST " '");
2396 if (type->builtInType != 0) {
2397 msg = xmlStrcat(msg, BAD_CAST "xs:");
2398 msg = xmlStrcat(msg, type->name);
2399 } else
2400 msg = xmlStrcat(msg,
2401 xmlSchemaFormatQName(&str,
2402 type->targetNamespace, type->name));
2403 msg = xmlStrcat(msg, BAD_CAST "'");
2404 FREE_AND_NULL(str);
2405 }
2406 msg = xmlStrcat(msg, BAD_CAST ".\n");
2407 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2408 XML_ATTRIBUTE_NODE))
2409 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2410 else
2411 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2412 FREE_AND_NULL(msg)
2413}
2414
Daniel Veillardc0826a72004-08-10 14:17:33 +00002415static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002416xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2417 xmlSchemaNodeInfoPtr ni,
2418 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002420 if (node != NULL) {
2421 if (node->ns != NULL)
2422 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2423 else
2424 return (xmlSchemaFormatQName(str, NULL, node->name));
2425 } else if (ni != NULL)
2426 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2427 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002428}
2429
Daniel Veillardc0826a72004-08-10 14:17:33 +00002430static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2432 xmlParserErrors error,
2433 xmlSchemaAttrInfoPtr ni,
2434 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002435{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002436 xmlChar *msg = NULL, *str = NULL;
2437
2438 xmlSchemaFormatNodeForError(&msg, actxt, node);
2439 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2440 xmlSchemaErr(actxt, error, node, (const char *) msg,
2441 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2442 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002443 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002444 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002445}
2446
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2449 xmlParserErrors error,
2450 xmlNodePtr node,
2451 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002452 const char *message,
2453 int nbval,
2454 int nbneg,
2455 xmlChar **values)
2456{
2457 xmlChar *str = NULL, *msg = NULL;
2458 xmlChar *localName, *nsName;
2459 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002460 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002461
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002462 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002463 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002464 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002465 /*
2466 * Note that is does not make sense to report that we have a
2467 * wildcard here, since the wildcard might be unfolded into
2468 * multiple transitions.
2469 */
2470 if (nbval + nbneg > 0) {
2471 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002472 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002473 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002474 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002475 nsName = NULL;
2476
2477 for (i = 0; i < nbval + nbneg; i++) {
2478 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002479 if (cur == NULL)
2480 continue;
2481 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2482 (cur[3] == ' ')) {
2483 is_not = 1;
2484 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002485 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002486 } else {
2487 is_not = 0;
2488 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002489 /*
2490 * Get the local name.
2491 */
2492 localName = NULL;
2493
2494 end = cur;
2495 if (*end == '*') {
2496 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002497 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002498 } else {
2499 while ((*end != 0) && (*end != '|'))
2500 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002501 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002502 }
2503 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002504 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002505 /*
2506 * Skip "*|*" if they come with negated expressions, since
2507 * they represent the same negated wildcard.
2508 */
2509 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2510 /*
2511 * Get the namespace name.
2512 */
2513 cur = end;
2514 if (*end == '*') {
2515 nsName = xmlStrdup(BAD_CAST "{*}");
2516 } else {
2517 while (*end != 0)
2518 end++;
2519
2520 if (i >= nbval)
2521 nsName = xmlStrdup(BAD_CAST "{##other:");
2522 else
2523 nsName = xmlStrdup(BAD_CAST "{");
2524
2525 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2526 nsName = xmlStrcat(nsName, BAD_CAST "}");
2527 }
2528 str = xmlStrcat(str, BAD_CAST nsName);
2529 FREE_AND_NULL(nsName)
2530 } else {
2531 FREE_AND_NULL(localName);
2532 continue;
2533 }
2534 }
2535 str = xmlStrcat(str, BAD_CAST localName);
2536 FREE_AND_NULL(localName);
2537
2538 if (i < nbval + nbneg -1)
2539 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002541 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002542 msg = xmlStrcat(msg, BAD_CAST str);
2543 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002544 } else
2545 msg = xmlStrcat(msg, BAD_CAST "\n");
2546 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002547 xmlFree(msg);
2548}
2549
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002550static void
2551xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2552 xmlParserErrors error,
2553 xmlNodePtr node,
2554 const xmlChar *value,
2555 unsigned long length,
2556 xmlSchemaTypePtr type,
2557 xmlSchemaFacetPtr facet,
2558 const char *message,
2559 const xmlChar *str1,
2560 const xmlChar *str2)
2561{
2562 xmlChar *str = NULL, *msg = NULL;
2563 xmlSchemaTypeType facetType;
2564 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2565
2566 xmlSchemaFormatNodeForError(&msg, actxt, node);
2567 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2568 facetType = XML_SCHEMA_FACET_ENUMERATION;
2569 /*
2570 * If enumerations are validated, one must not expect the
2571 * facet to be given.
2572 */
2573 } else
2574 facetType = facet->type;
2575 msg = xmlStrcat(msg, BAD_CAST "[");
2576 msg = xmlStrcat(msg, BAD_CAST "facet '");
2577 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2578 msg = xmlStrcat(msg, BAD_CAST "'] ");
2579 if (message == NULL) {
2580 /*
2581 * Use a default message.
2582 */
2583 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2584 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2585 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2586
2587 char len[25], actLen[25];
2588
2589 /* FIXME, TODO: What is the max expected string length of the
2590 * this value?
2591 */
2592 if (nodeType == XML_ATTRIBUTE_NODE)
2593 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2594 else
2595 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2596
2597 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2598 snprintf(actLen, 24, "%lu", length);
2599
2600 if (facetType == XML_SCHEMA_FACET_LENGTH)
2601 msg = xmlStrcat(msg,
2602 BAD_CAST "this differs from the allowed length of '%s'.\n");
2603 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2604 msg = xmlStrcat(msg,
2605 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2606 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2607 msg = xmlStrcat(msg,
2608 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2609
2610 if (nodeType == XML_ATTRIBUTE_NODE)
2611 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2612 value, (const xmlChar *) actLen, (const xmlChar *) len);
2613 else
2614 xmlSchemaErr(actxt, error, node, (const char *) msg,
2615 (const xmlChar *) actLen, (const xmlChar *) len);
2616
2617 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2618 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2619 "of the set {%s}.\n");
2620 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2621 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2622 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2623 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2624 "by the pattern '%s'.\n");
2625 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2626 facet->value);
2627 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2628 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2629 "minimum value allowed ('%s').\n");
2630 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2631 facet->value);
2632 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2633 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2634 "maximum value allowed ('%s').\n");
2635 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2636 facet->value);
2637 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2638 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2639 "'%s'.\n");
2640 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2641 facet->value);
2642 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2643 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2644 "'%s'.\n");
2645 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2646 facet->value);
2647 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2648 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2649 "digits than are allowed ('%s').\n");
2650 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2651 facet->value);
2652 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2653 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2654 "digits than are allowed ('%s').\n");
2655 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2656 facet->value);
2657 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2658 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2659 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2660 } else {
2661 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2662 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2663 }
2664 } else {
2665 msg = xmlStrcat(msg, (const xmlChar *) message);
2666 msg = xmlStrcat(msg, BAD_CAST ".\n");
2667 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2668 }
2669 FREE_AND_NULL(str)
2670 xmlFree(msg);
2671}
2672
2673#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002674 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002675
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002676#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002677
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002678#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2679#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002680
2681#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2682
2683
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002684/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002685 * xmlSchemaPMissingAttrErr:
2686 * @ctxt: the schema validation context
2687 * @ownerDes: the designation of the owner
2688 * @ownerName: the name of the owner
2689 * @ownerItem: the owner as a schema object
2690 * @ownerElem: the owner as an element node
2691 * @node: the parent element node of the missing attribute node
2692 * @type: the corresponding type of the attribute node
2693 *
2694 * Reports an illegal attribute.
2695 */
2696static void
2697xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002698 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002699 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002700 xmlNodePtr ownerElem,
2701 const char *name,
2702 const char *message)
2703{
2704 xmlChar *des = NULL;
2705
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002706 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2707
Daniel Veillardc0826a72004-08-10 14:17:33 +00002708 if (message != NULL)
2709 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002710 else
2711 xmlSchemaPErr(ctxt, ownerElem, error,
2712 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002713 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002715}
2716
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Daniel Veillardc0826a72004-08-10 14:17:33 +00002718/**
2719 * xmlSchemaPResCompAttrErr:
2720 * @ctxt: the schema validation context
2721 * @error: the error code
2722 * @ownerDes: the designation of the owner
2723 * @ownerItem: the owner as a schema object
2724 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002725 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002726 * @refName: the referenced local name
2727 * @refURI: the referenced namespace URI
2728 * @message: optional message
2729 *
2730 * Used to report QName attribute values that failed to resolve
2731 * to schema components.
2732 */
2733static void
2734xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002735 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002736 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002737 xmlNodePtr ownerElem,
2738 const char *name,
2739 const xmlChar *refName,
2740 const xmlChar *refURI,
2741 xmlSchemaTypeType refType,
2742 const char *refTypeStr)
2743{
2744 xmlChar *des = NULL, *strA = NULL;
2745
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002746 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002747 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002748 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002749 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002750 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2752 "%s.\n", BAD_CAST des, BAD_CAST name,
2753 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002754 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002755 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002756 FREE_AND_NULL(strA)
2757}
2758
William M. Brack2f2a6632004-08-20 23:09:47 +00002759/**
2760 * xmlSchemaPCustomAttrErr:
2761 * @ctxt: the schema parser context
2762 * @error: the error code
2763 * @ownerDes: the designation of the owner
2764 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002765 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002766 *
2767 * Reports an illegal attribute during the parse.
2768 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002769static void
2770xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002771 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002772 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002773 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002774 xmlAttrPtr attr,
2775 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002776{
2777 xmlChar *des = NULL;
2778
2779 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002780 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002781 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002782 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002783 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002784 } else
2785 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002786 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002788 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2789 if (ownerDes == NULL)
2790 FREE_AND_NULL(des);
2791}
2792
2793/**
2794 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002795 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002796 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002797 * @ownerDes: the designation of the attribute's owner
2798 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002800 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002801 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002802 */
2803static void
2804xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002805 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002806 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002807 xmlAttrPtr attr)
2808{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002809 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002810
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002811 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2812 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2813 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2814 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2815 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002816 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002817 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818}
2819
William M. Brack2f2a6632004-08-20 23:09:47 +00002820/**
2821 * xmlSchemaPCustomErr:
2822 * @ctxt: the schema parser context
2823 * @error: the error code
2824 * @itemDes: the designation of the schema item
2825 * @item: the schema item
2826 * @itemElem: the node of the schema item
2827 * @message: the error message
2828 * @str1: an optional param for the error message
2829 * @str2: an optional param for the error message
2830 * @str3: an optional param for the error message
2831 *
2832 * Reports an error during parsing.
2833 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002834static void
2835xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002837 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002838 xmlNodePtr itemElem,
2839 const char *message,
2840 const xmlChar *str1,
2841 const xmlChar *str2,
2842 const xmlChar *str3)
2843{
2844 xmlChar *des = NULL, *msg = NULL;
2845
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002846 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847 msg = xmlStrdup(BAD_CAST "%s: ");
2848 msg = xmlStrcat(msg, (const xmlChar *) message);
2849 msg = xmlStrcat(msg, BAD_CAST ".\n");
2850 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002851 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002852 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002853 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002854 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855 FREE_AND_NULL(msg);
2856}
2857
William M. Brack2f2a6632004-08-20 23:09:47 +00002858/**
2859 * xmlSchemaPCustomErr:
2860 * @ctxt: the schema parser context
2861 * @error: the error code
2862 * @itemDes: the designation of the schema item
2863 * @item: the schema item
2864 * @itemElem: the node of the schema item
2865 * @message: the error message
2866 * @str1: the optional param for the error message
2867 *
2868 * Reports an error during parsing.
2869 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002870static void
2871xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002872 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002873 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002874 xmlNodePtr itemElem,
2875 const char *message,
2876 const xmlChar *str1)
2877{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002878 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002879 str1, NULL, NULL);
2880}
2881
William M. Brack2f2a6632004-08-20 23:09:47 +00002882/**
2883 * xmlSchemaPAttrUseErr:
2884 * @ctxt: the schema parser context
2885 * @error: the error code
2886 * @itemDes: the designation of the schema type
2887 * @item: the schema type
2888 * @itemElem: the node of the schema type
2889 * @attr: the invalid schema attribute
2890 * @message: the error message
2891 * @str1: the optional param for the error message
2892 *
2893 * Reports an attribute use error during parsing.
2894 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002895static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002896xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002897 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002898 xmlNodePtr node,
2899 xmlSchemaBasicItemPtr ownerItem,
2900 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002901 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002902 const xmlChar *str1, const xmlChar *str2,
2903 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002904{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002905 xmlChar *str = NULL, *msg = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002906
2907 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2908 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002909 msg = xmlStrcat(msg,
2910 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002911 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002912 FREE_AND_NULL(str);
2913 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002914 msg = xmlStrcat(msg, (const xmlChar *) message);
2915 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002916 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2917 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002918 xmlFree(msg);
2919}
2920
William M. Brack2f2a6632004-08-20 23:09:47 +00002921/**
2922 * xmlSchemaPIllegalFacetAtomicErr:
2923 * @ctxt: the schema parser context
2924 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002925 * @type: the schema type
2926 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00002927 * @facet: the illegal facet
2928 *
2929 * Reports an illegal facet for atomic simple types.
2930 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002931static void
2932xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002933 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002934 xmlSchemaTypePtr type,
2935 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002936 xmlSchemaFacetPtr facet)
2937{
2938 xmlChar *des = NULL, *strT = NULL;
2939
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002940 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2941 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002942 "%s: The facet '%s' is not allowed on types derived from the "
2943 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002944 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002945 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002946 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002947 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002948 FREE_AND_NULL(strT);
2949}
2950
William M. Brack2f2a6632004-08-20 23:09:47 +00002951/**
2952 * xmlSchemaPIllegalFacetListUnionErr:
2953 * @ctxt: the schema parser context
2954 * @error: the error code
2955 * @itemDes: the designation of the schema item involved
2956 * @item: the schema item involved
2957 * @facet: the illegal facet
2958 *
2959 * Reports an illegal facet for <list> and <union>.
2960 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002961static void
2962xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002963 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002964 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002965 xmlSchemaFacetPtr facet)
2966{
2967 xmlChar *des = NULL, *strT = NULL;
2968
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002969 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
2970 type->node);
2971 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002972 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002973 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002974 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002975 FREE_AND_NULL(strT);
2976}
2977
2978/**
2979 * xmlSchemaPMutualExclAttrErr:
2980 * @ctxt: the schema validation context
2981 * @error: the error code
2982 * @elemDes: the designation of the parent element node
2983 * @attr: the bad attribute node
2984 * @type: the corresponding type of the attribute node
2985 *
2986 * Reports an illegal attribute.
2987 */
2988static void
2989xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2990 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002991 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002992 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002993 const char *name1,
2994 const char *name2)
2995{
2996 xmlChar *des = NULL;
2997
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002998 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002999 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003000 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003001 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003002 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003}
3004
3005/**
3006 * xmlSchemaPSimpleTypeErr:
3007 * @ctxt: the schema validation context
3008 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003009 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003010 * @ownerDes: the designation of the owner
3011 * @ownerItem: the schema object if existent
3012 * @node: the validated node
3013 * @value: the validated value
3014 *
3015 * Reports a simple type validation error.
3016 * TODO: Should this report the value of an element as well?
3017 */
3018static void
3019xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3020 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003021 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003022 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003023 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003024 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003025 const xmlChar *value,
3026 const char *message,
3027 const xmlChar *str1,
3028 const xmlChar *str2)
3029{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003030 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003031
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003032 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003033 if (message == NULL) {
3034 /*
3035 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003036 */
3037 if (type != NULL) {
3038 if (node->type == XML_ATTRIBUTE_NODE)
3039 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3040 else
3041 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3042 "valid value of ");
3043 if (! xmlSchemaIsGlobalItem(type))
3044 msg = xmlStrcat(msg, BAD_CAST "the local ");
3045 else
3046 msg = xmlStrcat(msg, BAD_CAST "the ");
3047
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003048 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003049 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003050 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003051 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003052 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003053 msg = xmlStrcat(msg, BAD_CAST "union type");
3054
3055 if (xmlSchemaIsGlobalItem(type)) {
3056 xmlChar *str = NULL;
3057 msg = xmlStrcat(msg, BAD_CAST " '");
3058 if (type->builtInType != 0) {
3059 msg = xmlStrcat(msg, BAD_CAST "xs:");
3060 msg = xmlStrcat(msg, type->name);
3061 } else
3062 msg = xmlStrcat(msg,
3063 xmlSchemaFormatQName(&str,
3064 type->targetNamespace, type->name));
3065 msg = xmlStrcat(msg, BAD_CAST "'.");
3066 FREE_AND_NULL(str);
3067 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003069 if (node->type == XML_ATTRIBUTE_NODE)
3070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3071 else
3072 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3073 "valid.");
3074 }
3075 if (expected) {
3076 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3077 msg = xmlStrcat(msg, BAD_CAST expected);
3078 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3079 } else
3080 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003081 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003082 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3083 else
3084 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3085 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003086 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003087 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003088 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003089 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003091 /* Cleanup. */
3092 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003093}
3094
William M. Brack2f2a6632004-08-20 23:09:47 +00003095/**
3096 * xmlSchemaPContentErr:
3097 * @ctxt: the schema parser context
3098 * @error: the error code
3099 * @onwerDes: the designation of the holder of the content
3100 * @ownerItem: the owner item of the holder of the content
3101 * @ownerElem: the node of the holder of the content
3102 * @child: the invalid child node
3103 * @message: the optional error message
3104 * @content: the optional string describing the correct content
3105 *
3106 * Reports an error concerning the content of a schema element.
3107 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003108static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003109xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003110 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003111 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003112 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003113 xmlNodePtr child,
3114 const char *message,
3115 const char *content)
3116{
3117 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003118
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003119 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003120 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003121 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3122 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003123 BAD_CAST des, BAD_CAST message);
3124 else {
3125 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003126 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3127 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003128 BAD_CAST des, BAD_CAST content);
3129 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003130 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3131 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003132 BAD_CAST des, NULL);
3133 }
3134 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003135 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003136}
3137
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003138/************************************************************************
3139 * *
3140 * Streamable error functions *
3141 * *
3142 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003143
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003144
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003145
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003146
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003147/************************************************************************
3148 * *
3149 * Validation helper functions *
3150 * *
3151 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003152
Daniel Veillardc0826a72004-08-10 14:17:33 +00003153
Daniel Veillard4255d502002-04-16 15:50:10 +00003154/************************************************************************
3155 * *
3156 * Allocation functions *
3157 * *
3158 ************************************************************************/
3159
3160/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003161 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003162 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003163 *
3164 * Allocate a new Schema structure.
3165 *
3166 * Returns the newly allocated structure or NULL in case or error
3167 */
3168static xmlSchemaPtr
3169xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3170{
3171 xmlSchemaPtr ret;
3172
3173 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3174 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003175 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 return (NULL);
3177 }
3178 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003179 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003180 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003181
3182 return (ret);
3183}
3184
3185/**
3186 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003187 *
3188 * Allocate a new Facet structure.
3189 *
3190 * Returns the newly allocated structure or NULL in case or error
3191 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003192xmlSchemaFacetPtr
3193xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003194{
3195 xmlSchemaFacetPtr ret;
3196
3197 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3198 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 return (NULL);
3200 }
3201 memset(ret, 0, sizeof(xmlSchemaFacet));
3202
3203 return (ret);
3204}
3205
3206/**
3207 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003208 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003209 * @node: a node
3210 *
3211 * Allocate a new annotation structure.
3212 *
3213 * Returns the newly allocated structure or NULL in case or error
3214 */
3215static xmlSchemaAnnotPtr
3216xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3217{
3218 xmlSchemaAnnotPtr ret;
3219
3220 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3221 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003222 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003223 return (NULL);
3224 }
3225 memset(ret, 0, sizeof(xmlSchemaAnnot));
3226 ret->content = node;
3227 return (ret);
3228}
3229
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003230static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003231xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003232{
3233 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003234
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003235 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3236 if (ret == NULL) {
3237 xmlSchemaPErrMemory(NULL,
3238 "allocating an item list structure", NULL);
3239 return (NULL);
3240 }
3241 memset(ret, 0, sizeof(xmlSchemaItemList));
3242 return (ret);
3243}
3244
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003245static void
3246xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3247{
3248 if (list->items != NULL) {
3249 xmlFree(list->items);
3250 list->items = NULL;
3251 }
3252 list->nbItems = 0;
3253 list->sizeItems = 0;
3254}
3255
3256static int
3257xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3258{
3259 if (list->items == NULL) {
3260 list->items = (void **) xmlMalloc(
3261 20 * sizeof(void *));
3262 if (list->items == NULL) {
3263 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3264 return(-1);
3265 }
3266 list->sizeItems = 20;
3267 } else if (list->sizeItems <= list->nbItems) {
3268 list->sizeItems *= 2;
3269 list->items = (void **) xmlRealloc(list->items,
3270 list->sizeItems * sizeof(void *));
3271 if (list->items == NULL) {
3272 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3273 list->sizeItems = 0;
3274 return(-1);
3275 }
3276 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003277 list->items[list->nbItems++] = item;
3278 return(0);
3279}
3280
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003281static int
3282xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3283 int initialSize,
3284 void *item)
3285{
3286 if (list->items == NULL) {
3287 if (initialSize <= 0)
3288 initialSize = 1;
3289 list->items = (void **) xmlMalloc(
3290 initialSize * sizeof(void *));
3291 if (list->items == NULL) {
3292 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3293 return(-1);
3294 }
3295 list->sizeItems = initialSize;
3296 } else if (list->sizeItems <= list->nbItems) {
3297 list->sizeItems *= 2;
3298 list->items = (void **) xmlRealloc(list->items,
3299 list->sizeItems * sizeof(void *));
3300 if (list->items == NULL) {
3301 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3302 list->sizeItems = 0;
3303 return(-1);
3304 }
3305 }
3306 list->items[list->nbItems++] = item;
3307 return(0);
3308}
3309
3310static int
3311xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3312{
3313 if (list->items == NULL) {
3314 list->items = (void **) xmlMalloc(
3315 20 * sizeof(void *));
3316 if (list->items == NULL) {
3317 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3318 return(-1);
3319 }
3320 list->sizeItems = 20;
3321 } else if (list->sizeItems <= list->nbItems) {
3322 list->sizeItems *= 2;
3323 list->items = (void **) xmlRealloc(list->items,
3324 list->sizeItems * sizeof(void *));
3325 if (list->items == NULL) {
3326 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3327 list->sizeItems = 0;
3328 return(-1);
3329 }
3330 }
3331 /*
3332 * Just append if the index is greater/equal than the item count.
3333 */
3334 if (idx >= list->nbItems) {
3335 list->items[list->nbItems++] = item;
3336 } else {
3337 int i;
3338 for (i = list->nbItems; i > idx; i--)
3339 list->items[i] = list->items[i-1];
3340 list->items[idx] = item;
3341 list->nbItems++;
3342 }
3343 return(0);
3344}
3345
3346#if 0 /* enable if ever needed */
3347static int
3348xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3349 int initialSize,
3350 void *item,
3351 int idx)
3352{
3353 if (list->items == NULL) {
3354 if (initialSize <= 0)
3355 initialSize = 1;
3356 list->items = (void **) xmlMalloc(
3357 initialSize * sizeof(void *));
3358 if (list->items == NULL) {
3359 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3360 return(-1);
3361 }
3362 list->sizeItems = initialSize;
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#endif
3388
3389static int
3390xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3391{
3392 int i;
3393 if ((list->items == NULL) || (idx >= list->nbItems)) {
3394 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3395 "index error.\n");
3396 return(-1);
3397 }
3398
3399 if (list->nbItems == 1) {
3400 /* TODO: Really free the list? */
3401 xmlFree(list->items);
3402 list->items = NULL;
3403 list->nbItems = 0;
3404 list->sizeItems = 0;
3405 } else if (list->nbItems -1 == idx) {
3406 list->nbItems--;
3407 } else {
3408 for (i = idx; i < list->nbItems -1; i++)
3409 list->items[i] = list->items[i+1];
3410 list->nbItems--;
3411 }
3412 return(0);
3413}
3414
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003415/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003416 * xmlSchemaItemListFree:
3417 * @annot: a schema type structure
3418 *
3419 * Deallocate a annotation structure
3420 */
3421static void
3422xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3423{
3424 if (list == NULL)
3425 return;
3426 if (list->items != NULL)
3427 xmlFree(list->items);
3428 xmlFree(list);
3429}
3430
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003431static void
3432xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003433{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003434 if (bucket == NULL)
3435 return;
3436 if (bucket->globals != NULL) {
3437 xmlSchemaComponentListFree(bucket->globals);
3438 xmlSchemaItemListFree(bucket->globals);
3439 }
3440 if (bucket->locals != NULL) {
3441 xmlSchemaComponentListFree(bucket->locals);
3442 xmlSchemaItemListFree(bucket->locals);
3443 }
3444 if (bucket->relations != NULL) {
3445 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3446 do {
3447 prev = cur;
3448 cur = cur->next;
3449 xmlFree(prev);
3450 } while (cur != NULL);
3451 }
3452 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3453 xmlFreeDoc(bucket->doc);
3454 }
3455 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003456 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3457 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003458 }
3459 xmlFree(bucket);
3460}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003461
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003462static xmlSchemaBucketPtr
3463xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003464 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003465{
3466 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003467 int size;
3468 xmlSchemaPtr mainSchema;
3469
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003470 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003471 PERROR_INT("xmlSchemaBucketCreate",
3472 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003473 return(NULL);
3474 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003475 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003476 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003477 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003478 size = sizeof(xmlSchemaInclude);
3479 else
3480 size = sizeof(xmlSchemaImport);
3481 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3482 if (ret == NULL) {
3483 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3484 return(NULL);
3485 }
3486 memset(ret, 0, size);
3487 ret->targetNamespace = targetNamespace;
3488 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003489 ret->globals = xmlSchemaItemListCreate();
3490 if (ret->globals == NULL) {
3491 xmlFree(ret);
3492 return(NULL);
3493 }
3494 ret->locals = xmlSchemaItemListCreate();
3495 if (ret->locals == NULL) {
3496 xmlFree(ret);
3497 return(NULL);
3498 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003499 /*
3500 * The following will assure that only the first bucket is marked as
3501 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3502 * For each following import buckets an xmlSchema will be created.
3503 */
3504 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003505 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003506 PERROR_INT("xmlSchemaBucketCreate",
3507 "first bucket but it's an include or redefine");
3508 xmlSchemaBucketFree(ret);
3509 return(NULL);
3510 }
3511 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3512 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3513 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003514 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3515 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003516 } else {
3517 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3518 PERROR_INT("xmlSchemaBucketCreate",
3519 "main bucket but it's not the first one");
3520 xmlSchemaBucketFree(ret);
3521 return(NULL);
3522 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3523 /*
3524 * Create a schema for imports.
3525 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003526 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3527 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003528 xmlSchemaBucketFree(ret);
3529 return(NULL);
3530 }
3531 }
3532 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003533 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003534 int res;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003535 /* Imports go into the "schemasImports" slot of the main *schema*. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003536 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003537 mainSchema->schemasImports = xmlHashCreateDict(5,
3538 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003539 if (mainSchema->schemasImports == NULL) {
3540 xmlSchemaBucketFree(ret);
3541 return(NULL);
3542 }
3543 }
3544 if (targetNamespace == NULL)
3545 res = xmlHashAddEntry(mainSchema->schemasImports,
3546 XML_SCHEMAS_NO_NAMESPACE, ret);
3547 else
3548 res = xmlHashAddEntry(mainSchema->schemasImports,
3549 targetNamespace, ret);
3550 if (res != 0) {
3551 PERROR_INT("xmlSchemaBucketCreate",
3552 "failed to add the schema bucket to the hash");
3553 xmlSchemaBucketFree(ret);
3554 return(NULL);
3555 }
3556 } else {
3557 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003558 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3559 WXS_INCBUCKET(ret)->ownerImport =
3560 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003561 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003562 WXS_INCBUCKET(ret)->ownerImport =
3563 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003564
3565 /* Includes got into the "includes" slot of the *main* schema. */
3566 if (mainSchema->includes == NULL) {
3567 mainSchema->includes = xmlSchemaItemListCreate();
3568 if (mainSchema->includes == NULL) {
3569 xmlSchemaBucketFree(ret);
3570 return(NULL);
3571 }
3572 }
3573 xmlSchemaItemListAdd(mainSchema->includes, ret);
3574 }
3575 /*
3576 * Add to list of all buckets; this is used for lookup
3577 * during schema construction time only.
3578 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003579 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003580 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003581 return(ret);
3582}
3583
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003584static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003585xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003586{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003587 if (*list == NULL) {
3588 *list = xmlSchemaItemListCreate();
3589 if (*list == NULL)
3590 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003591 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003592 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003593 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003594}
3595
3596/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003597 * xmlSchemaFreeAnnot:
3598 * @annot: a schema type structure
3599 *
3600 * Deallocate a annotation structure
3601 */
3602static void
3603xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3604{
3605 if (annot == NULL)
3606 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003607 if (annot->next == NULL) {
3608 xmlFree(annot);
3609 } else {
3610 xmlSchemaAnnotPtr prev;
3611
3612 do {
3613 prev = annot;
3614 annot = annot->next;
3615 xmlFree(prev);
3616 } while (annot != NULL);
3617 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003618}
3619
3620/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 * xmlSchemaFreeNotation:
3622 * @schema: a schema notation structure
3623 *
3624 * Deallocate a Schema Notation structure.
3625 */
3626static void
3627xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3628{
3629 if (nota == NULL)
3630 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003631 xmlFree(nota);
3632}
3633
3634/**
3635 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003636 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003637 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003638 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 */
3640static void
3641xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3642{
3643 if (attr == NULL)
3644 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003645 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003646 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003647 if (attr->defVal != NULL)
3648 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 xmlFree(attr);
3650}
3651
3652/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003653 * xmlSchemaFreeAttributeUse:
3654 * @use: an attribute use
3655 *
3656 * Deallocates an attribute use structure.
3657 */
3658static void
3659xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3660{
3661 if (use == NULL)
3662 return;
3663 if (use->annot != NULL)
3664 xmlSchemaFreeAnnot(use->annot);
3665 if (use->defVal != NULL)
3666 xmlSchemaFreeValue(use->defVal);
3667 xmlFree(use);
3668}
3669
3670/**
3671 * xmlSchemaFreeAttributeUseProhib:
3672 * @prohib: an attribute use prohibition
3673 *
3674 * Deallocates an attribute use structure.
3675 */
3676static void
3677xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3678{
3679 if (prohib == NULL)
3680 return;
3681 xmlFree(prohib);
3682}
3683
3684/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003685 * xmlSchemaFreeWildcardNsSet:
3686 * set: a schema wildcard namespace
3687 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003688 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003689 */
3690static void
3691xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3692{
3693 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003694
Daniel Veillard3646d642004-06-02 19:19:14 +00003695 while (set != NULL) {
3696 next = set->next;
3697 xmlFree(set);
3698 set = next;
3699 }
3700}
3701
3702/**
3703 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003704 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003705 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003706 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003707 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003708void
Daniel Veillard3646d642004-06-02 19:19:14 +00003709xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3710{
3711 if (wildcard == NULL)
3712 return;
3713 if (wildcard->annot != NULL)
3714 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003715 if (wildcard->nsSet != NULL)
3716 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3717 if (wildcard->negNsSet != NULL)
3718 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003719 xmlFree(wildcard);
3720}
3721
3722/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003723 * xmlSchemaFreeAttributeGroup:
3724 * @schema: a schema attribute group structure
3725 *
3726 * Deallocate a Schema Attribute Group structure.
3727 */
3728static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003729xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003730{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003731 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003732 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003733 if (attrGr->annot != NULL)
3734 xmlSchemaFreeAnnot(attrGr->annot);
3735 if (attrGr->attrUses != NULL)
3736 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3737 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003738}
3739
3740/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003741 * xmlSchemaFreeQNameRef:
3742 * @item: a QName reference structure
3743 *
3744 * Deallocatea a QName reference structure.
3745 */
3746static void
3747xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3748{
3749 xmlFree(item);
3750}
3751
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003752/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003753 * xmlSchemaFreeTypeLinkList:
3754 * @alink: a type link
3755 *
3756 * Deallocate a list of types.
3757 */
3758static void
3759xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3760{
3761 xmlSchemaTypeLinkPtr next;
3762
3763 while (link != NULL) {
3764 next = link->next;
3765 xmlFree(link);
3766 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003767 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003768}
3769
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003770static void
3771xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3772{
3773 xmlSchemaIDCStateObjPtr next;
3774 while (sto != NULL) {
3775 next = sto->next;
3776 if (sto->history != NULL)
3777 xmlFree(sto->history);
3778 if (sto->xpathCtxt != NULL)
3779 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3780 xmlFree(sto);
3781 sto = next;
3782 }
3783}
3784
3785/**
3786 * xmlSchemaFreeIDC:
3787 * @idc: a identity-constraint definition
3788 *
3789 * Deallocates an identity-constraint definition.
3790 */
3791static void
3792xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3793{
3794 xmlSchemaIDCSelectPtr cur, prev;
3795
3796 if (idcDef == NULL)
3797 return;
3798 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003799 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003800 /* Selector */
3801 if (idcDef->selector != NULL) {
3802 if (idcDef->selector->xpathComp != NULL)
3803 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3804 xmlFree(idcDef->selector);
3805 }
3806 /* Fields */
3807 if (idcDef->fields != NULL) {
3808 cur = idcDef->fields;
3809 do {
3810 prev = cur;
3811 cur = cur->next;
3812 if (prev->xpathComp != NULL)
3813 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003814 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003815 } while (cur != NULL);
3816 }
3817 xmlFree(idcDef);
3818}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003819
Daniel Veillard01fa6152004-06-29 17:04:39 +00003820/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003821 * xmlSchemaFreeElement:
3822 * @schema: a schema element structure
3823 *
3824 * Deallocate a Schema Element structure.
3825 */
3826static void
3827xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3828{
3829 if (elem == NULL)
3830 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003831 if (elem->annot != NULL)
3832 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003833 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003834 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003835 if (elem->defVal != NULL)
3836 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003837 xmlFree(elem);
3838}
3839
3840/**
3841 * xmlSchemaFreeFacet:
3842 * @facet: a schema facet structure
3843 *
3844 * Deallocate a Schema Facet structure.
3845 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003846void
Daniel Veillard4255d502002-04-16 15:50:10 +00003847xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3848{
3849 if (facet == NULL)
3850 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003851 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003852 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003853 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003854 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003855 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003856 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003857 xmlFree(facet);
3858}
3859
3860/**
3861 * xmlSchemaFreeType:
3862 * @type: a schema type structure
3863 *
3864 * Deallocate a Schema Type structure.
3865 */
3866void
3867xmlSchemaFreeType(xmlSchemaTypePtr type)
3868{
3869 if (type == NULL)
3870 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003872 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003873 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003874 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003875
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 facet = type->facets;
3877 while (facet != NULL) {
3878 next = facet->next;
3879 xmlSchemaFreeFacet(facet);
3880 facet = next;
3881 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003883 if (type->attrUses != NULL)
3884 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003885 if (type->memberTypes != NULL)
3886 xmlSchemaFreeTypeLinkList(type->memberTypes);
3887 if (type->facetSet != NULL) {
3888 xmlSchemaFacetLinkPtr next, link;
3889
3890 link = type->facetSet;
3891 do {
3892 next = link->next;
3893 xmlFree(link);
3894 link = next;
3895 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003896 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003897 if (type->contModel != NULL)
3898 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 xmlFree(type);
3900}
3901
3902/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003903 * xmlSchemaFreeModelGroupDef:
3904 * @item: a schema model group definition
3905 *
3906 * Deallocates a schema model group definition.
3907 */
3908static void
3909xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3910{
3911 if (item->annot != NULL)
3912 xmlSchemaFreeAnnot(item->annot);
3913 xmlFree(item);
3914}
3915
3916/**
3917 * xmlSchemaFreeModelGroup:
3918 * @item: a schema model group
3919 *
3920 * Deallocates a schema model group structure.
3921 */
3922static void
3923xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3924{
3925 if (item->annot != NULL)
3926 xmlSchemaFreeAnnot(item->annot);
3927 xmlFree(item);
3928}
3929
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003930static void
3931xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3932{
3933 if ((list == NULL) || (list->nbItems == 0))
3934 return;
3935 {
3936 xmlSchemaTreeItemPtr item;
3937 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3938 int i;
3939
3940 for (i = 0; i < list->nbItems; i++) {
3941 item = items[i];
3942 if (item == NULL)
3943 continue;
3944 switch (item->type) {
3945 case XML_SCHEMA_TYPE_SIMPLE:
3946 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003947 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003948 break;
3949 case XML_SCHEMA_TYPE_ATTRIBUTE:
3950 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003951 break;
3952 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
3953 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
3954 break;
3955 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
3956 xmlSchemaFreeAttributeUseProhib(
3957 (xmlSchemaAttributeUseProhibPtr) item);
3958 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003959 case XML_SCHEMA_TYPE_ELEMENT:
3960 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
3961 break;
3962 case XML_SCHEMA_TYPE_PARTICLE:
3963 if (item->annot != NULL)
3964 xmlSchemaFreeAnnot(item->annot);
3965 xmlFree(item);
3966 break;
3967 case XML_SCHEMA_TYPE_SEQUENCE:
3968 case XML_SCHEMA_TYPE_CHOICE:
3969 case XML_SCHEMA_TYPE_ALL:
3970 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3971 break;
3972 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3973 xmlSchemaFreeAttributeGroup(
3974 (xmlSchemaAttributeGroupPtr) item);
3975 break;
3976 case XML_SCHEMA_TYPE_GROUP:
3977 xmlSchemaFreeModelGroupDef(
3978 (xmlSchemaModelGroupDefPtr) item);
3979 break;
3980 case XML_SCHEMA_TYPE_ANY:
3981 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3982 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3983 break;
3984 case XML_SCHEMA_TYPE_IDC_KEY:
3985 case XML_SCHEMA_TYPE_IDC_UNIQUE:
3986 case XML_SCHEMA_TYPE_IDC_KEYREF:
3987 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
3988 break;
3989 case XML_SCHEMA_TYPE_NOTATION:
3990 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
3991 break;
3992 case XML_SCHEMA_EXTRA_QNAMEREF:
3993 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3994 break;
3995 default: {
3996 /* TODO: This should never be hit. */
3997 xmlSchemaPSimpleInternalErr(NULL,
3998 "Internal error: xmlSchemaComponentListFree, "
3999 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004000 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004001 }
4002 break;
4003 }
4004 }
4005 list->nbItems = 0;
4006 }
4007}
4008
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004009/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004010 * xmlSchemaFree:
4011 * @schema: a schema structure
4012 *
4013 * Deallocate a Schema structure.
4014 */
4015void
4016xmlSchemaFree(xmlSchemaPtr schema)
4017{
4018 if (schema == NULL)
4019 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004020 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004021 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004022 TODO
4023 /*
4024 * Note that those slots are not responsible for freeing
4025 * schema components anymore; this will now be done by
4026 * the schema buckets.
4027 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004028 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004029 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004030 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004031 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004033 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004034 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004035 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004036 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004037 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004038 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004039 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004040 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004041 xmlHashFree(schema->idcDef, NULL);
4042
Daniel Veillard1d913862003-11-21 00:28:39 +00004043 if (schema->schemasImports != NULL)
4044 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004045 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004046 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004047 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4048 int i;
4049 for (i = 0; i < list->nbItems; i++) {
4050 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4051 }
4052 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004053 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004054 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004055 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004056 /* Never free the doc here, since this will be done by the buckets. */
4057
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004058 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004059 xmlFree(schema);
4060}
4061
4062/************************************************************************
4063 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004064 * Debug functions *
4065 * *
4066 ************************************************************************/
4067
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004068#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004069
Daniel Veillard4255d502002-04-16 15:50:10 +00004070/**
4071 * xmlSchemaElementDump:
4072 * @elem: an element
4073 * @output: the file output
4074 *
4075 * Dump the element
4076 */
4077static void
4078xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004079 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004080 const xmlChar * namespace ATTRIBUTE_UNUSED,
4081 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004082{
4083 if (elem == NULL)
4084 return;
4085
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004086
4087 fprintf(output, "Element");
4088 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4089 fprintf(output, " (global)");
4090 fprintf(output, ": %s ", elem->name);
4091 if (namespace != NULL)
4092 fprintf(output, "ns %s", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004093 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004094#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004095 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004096 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004097 if (elem->maxOccurs >= UNBOUNDED)
4098 fprintf(output, "max: unbounded\n");
4099 else if (elem->maxOccurs != 1)
4100 fprintf(output, "max: %d\n", elem->maxOccurs);
4101 else
4102 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004103 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004104#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004105 /*
4106 * Misc other properties.
4107 */
4108 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4109 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4110 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004111 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004112 fprintf(output, " props: ");
4113 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4114 fprintf(output, "[fixed] ");
4115 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4116 fprintf(output, "[default] ");
4117 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4118 fprintf(output, "[abstract] ");
4119 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4120 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004121 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004122 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004123 /*
4124 * Default/fixed value.
4125 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004126 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004127 fprintf(output, " value: '%s'\n", elem->value);
4128 /*
4129 * Type.
4130 */
4131 if (elem->namedType != NULL) {
4132 fprintf(output, " type: %s ", elem->namedType);
4133 if (elem->namedTypeNs != NULL)
4134 fprintf(output, "ns %s\n", elem->namedTypeNs);
4135 else
4136 fprintf(output, "\n");
4137 }
4138 /*
4139 * Substitution group.
4140 */
4141 if (elem->substGroup != NULL) {
4142 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
4143 if (elem->substGroupNs != NULL)
4144 fprintf(output, "ns %s\n", elem->substGroupNs);
4145 else
4146 fprintf(output, "\n");
4147 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004148}
4149
4150/**
4151 * xmlSchemaAnnotDump:
4152 * @output: the file output
4153 * @annot: a annotation
4154 *
4155 * Dump the annotation
4156 */
4157static void
4158xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4159{
4160 xmlChar *content;
4161
4162 if (annot == NULL)
4163 return;
4164
4165 content = xmlNodeGetContent(annot->content);
4166 if (content != NULL) {
4167 fprintf(output, " Annot: %s\n", content);
4168 xmlFree(content);
4169 } else
4170 fprintf(output, " Annot: empty\n");
4171}
4172
4173/**
4174 * xmlSchemaTypeDump:
4175 * @output: the file output
4176 * @type: a type structure
4177 *
4178 * Dump a SchemaType structure
4179 */
4180static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004181xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4182{
4183 xmlChar *str = NULL;
4184 xmlSchemaTreeItemPtr term;
4185 char shift[100];
4186 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004187
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004188 if (particle == NULL)
4189 return;
4190 for (i = 0;((i < depth) && (i < 25));i++)
4191 shift[2 * i] = shift[2 * i + 1] = ' ';
4192 shift[2 * i] = shift[2 * i + 1] = 0;
4193 fprintf(output, shift);
4194 if (particle->children == NULL) {
4195 fprintf(output, "MISSING particle term\n");
4196 return;
4197 }
4198 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004199 if (term == NULL) {
4200 fprintf(output, "(NULL)");
4201 } else {
4202 switch (term->type) {
4203 case XML_SCHEMA_TYPE_ELEMENT:
4204 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4205 ((xmlSchemaElementPtr)term)->targetNamespace,
4206 ((xmlSchemaElementPtr)term)->name));
4207 break;
4208 case XML_SCHEMA_TYPE_SEQUENCE:
4209 fprintf(output, "SEQUENCE");
4210 break;
4211 case XML_SCHEMA_TYPE_CHOICE:
4212 fprintf(output, "CHOICE");
4213 break;
4214 case XML_SCHEMA_TYPE_ALL:
4215 fprintf(output, "ALL");
4216 break;
4217 case XML_SCHEMA_TYPE_ANY:
4218 fprintf(output, "ANY");
4219 break;
4220 default:
4221 fprintf(output, "UNKNOWN\n");
4222 return;
4223 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004224 }
4225 if (particle->minOccurs != 1)
4226 fprintf(output, " min: %d", particle->minOccurs);
4227 if (particle->maxOccurs >= UNBOUNDED)
4228 fprintf(output, " max: unbounded");
4229 else if (particle->maxOccurs != 1)
4230 fprintf(output, " max: %d", particle->maxOccurs);
4231 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004232 if (term &&
4233 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4234 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4235 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4236 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004237 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4238 output, depth +1);
4239 }
4240 if (particle->next != NULL)
4241 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4242 output, depth);
4243}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004244
4245/**
4246 * xmlSchemaAttrUsesDump:
4247 * @uses: attribute uses list
4248 * @output: the file output
4249 *
4250 * Dumps a list of attribute use components.
4251 */
4252static void
4253xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4254{
4255 xmlSchemaAttributeUsePtr use;
4256 xmlSchemaAttributeUseProhibPtr prohib;
4257 xmlSchemaQNameRefPtr ref;
4258 const xmlChar *name, *tns;
4259 xmlChar *str = NULL;
4260 int i;
4261
4262 if ((uses == NULL) || (uses->nbItems == 0))
4263 return;
4264
4265 fprintf(output, "uses:\n");
4266 for (i = 0; i < uses->nbItems; i++) {
4267 use = uses->items[i];
4268 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4269 fprintf(output, " [prohibition] ");
4270 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4271 name = prohib->name;
4272 tns = prohib->targetNamespace;
4273 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4274 fprintf(output, " [reference] ");
4275 ref = (xmlSchemaQNameRefPtr) use;
4276 name = ref->name;
4277 tns = ref->targetNamespace;
4278 } else {
4279 fprintf(output, " [use] ");
4280 name = WXS_ATTRUSE_DECL_NAME(use);
4281 tns = WXS_ATTRUSE_DECL_TNS(use);
4282 }
4283 fprintf(output, "%s\n",
4284 (const char *) xmlSchemaFormatQName(&str, tns, name));
4285 FREE_AND_NULL(str);
4286 }
4287}
4288
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004289/**
4290 * xmlSchemaTypeDump:
4291 * @output: the file output
4292 * @type: a type structure
4293 *
4294 * Dump a SchemaType structure
4295 */
4296static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004297xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4298{
4299 if (type == NULL) {
4300 fprintf(output, "Type: NULL\n");
4301 return;
4302 }
4303 fprintf(output, "Type: ");
4304 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004305 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004306 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004307 fprintf(output, "no name ");
4308 if (type->targetNamespace != NULL)
4309 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004310 switch (type->type) {
4311 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004312 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004313 break;
4314 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004315 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004316 break;
4317 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004318 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004319 break;
4320 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004321 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004322 break;
4323 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004324 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 break;
4326 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004327 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 break;
4329 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004330 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 break;
4332 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004333 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004334 break;
4335 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004336 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004337 break;
4338 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004339 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004340 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004341 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004342 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004344 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004345 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004346 break;
4347 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004348 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004349 break;
4350 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004351 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004352 break;
4353 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004354 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004355 break;
4356 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004357 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004358 break;
4359 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004360 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 break;
4362 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004363 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004364 break;
4365 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004366 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004367 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004368 }
4369 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004370 if (type->base != NULL) {
4371 fprintf(output, " base type: %s", type->base);
4372 if (type->baseNs != NULL)
4373 fprintf(output, " ns %s\n", type->baseNs);
4374 else
4375 fprintf(output, "\n");
4376 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004377 if (type->attrUses != NULL)
4378 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (type->annot != NULL)
4380 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004381#ifdef DUMP_CONTENT_MODEL
4382 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4383 (type->subtypes != NULL)) {
4384 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4385 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004386 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004387#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004388}
4389
4390/**
4391 * xmlSchemaDump:
4392 * @output: the file output
4393 * @schema: a schema structure
4394 *
4395 * Dump a Schema structure.
4396 */
4397void
4398xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4399{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004400 if (output == NULL)
4401 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004402 if (schema == NULL) {
4403 fprintf(output, "Schemas: NULL\n");
4404 return;
4405 }
4406 fprintf(output, "Schemas: ");
4407 if (schema->name != NULL)
4408 fprintf(output, "%s, ", schema->name);
4409 else
4410 fprintf(output, "no name, ");
4411 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004412 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004413 else
4414 fprintf(output, "no target namespace");
4415 fprintf(output, "\n");
4416 if (schema->annot != NULL)
4417 xmlSchemaAnnotDump(output, schema->annot);
4418
4419 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4420 output);
4421 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004423}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004424
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004425#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004426/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004427 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004428 * @vctxt: the WXS validation context
4429 *
4430 * Displays the current IDC table for debug purposes.
4431 */
4432static void
4433xmlSchemaDebugDumpIDCTable(FILE * output,
4434 const xmlChar *namespaceName,
4435 const xmlChar *localName,
4436 xmlSchemaPSVIIDCBindingPtr bind)
4437{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004438 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004439 xmlSchemaPSVIIDCNodePtr tab;
4440 xmlSchemaPSVIIDCKeyPtr key;
4441 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004442
4443 fprintf(output, "IDC: TABLES on %s\n",
4444 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004445 FREE_AND_NULL(str)
4446
4447 if (bind == NULL)
4448 return;
4449 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004450 fprintf(output, "IDC: BINDING %s\n",
4451 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004452 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004453 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004454 for (i = 0; i < bind->nbNodes; i++) {
4455 tab = bind->nodeTable[i];
4456 fprintf(output, " ( ");
4457 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004458 key = tab->keys[j];
4459 if ((key != NULL) && (key->val != NULL)) {
4460 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004461 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004462 fprintf(output, "\"%s\" ", value);
4463 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004464 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004465 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004466 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004467 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004468 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004469 else
4470 fprintf(output, "(key missing), ");
4471 }
4472 fprintf(output, ")\n");
4473 }
4474 bind = bind->next;
4475 } while (bind != NULL);
4476}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004477#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004478#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004479
4480/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004481 * *
4482 * Utilities *
4483 * *
4484 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004485
Daniel Veillardc0826a72004-08-10 14:17:33 +00004486/**
4487 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004488 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004489 * @name: the name of the attribute
4490 *
4491 * Seeks an attribute with a name of @name in
4492 * no namespace.
4493 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004494 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004495 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004496static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004497xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004498{
4499 xmlAttrPtr prop;
4500
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004501 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004502 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004503 prop = node->properties;
4504 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004505 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004506 return(prop);
4507 prop = prop->next;
4508 }
4509 return (NULL);
4510}
4511
4512/**
4513 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004514 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004515 * @uri: the uri
4516 * @name: the name of the attribute
4517 *
4518 * Seeks an attribute with a local name of @name and
4519 * a namespace URI of @uri.
4520 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004521 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004522 */
4523static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004525{
4526 xmlAttrPtr prop;
4527
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004528 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004529 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004530 prop = node->properties;
4531 while (prop != NULL) {
4532 if ((prop->ns != NULL) &&
4533 xmlStrEqual(prop->name, BAD_CAST name) &&
4534 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004535 return(prop);
4536 prop = prop->next;
4537 }
4538 return (NULL);
4539}
4540
4541static const xmlChar *
4542xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4543{
4544 xmlChar *val;
4545 const xmlChar *ret;
4546
4547 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004548 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004549 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004550 ret = xmlDictLookup(ctxt->dict, val, -1);
4551 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004552 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004553}
4554
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004555static const xmlChar *
4556xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4557{
4558 return((const xmlChar*) xmlNodeGetContent(node));
4559}
4560
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004561/**
4562 * xmlSchemaGetProp:
4563 * @ctxt: the parser context
4564 * @node: the node
4565 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004566 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004567 * Read a attribute value and internalize the string
4568 *
4569 * Returns the string or NULL if not present.
4570 */
4571static const xmlChar *
4572xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4573 const char *name)
4574{
4575 xmlChar *val;
4576 const xmlChar *ret;
4577
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004578 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004579 if (val == NULL)
4580 return(NULL);
4581 ret = xmlDictLookup(ctxt->dict, val, -1);
4582 xmlFree(val);
4583 return(ret);
4584}
4585
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004586/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004587 * *
4588 * Parsing functions *
4589 * *
4590 ************************************************************************/
4591
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004592#define WXS_FIND_GLOBAL_ITEM(slot) \
4593 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4594 ret = xmlHashLookup(schema->slot, name); \
4595 if (ret != NULL) goto exit; \
4596 } \
4597 if (xmlHashSize(schema->schemasImports) > 1) { \
4598 xmlSchemaImportPtr import; \
4599 if (nsName == NULL) \
4600 import = xmlHashLookup(schema->schemasImports, \
4601 XML_SCHEMAS_NO_NAMESPACE); \
4602 else \
4603 import = xmlHashLookup(schema->schemasImports, nsName); \
4604 if (import == NULL) \
4605 goto exit; \
4606 ret = xmlHashLookup(import->schema->slot, name); \
4607 }
4608
Daniel Veillard4255d502002-04-16 15:50:10 +00004609/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004610 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004611 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004612 * @name: the element name
4613 * @ns: the element namespace
4614 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004615 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004616 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004617 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004618 */
4619static xmlSchemaElementPtr
4620xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004621 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004622{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004623 xmlSchemaElementPtr ret = NULL;
4624
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004625 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004626 return(NULL);
4627 if (schema != NULL) {
4628 WXS_FIND_GLOBAL_ITEM(elemDecl)
4629 }
4630exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004631#ifdef DEBUG
4632 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004633 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004634 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004635 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004636 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004637 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004638 }
4639#endif
4640 return (ret);
4641}
4642
4643/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004645 * @schema: the main schema
4646 * @name: the type's name
4647 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 *
4649 * Lookup a type in the schemas or the predefined types
4650 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004651 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004652 */
4653static xmlSchemaTypePtr
4654xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004655 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004656{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004657 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004658
4659 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004660 return (NULL);
4661 /* First try the built-in types. */
4662 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4663 ret = xmlSchemaGetPredefinedType(name, nsName);
4664 if (ret != NULL)
4665 goto exit;
4666 /*
4667 * Note that we try the parsed schemas as well here
4668 * since one might have parsed the S4S, which contain more
4669 * than the built-in types.
4670 * TODO: Can we optimize this?
4671 */
4672 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004674 WXS_FIND_GLOBAL_ITEM(typeDecl)
4675 }
4676exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004677
Daniel Veillard4255d502002-04-16 15:50:10 +00004678#ifdef DEBUG
4679 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004680 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004681 fprintf(stderr, "Unable to lookup type %s", name);
4682 else
4683 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004684 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004685 }
4686#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004687 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004688}
4689
Daniel Veillard3646d642004-06-02 19:19:14 +00004690/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004691 * xmlSchemaGetAttributeDecl:
4692 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004693 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004694 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004695 *
4696 * Lookup a an attribute in the schema or imported schemas
4697 *
4698 * Returns the attribute declaration or NULL if not found.
4699 */
4700static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004701xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004702 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004703{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004704 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004705
4706 if ((name == NULL) || (schema == NULL))
4707 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004708 if (schema != NULL) {
4709 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004710 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004711exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004712#ifdef DEBUG
4713 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004714 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004715 fprintf(stderr, "Unable to lookup attribute %s", name);
4716 else
4717 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004718 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004719 }
4720#endif
4721 return (ret);
4722}
4723
4724/**
4725 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004726 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004727 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004728 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004729 *
4730 * Lookup a an attribute group in the schema or imported schemas
4731 *
4732 * Returns the attribute group definition or NULL if not found.
4733 */
4734static xmlSchemaAttributeGroupPtr
4735xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004736 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004737{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004738 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004739
4740 if ((name == NULL) || (schema == NULL))
4741 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004742 if (schema != NULL) {
4743 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4744 }
4745exit:
4746 /* TODO:
4747 if ((ret != NULL) && (ret->redef != NULL)) {
4748 * Return the last redefinition. *
4749 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004750 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004751 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004752#ifdef DEBUG
4753 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004754 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004755 fprintf(stderr, "Unable to lookup attribute group %s", name);
4756 else
4757 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004758 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004759 }
4760#endif
4761 return (ret);
4762}
4763
4764/**
4765 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004766 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004767 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004768 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004769 *
4770 * Lookup a group in the schema or imported schemas
4771 *
4772 * Returns the group definition or NULL if not found.
4773 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004774static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004775xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004776 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004777{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004778 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004779
4780 if ((name == NULL) || (schema == NULL))
4781 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004782 if (schema != NULL) {
4783 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004784 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004785exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004786
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 group %s", name);
4791 else
4792 fprintf(stderr, "Unable to lookup group %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
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004799static xmlSchemaNotationPtr
4800xmlSchemaGetNotation(xmlSchemaPtr schema,
4801 const xmlChar *name,
4802 const xmlChar *nsName)
4803{
4804 xmlSchemaNotationPtr ret = NULL;
4805
4806 if ((name == NULL) || (schema == NULL))
4807 return (NULL);
4808 if (schema != NULL) {
4809 WXS_FIND_GLOBAL_ITEM(notaDecl)
4810 }
4811exit:
4812 return (ret);
4813}
4814
4815static xmlSchemaIDCPtr
4816xmlSchemaGetIDC(xmlSchemaPtr schema,
4817 const xmlChar *name,
4818 const xmlChar *nsName)
4819{
4820 xmlSchemaIDCPtr ret = NULL;
4821
4822 if ((name == NULL) || (schema == NULL))
4823 return (NULL);
4824 if (schema != NULL) {
4825 WXS_FIND_GLOBAL_ITEM(idcDef)
4826 }
4827exit:
4828 return (ret);
4829}
4830
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004831/**
4832 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004833 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004834 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004835 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004836 *
4837 * Lookup a group in the schema or imported schemas
4838 *
4839 * Returns the group definition or NULL if not found.
4840 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004841static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4843 xmlSchemaTypeType itemType,
4844 const xmlChar *name,
4845 const xmlChar *targetNs)
4846{
4847 switch (itemType) {
4848 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004849 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004850 name, targetNs));
4851 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004852 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004853 name, targetNs));
4854 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004855 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004856 return (NULL);
4857 }
4858}
4859
Daniel Veillard4255d502002-04-16 15:50:10 +00004860/************************************************************************
4861 * *
4862 * Parsing functions *
4863 * *
4864 ************************************************************************/
4865
4866#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004867 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004868
4869/**
4870 * xmlSchemaIsBlank:
4871 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004872 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004873 *
4874 * Check if a string is ignorable
4875 *
4876 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4877 */
4878static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004879xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004880{
Daniel Veillard4255d502002-04-16 15:50:10 +00004881 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004882 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004883 if (len < 0) {
4884 while (*str != 0) {
4885 if (!(IS_BLANK_CH(*str)))
4886 return (0);
4887 str++;
4888 }
4889 } else while ((*str != 0) && (len != 0)) {
4890 if (!(IS_BLANK_CH(*str)))
4891 return (0);
4892 str++;
4893 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004894 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004895
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004897}
4898
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004899#define WXS_COMP_NAME(c, t) ((t) (c))->name
4900#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4901/*
4902* xmlSchemaFindRedefCompInGraph:
4903* ATTENTION TODO: This uses pointer comp. for strings.
4904*/
4905static xmlSchemaBasicItemPtr
4906xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4907 xmlSchemaTypeType type,
4908 const xmlChar *name,
4909 const xmlChar *nsName)
4910{
4911 xmlSchemaBasicItemPtr ret;
4912 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004913
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004914 if ((bucket == NULL) || (name == NULL))
4915 return(NULL);
4916 if ((bucket->globals == NULL) ||
4917 (bucket->globals->nbItems == 0))
4918 goto subschemas;
4919 /*
4920 * Search in global components.
4921 */
4922 for (i = 0; i < bucket->globals->nbItems; i++) {
4923 ret = bucket->globals->items[i];
4924 if (ret->type == type) {
4925 switch (type) {
4926 case XML_SCHEMA_TYPE_COMPLEX:
4927 case XML_SCHEMA_TYPE_SIMPLE:
4928 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
4929 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
4930 nsName))
4931 {
4932 return(ret);
4933 }
4934 break;
4935 case XML_SCHEMA_TYPE_GROUP:
4936 if ((WXS_COMP_NAME(ret,
4937 xmlSchemaModelGroupDefPtr) == name) &&
4938 (WXS_COMP_TNS(ret,
4939 xmlSchemaModelGroupDefPtr) == nsName))
4940 {
4941 return(ret);
4942 }
4943 break;
4944 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4945 if ((WXS_COMP_NAME(ret,
4946 xmlSchemaAttributeGroupPtr) == name) &&
4947 (WXS_COMP_TNS(ret,
4948 xmlSchemaAttributeGroupPtr) == nsName))
4949 {
4950 return(ret);
4951 }
4952 default:
4953 /* Should not be hit. */
4954 return(NULL);
4955 }
4956 }
4957 }
4958subschemas:
4959 /*
4960 * Process imported/included schemas.
4961 */
4962 if (bucket->relations != NULL) {
4963 xmlSchemaSchemaRelationPtr rel = bucket->relations;
4964
4965 /*
4966 * TODO: Marking the bucket will not avoid multiple searches
4967 * in the same schema, but avoids at least circularity.
4968 */
4969 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
4970 do {
4971 if ((rel->bucket != NULL) &&
4972 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
4973 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
4974 type, name, nsName);
4975 if (ret != NULL)
4976 return(ret);
4977 }
4978 rel = rel->next;
4979 } while (rel != NULL);
4980 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
4981 }
4982 return(NULL);
4983}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004984
4985/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004986 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004987 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004988 * @schema: the schema being built
4989 * @name: the item name
4990 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004992 * *WARNING* this interface is highly subject to change
4993 *
4994 * Returns the new struture or NULL in case of error
4995 */
4996static xmlSchemaNotationPtr
4997xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004998 const xmlChar *name, const xmlChar *nsName,
4999 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005000{
5001 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005002
5003 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5004 return (NULL);
5005
Daniel Veillard4255d502002-04-16 15:50:10 +00005006 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5007 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005008 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005009 return (NULL);
5010 }
5011 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005012 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005013 ret->name = name;
5014 ret->targetNamespace = nsName;
5015 /* TODO: do we need the node to be set?
5016 * ret->node = node;*/
5017 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005018 return (ret);
5019}
5020
Daniel Veillard4255d502002-04-16 15:50:10 +00005021/**
5022 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005023 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005024 * @schema: the schema being built
5025 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005026 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005027 *
5028 * Add an XML schema Attrribute declaration
5029 * *WARNING* this interface is highly subject to change
5030 *
5031 * Returns the new struture or NULL in case of error
5032 */
5033static xmlSchemaAttributePtr
5034xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005035 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005036 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005037{
5038 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005039
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005040 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005041 return (NULL);
5042
5043 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5044 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005046 return (NULL);
5047 }
5048 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005049 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5050 ret->node = node;
5051 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005052 ret->targetNamespace = nsName;
5053
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005054 if (topLevel)
5055 WXS_ADD_GLOBAL(ctxt, ret);
5056 else
5057 WXS_ADD_LOCAL(ctxt, ret);
5058 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005059 return (ret);
5060}
5061
5062/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005063 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005064 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005065 * @schema: the schema being built
5066 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005067 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005068 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005069 * Add an XML schema Attrribute declaration
5070 * *WARNING* this interface is highly subject to change
5071 *
5072 * Returns the new struture or NULL in case of error
5073 */
5074static xmlSchemaAttributeUsePtr
5075xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5076 xmlNodePtr node)
5077{
5078 xmlSchemaAttributeUsePtr ret = NULL;
5079
5080 if (pctxt == NULL)
5081 return (NULL);
5082
5083 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5084 if (ret == NULL) {
5085 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5086 return (NULL);
5087 }
5088 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5089 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5090 ret->node = node;
5091
5092 WXS_ADD_LOCAL(pctxt, ret);
5093 return (ret);
5094}
5095
5096/*
5097* xmlSchemaAddRedef:
5098*
5099* Adds a redefinition information. This is used at a later stage to:
5100* resolve references to the redefined components and to check constraints.
5101*/
5102static xmlSchemaRedefPtr
5103xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5104 xmlSchemaBucketPtr targetBucket,
5105 void *item,
5106 const xmlChar *refName,
5107 const xmlChar *refTargetNs)
5108{
5109 xmlSchemaRedefPtr ret;
5110
5111 ret = (xmlSchemaRedefPtr)
5112 xmlMalloc(sizeof(xmlSchemaRedef));
5113 if (ret == NULL) {
5114 xmlSchemaPErrMemory(pctxt,
5115 "allocating redefinition info", NULL);
5116 return (NULL);
5117 }
5118 memset(ret, 0, sizeof(xmlSchemaRedef));
5119 ret->item = item;
5120 ret->targetBucket = targetBucket;
5121 ret->refName = refName;
5122 ret->refTargetNs = refTargetNs;
5123 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5124 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5125 else
5126 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5127 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5128
5129 return (ret);
5130}
5131
5132/**
5133 * xmlSchemaAddAttributeGroupDefinition:
5134 * @ctxt: a schema parser context
5135 * @schema: the schema being built
5136 * @name: the item name
5137 * @nsName: the target namespace
5138 * @node: the corresponding node
5139 *
5140 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005141 *
5142 * Returns the new struture or NULL in case of error
5143 */
5144static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005145xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5146 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5147 const xmlChar *name,
5148 const xmlChar *nsName,
5149 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005150{
5151 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005152
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005153 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005154 return (NULL);
5155
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005156 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005158 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005159 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005160 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005161 }
5162 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005163 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005164 ret->name = name;
5165 ret->targetNamespace = nsName;
5166 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005167
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005168 /* TODO: Remove the flag. */
5169 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5170 if (pctxt->isRedefine) {
5171 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5172 ret, name, nsName);
5173 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005174 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005175 return(NULL);
5176 }
5177 pctxt->redefCounter = 0;
5178 }
5179 WXS_ADD_GLOBAL(pctxt, ret);
5180 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005181 return (ret);
5182}
5183
5184/**
5185 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005186 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 * @schema: the schema being built
5188 * @name: the type name
5189 * @namespace: the type namespace
5190 *
5191 * Add an XML schema Element declaration
5192 * *WARNING* this interface is highly subject to change
5193 *
5194 * Returns the new struture or NULL in case of error
5195 */
5196static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005197xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005198 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005199 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005200{
5201 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005202
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005203 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005204 return (NULL);
5205
Daniel Veillard4255d502002-04-16 15:50:10 +00005206 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5207 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005208 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005209 return (NULL);
5210 }
5211 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005212 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5213 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005214 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005215 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005216
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005217 if (topLevel)
5218 WXS_ADD_GLOBAL(ctxt, ret);
5219 else
5220 WXS_ADD_LOCAL(ctxt, ret);
5221 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005222 return (ret);
5223}
5224
5225/**
5226 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005227 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005228 * @schema: the schema being built
5229 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005230 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005232 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 * *WARNING* this interface is highly subject to change
5234 *
5235 * Returns the new struture or NULL in case of error
5236 */
5237static xmlSchemaTypePtr
5238xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005239 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005240 const xmlChar * name, const xmlChar * nsName,
5241 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005242{
5243 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005245 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005246 return (NULL);
5247
5248 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5249 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 return (NULL);
5252 }
5253 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005254 ret->type = type;
5255 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005256 ret->targetNamespace = nsName;
5257 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005258 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005259 if (ctxt->isRedefine) {
5260 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5261 ret, name, nsName);
5262 if (ctxt->redef == NULL) {
5263 xmlFree(ret);
5264 return(NULL);
5265 }
5266 ctxt->redefCounter = 0;
5267 }
5268 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005269 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005270 WXS_ADD_LOCAL(ctxt, ret);
5271 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005272 return (ret);
5273}
5274
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005275static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005276xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005277 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005278 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005279 const xmlChar *refNs)
5280{
5281 xmlSchemaQNameRefPtr ret;
5282
5283 ret = (xmlSchemaQNameRefPtr)
5284 xmlMalloc(sizeof(xmlSchemaQNameRef));
5285 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005286 xmlSchemaPErrMemory(pctxt,
5287 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005288 return (NULL);
5289 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005290 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005291 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5292 ret->name = refName;
5293 ret->targetNamespace = refNs;
5294 ret->item = NULL;
5295 ret->itemType = refType;
5296 /*
5297 * Store the reference item in the schema.
5298 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005299 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005300 return (ret);
5301}
5302
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005303static xmlSchemaAttributeUseProhibPtr
5304xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5305{
5306 xmlSchemaAttributeUseProhibPtr ret;
5307
5308 ret = (xmlSchemaAttributeUseProhibPtr)
5309 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5310 if (ret == NULL) {
5311 xmlSchemaPErrMemory(pctxt,
5312 "allocating attribute use prohibition", NULL);
5313 return (NULL);
5314 }
5315 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5316 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5317 WXS_ADD_LOCAL(pctxt, ret);
5318 return (ret);
5319}
5320
5321
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005322/**
5323 * xmlSchemaAddModelGroup:
5324 * @ctxt: a schema parser context
5325 * @schema: the schema being built
5326 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005327 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005328 *
5329 * Adds a schema model group
5330 * *WARNING* this interface is highly subject to change
5331 *
5332 * Returns the new struture or NULL in case of error
5333 */
5334static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005335xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5336 xmlSchemaPtr schema,
5337 xmlSchemaTypeType type,
5338 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005339{
5340 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005341
5342 if ((ctxt == NULL) || (schema == NULL))
5343 return (NULL);
5344
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005345 ret = (xmlSchemaModelGroupPtr)
5346 xmlMalloc(sizeof(xmlSchemaModelGroup));
5347 if (ret == NULL) {
5348 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5349 NULL);
5350 return (NULL);
5351 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005352 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005353 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005354 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005355 WXS_ADD_LOCAL(ctxt, ret);
5356 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5357 (type == XML_SCHEMA_TYPE_CHOICE))
5358 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005359 return (ret);
5360}
5361
5362
5363/**
5364 * xmlSchemaAddParticle:
5365 * @ctxt: a schema parser context
5366 * @schema: the schema being built
5367 * @node: the corresponding node in the schema doc
5368 * @min: the minOccurs
5369 * @max: the maxOccurs
5370 *
5371 * Adds an XML schema particle component.
5372 * *WARNING* this interface is highly subject to change
5373 *
5374 * Returns the new struture or NULL in case of error
5375 */
5376static xmlSchemaParticlePtr
5377xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5378 xmlNodePtr node, int min, int max)
5379{
5380 xmlSchemaParticlePtr ret = NULL;
5381 if ((ctxt == NULL) || (schema == NULL))
5382 return (NULL);
5383
5384#ifdef DEBUG
5385 fprintf(stderr, "Adding particle component\n");
5386#endif
5387 ret = (xmlSchemaParticlePtr)
5388 xmlMalloc(sizeof(xmlSchemaParticle));
5389 if (ret == NULL) {
5390 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5391 NULL);
5392 return (NULL);
5393 }
5394 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5395 ret->annot = NULL;
5396 ret->node = node;
5397 ret->minOccurs = min;
5398 ret->maxOccurs = max;
5399 ret->next = NULL;
5400 ret->children = NULL;
5401
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005402 WXS_ADD_LOCAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005403 /*
5404 * Note that addition to pending components will be done locally
5405 * to the specific parsing function, since the most particles
5406 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005407 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005409 return (ret);
5410}
5411
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005412/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005413 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005414 * @ctxt: a schema validation context
5415 * @schema: the schema being built
5416 * @name: the group name
5417 *
5418 * Add an XML schema Group definition
5419 *
5420 * Returns the new struture or NULL in case of error
5421 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005422static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005423xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5424 xmlSchemaPtr schema,
5425 const xmlChar *name,
5426 const xmlChar *nsName,
5427 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005428{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005429 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005430
5431 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5432 return (NULL);
5433
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005434 ret = (xmlSchemaModelGroupDefPtr)
5435 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005436 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005437 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005438 return (NULL);
5439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005440 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005441 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005442 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005443 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005444 ret->targetNamespace = nsName;
5445
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005446 if (ctxt->isRedefine) {
5447 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5448 ret, name, nsName);
5449 if (ctxt->redef == NULL) {
5450 xmlFree(ret);
5451 return(NULL);
5452 }
5453 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005454 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005455 WXS_ADD_GLOBAL(ctxt, ret);
5456 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005457 return (ret);
5458}
5459
Daniel Veillard3646d642004-06-02 19:19:14 +00005460/**
5461 * xmlSchemaNewWildcardNs:
5462 * @ctxt: a schema validation context
5463 *
5464 * Creates a new wildcard namespace constraint.
5465 *
5466 * Returns the new struture or NULL in case of error
5467 */
5468static xmlSchemaWildcardNsPtr
5469xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5470{
5471 xmlSchemaWildcardNsPtr ret;
5472
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005473 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005474 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5475 if (ret == NULL) {
5476 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005477 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005478 }
5479 ret->value = NULL;
5480 ret->next = NULL;
5481 return (ret);
5482}
5483
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005484static xmlSchemaIDCPtr
5485xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5486 const xmlChar *name, const xmlChar *nsName,
5487 int category, xmlNodePtr node)
5488{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005489 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005490
5491 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5492 return (NULL);
5493
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005494 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5495 if (ret == NULL) {
5496 xmlSchemaPErrMemory(ctxt,
5497 "allocating an identity-constraint definition", NULL);
5498 return (NULL);
5499 }
5500 memset(ret, 0, sizeof(xmlSchemaIDC));
5501 /* The target namespace of the parent element declaration. */
5502 ret->targetNamespace = nsName;
5503 ret->name = name;
5504 ret->type = category;
5505 ret->node = node;
5506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005507 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005508 /*
5509 * Only keyrefs need to be fixup up.
5510 */
5511 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005512 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005513 return (ret);
5514}
5515
Daniel Veillard3646d642004-06-02 19:19:14 +00005516/**
5517 * xmlSchemaAddWildcard:
5518 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005519 * @schema: a schema
5520 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005521 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005522 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005523 *
5524 * Returns the new struture or NULL in case of error
5525 */
5526static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005527xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5528 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005529{
5530 xmlSchemaWildcardPtr ret = NULL;
5531
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005532 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005533 return (NULL);
5534
5535 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5536 if (ret == NULL) {
5537 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5538 return (NULL);
5539 }
5540 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005541 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005542 ret->node = node;
5543 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005544 return (ret);
5545}
5546
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005547static void
5548xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5549{
5550 if (group == NULL)
5551 return;
5552 if (group->members != NULL)
5553 xmlSchemaItemListFree(group->members);
5554 xmlFree(group);
5555}
5556
5557static xmlSchemaSubstGroupPtr
5558xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5559 xmlSchemaElementPtr head)
5560{
5561 xmlSchemaSubstGroupPtr ret;
5562
5563 /* Init subst group hash. */
5564 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5565 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5566 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5567 return(NULL);
5568 }
5569 /* Create a new substitution group. */
5570 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5571 if (ret == NULL) {
5572 xmlSchemaPErrMemory(NULL,
5573 "allocating a substitution group container", NULL);
5574 return(NULL);
5575 }
5576 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5577 ret->head = head;
5578 /* Create list of members. */
5579 ret->members = xmlSchemaItemListCreate();
5580 if (ret->members == NULL) {
5581 xmlSchemaSubstGroupFree(ret);
5582 return(NULL);
5583 }
5584 /* Add subst group to hash. */
5585 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5586 head->name, head->targetNamespace, ret) != 0) {
5587 PERROR_INT("xmlSchemaSubstGroupAdd",
5588 "failed to add a new substitution container");
5589 xmlSchemaSubstGroupFree(ret);
5590 return(NULL);
5591 }
5592 return(ret);
5593}
5594
5595static xmlSchemaSubstGroupPtr
5596xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5597 xmlSchemaElementPtr head)
5598{
5599 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5600 return(NULL);
5601 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5602 head->name, head->targetNamespace));
5603
5604}
5605
5606/**
5607 * xmlSchemaAddElementSubstitutionMember:
5608 * @pctxt: a schema parser context
5609 * @head: the head of the substitution group
5610 * @member: the new member of the substitution group
5611 *
5612 * Allocate a new annotation structure.
5613 *
5614 * Returns the newly allocated structure or NULL in case or error
5615 */
5616static int
5617xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5618 xmlSchemaElementPtr head,
5619 xmlSchemaElementPtr member)
5620{
5621 xmlSchemaSubstGroupPtr substGroup = NULL;
5622
5623 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5624 return (-1);
5625
5626 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5627 if (substGroup == NULL)
5628 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5629 if (substGroup == NULL)
5630 return(-1);
5631 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5632 return(-1);
5633 return(0);
5634}
5635
Daniel Veillard4255d502002-04-16 15:50:10 +00005636/************************************************************************
5637 * *
5638 * Utilities for parsing *
5639 * *
5640 ************************************************************************/
5641
Daniel Veillard4255d502002-04-16 15:50:10 +00005642/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005643 * xmlSchemaPValAttrNodeQNameValue:
5644 * @ctxt: a schema parser context
5645 * @schema: the schema context
5646 * @ownerDes: the designation of the parent element
5647 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005648 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005649 * @local: the resulting local part if found, the attribute value otherwise
5650 * @uri: the resulting namespace URI if found
5651 *
5652 * Extracts the local name and the URI of a QName value and validates it.
5653 * This one is intended to be used on attribute values that
5654 * should resolve to schema components.
5655 *
5656 * Returns 0, in case the QName is valid, a positive error code
5657 * if not valid and -1 if an internal error occurs.
5658 */
5659static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005660xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005661 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005662 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005663 xmlAttrPtr attr,
5664 const xmlChar *value,
5665 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005666 const xmlChar **local)
5667{
5668 const xmlChar *pref;
5669 xmlNsPtr ns;
5670 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 *uri = NULL;
5673 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005674 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005675 if (ret > 0) {
5676 xmlSchemaPSimpleTypeErr(ctxt,
5677 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5678 ownerItem, (xmlNodePtr) attr,
5679 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5680 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005681 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005682 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 } else if (ret < 0)
5684 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685
5686 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005687 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 if (ns)
5689 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5690 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005691 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5692 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005693 /*
5694 * This one takes care of included schemas with no
5695 * target namespace.
5696 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005697 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005698 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005699 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005700 return (0);
5701 }
5702 /*
5703 * At this point xmlSplitQName3 has to return a local name.
5704 */
5705 *local = xmlSplitQName3(value, &len);
5706 *local = xmlDictLookup(ctxt->dict, *local, -1);
5707 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005708 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5709 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005710 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005711 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005712 ownerItem, (xmlNodePtr) attr,
5713 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5714 "The value '%s' of simple type 'xs:QName' has no "
5715 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005716 return (ctxt->err);
5717 } else {
5718 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005719 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005720 return (0);
5721}
5722
5723/**
5724 * xmlSchemaPValAttrNodeQName:
5725 * @ctxt: a schema parser context
5726 * @schema: the schema context
5727 * @ownerDes: the designation of the owner element
5728 * @ownerItem: the owner as a schema object
5729 * @attr: the attribute node
5730 * @local: the resulting local part if found, the attribute value otherwise
5731 * @uri: the resulting namespace URI if found
5732 *
5733 * Extracts and validates the QName of an attribute value.
5734 * This one is intended to be used on attribute values that
5735 * should resolve to schema components.
5736 *
5737 * Returns 0, in case the QName is valid, a positive error code
5738 * if not valid and -1 if an internal error occurs.
5739 */
5740static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005741xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005743 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005744 xmlAttrPtr attr,
5745 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 const xmlChar **local)
5747{
5748 const xmlChar *value;
5749
5750 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005751 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005752 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753}
5754
5755/**
5756 * xmlSchemaPValAttrQName:
5757 * @ctxt: a schema parser context
5758 * @schema: the schema context
5759 * @ownerDes: the designation of the parent element
5760 * @ownerItem: the owner as a schema object
5761 * @ownerElem: the parent node of the attribute
5762 * @name: the name of the attribute
5763 * @local: the resulting local part if found, the attribute value otherwise
5764 * @uri: the resulting namespace URI if found
5765 *
5766 * Extracts and validates the QName of an attribute value.
5767 *
5768 * Returns 0, in case the QName is valid, a positive error code
5769 * if not valid and -1 if an internal error occurs.
5770 */
5771static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005772xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5773 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005774 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005775 xmlNodePtr ownerElem,
5776 const char *name,
5777 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005778 const xmlChar **local)
5779{
5780 xmlAttrPtr attr;
5781
5782 attr = xmlSchemaGetPropNode(ownerElem, name);
5783 if (attr == NULL) {
5784 *local = NULL;
5785 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005786 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005787 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005788 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005789 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005790}
5791
5792/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005793 * xmlSchemaPValAttrID:
5794 * @ctxt: a schema parser context
5795 * @schema: the schema context
5796 * @ownerDes: the designation of the parent element
5797 * @ownerItem: the owner as a schema object
5798 * @ownerElem: the parent node of the attribute
5799 * @name: the name of the attribute
5800 *
5801 * Extracts and validates the ID of an attribute value.
5802 *
5803 * Returns 0, in case the ID is valid, a positive error code
5804 * if not valid and -1 if an internal error occurs.
5805 */
5806static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005807xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005808{
5809 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005810 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005811
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005812 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005813 return(0);
5814 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5815 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005816 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005817 /*
5818 * NOTE: the IDness might have already be declared in the DTD
5819 */
5820 if (attr->atype != XML_ATTRIBUTE_ID) {
5821 xmlIDPtr res;
5822 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005823
5824 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005825 * TODO: Use xmlSchemaStrip here; it's not exported at this
5826 * moment.
5827 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005828 strip = xmlSchemaCollapseString(value);
5829 if (strip != NULL) {
5830 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005831 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005832 }
5833 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005834 if (res == NULL) {
5835 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005836 xmlSchemaPSimpleTypeErr(ctxt,
5837 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005838 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005839 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5840 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005841 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005842 } else
5843 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005844 }
5845 } else if (ret > 0) {
5846 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005847 xmlSchemaPSimpleTypeErr(ctxt,
5848 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005849 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005850 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5851 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5852 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005853 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005854 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005855 if (value != NULL)
5856 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005857
5858 return (ret);
5859}
5860
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005861static int
5862xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5863 xmlNodePtr ownerElem,
5864 const xmlChar *name)
5865{
5866 xmlAttrPtr attr;
5867
5868 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5869 if (attr == NULL)
5870 return(0);
5871 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5872
5873}
5874
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005875/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005876 * xmlGetMaxOccurs:
5877 * @ctxt: a schema validation context
5878 * @node: a subtree containing XML Schema informations
5879 *
5880 * Get the maxOccurs property
5881 *
5882 * Returns the default if not found, or the value
5883 */
5884static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005885xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5886 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005887{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005888 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005889 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005890 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005891
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005892 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5893 if (attr == NULL)
5894 return (def);
5895 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005896
5897 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005898 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5901 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005902 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005903 val, NULL, NULL, NULL);
5904 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005905 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005906 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005907 }
5908
5909 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005910 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005911 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005912 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005913 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005914 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5915 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005917 val, NULL, NULL, NULL);
5918 return (def);
5919 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005920 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005921 ret = ret * 10 + (*cur - '0');
5922 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005923 }
William M. Brack76e95df2003-10-18 16:20:14 +00005924 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005926 /*
5927 * TODO: Restrict the maximal value to Integer.
5928 */
5929 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005930 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005931 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5932 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005933 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005934 val, NULL, NULL, NULL);
5935 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005936 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005937 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005938}
5939
5940/**
5941 * xmlGetMinOccurs:
5942 * @ctxt: a schema validation context
5943 * @node: a subtree containing XML Schema informations
5944 *
5945 * Get the minOccurs property
5946 *
5947 * Returns the default if not found, or the value
5948 */
5949static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005950xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005951 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005952{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005953 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005954 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005955 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005956
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005957 attr = xmlSchemaGetPropNode(node, "minOccurs");
5958 if (attr == NULL)
5959 return (def);
5960 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005962 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005963 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005964 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005965 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005966 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5967 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005969 val, NULL, NULL, NULL);
5970 return (def);
5971 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005972 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005973 ret = ret * 10 + (*cur - '0');
5974 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005975 }
William M. Brack76e95df2003-10-18 16:20:14 +00005976 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005977 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005978 /*
5979 * TODO: Restrict the maximal value to Integer.
5980 */
5981 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005982 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5984 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005985 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005986 val, NULL, NULL, NULL);
5987 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005990}
5991
5992/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005993 * xmlSchemaPGetBoolNodeValue:
5994 * @ctxt: a schema validation context
5995 * @ownerDes: owner designation
5996 * @ownerItem: the owner as a schema item
5997 * @node: the node holding the value
5998 *
5999 * Converts a boolean string value into 1 or 0.
6000 *
6001 * Returns 0 or 1.
6002 */
6003static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006004xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006005 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006006 xmlNodePtr node)
6007{
6008 xmlChar *value = NULL;
6009 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006010
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006011 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006012 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006013 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006014 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006015 * can have the following legal literals {true, false, 1, 0}.
6016 */
6017 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6018 res = 1;
6019 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6020 res = 0;
6021 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6022 res = 1;
6023 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006025 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006026 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006027 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 ownerItem, node,
6029 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6030 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006031 NULL, NULL, NULL);
6032 }
6033 if (value != NULL)
6034 xmlFree(value);
6035 return (res);
6036}
6037
6038/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006039 * xmlGetBooleanProp:
6040 * @ctxt: a schema validation context
6041 * @node: a subtree containing XML Schema informations
6042 * @name: the attribute name
6043 * @def: the default value
6044 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006045 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006046 *
6047 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006048 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006049 */
6050static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006051xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006052 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006053 const char *name, int def)
6054{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006055 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006056
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006057 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006058 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006059 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006060 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006061 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006062 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00006063 * can have the following legal literals {true, false, 1, 0}.
6064 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006065 if (xmlStrEqual(val, BAD_CAST "true"))
6066 def = 1;
6067 else if (xmlStrEqual(val, BAD_CAST "false"))
6068 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006069 else if (xmlStrEqual(val, BAD_CAST "1"))
6070 def = 1;
6071 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006072 def = 0;
6073 else {
6074 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006075 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006076 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006077 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006078 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6079 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006080 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006081 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006082}
6083
6084/************************************************************************
6085 * *
6086 * Shema extraction from an Infoset *
6087 * *
6088 ************************************************************************/
6089static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6090 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006091 xmlNodePtr node,
6092 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006093static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6094 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006095 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006096 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006097 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006098static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6099 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 xmlNodePtr node,
6102 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006103static xmlSchemaBasicItemPtr
6104xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6105 xmlSchemaPtr schema,
6106 xmlNodePtr node,
6107 xmlSchemaItemListPtr uses,
6108 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006109static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6110 xmlSchemaPtr schema,
6111 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006112static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006113xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6114 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006115
6116/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006117 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006118 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006119 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006120 * @ownerDes: the designation of the parent element
6121 * @ownerItem: the schema object owner if existent
6122 * @attr: the schema attribute node being validated
6123 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006125 *
6126 * Validates a value against the given built-in type.
6127 * This one is intended to be used internally for validation
6128 * of schema attribute values during parsing of the schema.
6129 *
6130 * Returns 0 if the value is valid, a positive error code
6131 * number otherwise and -1 in case of an internal or API error.
6132 */
6133static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006134xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006135 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006136 xmlAttrPtr attr,
6137 const xmlChar *value,
6138 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006139{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006140
6141 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006142
6143 /*
6144 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6145 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006146 */
6147 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006148 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006149 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6150 PERROR_INT("xmlSchemaPValAttrNodeValue",
6151 "the given type is not a built-in type");
6152 return (-1);
6153 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006154 switch (type->builtInType) {
6155 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006156 case XML_SCHEMAS_QNAME:
6157 case XML_SCHEMAS_ANYURI:
6158 case XML_SCHEMAS_TOKEN:
6159 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006160 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6161 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006162 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006163 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006164 PERROR_INT("xmlSchemaPValAttrNodeValue",
6165 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006166 return (-1);
6167 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006168 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006169 /*
6170 * TODO: Should we use the S4S error codes instead?
6171 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006172 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006173 PERROR_INT("xmlSchemaPValAttrNodeValue",
6174 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006175 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006176 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006177 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006178 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6179 else
6180 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6181 xmlSchemaPSimpleTypeErr(pctxt,
6182 ret, ownerItem, (xmlNodePtr) attr,
6183 type, NULL, value, NULL, NULL, NULL);
6184 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006185 return (ret);
6186}
6187
6188/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006189 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006190 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006191 * @ctxt: a schema parser context
6192 * @ownerDes: the designation of the parent element
6193 * @ownerItem: the schema object owner if existent
6194 * @attr: the schema attribute node being validated
6195 * @type: the built-in type to be validated against
6196 * @value: the resulting value if any
6197 *
6198 * Extracts and validates a value against the given built-in type.
6199 * This one is intended to be used internally for validation
6200 * of schema attribute values during parsing of the schema.
6201 *
6202 * Returns 0 if the value is valid, a positive error code
6203 * number otherwise and -1 in case of an internal or API error.
6204 */
6205static int
6206xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006207 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006208 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006209 xmlSchemaTypePtr type,
6210 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006211{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006212 const xmlChar *val;
6213
6214 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006215 return (-1);
6216
Daniel Veillardc0826a72004-08-10 14:17:33 +00006217 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6218 if (value != NULL)
6219 *value = val;
6220
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006221 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006223}
6224
6225/**
6226 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006228 * @ctxt: a schema parser context
6229 * @node: the element node of the attribute
6230 * @ownerDes: the designation of the parent element
6231 * @ownerItem: the schema object owner if existent
6232 * @ownerElem: the owner element node
6233 * @name: the name of the schema attribute node
6234 * @type: the built-in type to be validated against
6235 * @value: the resulting value if any
6236 *
6237 * Extracts and validates a value against the given built-in type.
6238 * This one is intended to be used internally for validation
6239 * of schema attribute values during parsing of the schema.
6240 *
6241 * Returns 0 if the value is valid, a positive error code
6242 * number otherwise and -1 in case of an internal or API error.
6243 */
6244static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006245xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6246 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006247 xmlNodePtr ownerElem,
6248 const char *name,
6249 xmlSchemaTypePtr type,
6250 const xmlChar **value)
6251{
6252 xmlAttrPtr attr;
6253
6254 if ((ctxt == NULL) || (type == NULL)) {
6255 if (value != NULL)
6256 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006257 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006258 }
6259 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6260 if (value != NULL)
6261 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006262 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006263 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006264 "Internal error: xmlSchemaPValAttr, the given "
6265 "type '%s' is not a built-in type.\n",
6266 type->name, NULL);
6267 return (-1);
6268 }
6269 attr = xmlSchemaGetPropNode(ownerElem, name);
6270 if (attr == NULL) {
6271 if (value != NULL)
6272 *value = NULL;
6273 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006274 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006275 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006276 type, value));
6277}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006278
6279static int
6280xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006281 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006282 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006283 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006284 const xmlChar *namespaceName)
6285{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006286 /* TODO: Pointer comparison instead? */
6287 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006288 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006289 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006290 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006291 /*
6292 * Check if the referenced namespace was <import>ed.
6293 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006294 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006295 xmlSchemaSchemaRelationPtr rel;
6296
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006297 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006298 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006299 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006300 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006301 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006302 rel = rel->next;
6303 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006304 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006305 /*
6306 * No matching <import>ed namespace found.
6307 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006308 {
6309 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6310
6311 if (namespaceName == NULL)
6312 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6313 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6314 "References from this schema to components in no "
6315 "namespace are not allowed, since not indicated by an "
6316 "import statement", NULL, NULL);
6317 else
6318 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6319 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6320 "References from this schema to components in the "
6321 "namespace '%s' are not allowed, since not indicated by an "
6322 "import statement", namespaceName, NULL);
6323 }
6324 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006325}
6326
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006328 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006329 * @ctxt: a schema validation context
6330 * @schema: the schema being built
6331 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006332 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006334 * Parses attribute uses and attribute declarations and
6335 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006336 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006337static int
6338xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6339 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6340 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006341{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006342 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006343
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006344 while ((IS_SCHEMA((*child), "attribute")) ||
6345 (IS_SCHEMA((*child), "attributeGroup"))) {
6346 if (IS_SCHEMA((*child), "attribute")) {
6347 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6348 *list, parentType);
6349 } else {
6350 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6351 if ((item != NULL) && (hasRefs != NULL))
6352 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006353 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006354 if (item != NULL) {
6355 if (*list == NULL) {
6356 /* TODO: Customize grow factor. */
6357 *list = xmlSchemaItemListCreate();
6358 if (*list == NULL)
6359 return(-1);
6360 }
6361 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6362 return(-1);
6363 }
6364 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006365 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006366 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006367}
6368
6369/**
6370 * xmlSchemaParseAnnotation:
6371 * @ctxt: a schema validation context
6372 * @schema: the schema being built
6373 * @node: a subtree containing XML Schema informations
6374 *
6375 * parse a XML schema Attrribute declaration
6376 * *WARNING* this interface is highly subject to change
6377 *
William M. Bracke7091952004-05-11 15:09:58 +00006378 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006379 * 1 in case of success.
6380 */
6381static xmlSchemaAnnotPtr
6382xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006383 xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006384{
6385 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 xmlNodePtr child = NULL;
6387 xmlAttrPtr attr;
6388 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006389
Daniel Veillardc0826a72004-08-10 14:17:33 +00006390 /*
6391 * INFO: S4S completed.
6392 */
6393 /*
6394 * id = ID
6395 * {any attributes with non-schema namespace . . .}>
6396 * Content: (appinfo | documentation)*
6397 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006398 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6399 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006400 if (needed)
6401 ret = xmlSchemaNewAnnot(ctxt, node);
6402 else
6403 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006404 attr = node->properties;
6405 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006406 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006408 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006409 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006410
6411 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006412 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 }
6414 attr = attr->next;
6415 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006416 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006417 /*
6418 * And now for the children...
6419 */
6420 child = node->children;
6421 while (child != NULL) {
6422 if (IS_SCHEMA(child, "appinfo")) {
6423 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006424 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006425 * source = anyURI
6426 * {any attributes with non-schema namespace . . .}>
6427 * Content: ({any})*
6428 */
6429 attr = child->properties;
6430 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006431 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006432 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006433 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006435
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006436 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006437 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006438 }
6439 attr = attr->next;
6440 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006441 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006442 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006443 child = child->next;
6444 } else if (IS_SCHEMA(child, "documentation")) {
6445 /* TODO: make available the content of "documentation". */
6446 /*
6447 * source = anyURI
6448 * {any attributes with non-schema namespace . . .}>
6449 * Content: ({any})*
6450 */
6451 attr = child->properties;
6452 while (attr != NULL) {
6453 if (attr->ns == NULL) {
6454 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006455 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006456 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006457 }
6458 } else {
6459 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6460 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6461 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006462
6463 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006465 }
6466 }
6467 attr = attr->next;
6468 }
6469 /*
6470 * Attribute "xml:lang".
6471 */
6472 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6473 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006474 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 child = child->next;
6477 } else {
6478 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006479 xmlSchemaPContentErr(ctxt,
6480 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006481 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 barked = 1;
6483 child = child->next;
6484 }
6485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006486
Daniel Veillard4255d502002-04-16 15:50:10 +00006487 return (ret);
6488}
6489
6490/**
6491 * xmlSchemaParseFacet:
6492 * @ctxt: a schema validation context
6493 * @schema: the schema being built
6494 * @node: a subtree containing XML Schema informations
6495 *
6496 * parse a XML schema Facet declaration
6497 * *WARNING* this interface is highly subject to change
6498 *
6499 * Returns the new type structure or NULL in case of error
6500 */
6501static xmlSchemaFacetPtr
6502xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006503 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006504{
6505 xmlSchemaFacetPtr facet;
6506 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006507 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006508
6509 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6510 return (NULL);
6511
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006512 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006513 if (facet == NULL) {
6514 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6515 return (NULL);
6516 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006517 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006518 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006519 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006520 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6521 "Facet %s has no value\n", node->name, NULL);
6522 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006523 return (NULL);
6524 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006525 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006527 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006528 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006529 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006530 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006532 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006533 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006534 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006535 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006536 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006538 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006539 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006540 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006541 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006542 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006543 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006544 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006545 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006546 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6547 } else if (IS_SCHEMA(node, "minLength")) {
6548 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6549 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006550 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6551 "Unknown facet type %s\n", node->name, NULL);
6552 xmlSchemaFreeFacet(facet);
6553 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006554 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006555 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006556 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006557 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6558 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6559 const xmlChar *fixed;
6560
6561 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6562 if (fixed != NULL) {
6563 if (xmlStrEqual(fixed, BAD_CAST "true"))
6564 facet->fixed = 1;
6565 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006567 child = node->children;
6568
6569 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006570 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006571 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006572 }
6573 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006574 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6575 "Facet %s has unexpected child content\n",
6576 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006577 }
6578 return (facet);
6579}
6580
6581/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006582 * xmlSchemaParseWildcardNs:
6583 * @ctxt: a schema parser context
6584 * @wildc: the wildcard, already created
6585 * @node: a subtree containing XML Schema informations
6586 *
6587 * Parses the attribute "processContents" and "namespace"
6588 * of a xsd:anyAttribute and xsd:any.
6589 * *WARNING* this interface is highly subject to change
6590 *
6591 * Returns 0 if everything goes fine, a positive error code
6592 * if something is not valid and -1 if an internal error occurs.
6593 */
6594static int
6595xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006596 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006597 xmlSchemaWildcardPtr wildc,
6598 xmlNodePtr node)
6599{
6600 const xmlChar *pc, *ns, *dictnsItem;
6601 int ret = 0;
6602 xmlChar *nsItem;
6603 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6604 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006605
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6607 if ((pc == NULL)
6608 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6609 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6610 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6611 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6612 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6613 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6614 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006616 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006617 NULL, node,
6618 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006619 NULL, NULL, NULL);
6620 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006621 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006622 }
6623 /*
6624 * Build the namespace constraints.
6625 */
6626 attr = xmlSchemaGetPropNode(node, "namespace");
6627 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006628 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006629 wildc->any = 1;
6630 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6631 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006632 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006633 return (-1);
6634 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006635 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006636 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006637 const xmlChar *end, *cur;
6638
6639 cur = ns;
6640 do {
6641 while (IS_BLANK_CH(*cur))
6642 cur++;
6643 end = cur;
6644 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6645 end++;
6646 if (end == cur)
6647 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006648 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006649 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6650 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006651 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006652 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 NULL, (xmlNodePtr) attr,
6654 NULL,
6655 "((##any | ##other) | List of (xs:anyURI | "
6656 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006657 nsItem, NULL, NULL, NULL);
6658 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6659 } else {
6660 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006661 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006662 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6663 dictnsItem = NULL;
6664 } else {
6665 /*
6666 * Validate the item (anyURI).
6667 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006668 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006669 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6670 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6671 }
6672 /*
6673 * Avoid dublicate namespaces.
6674 */
6675 tmp = wildc->nsSet;
6676 while (tmp != NULL) {
6677 if (dictnsItem == tmp->value)
6678 break;
6679 tmp = tmp->next;
6680 }
6681 if (tmp == NULL) {
6682 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6683 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006684 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006685 return (-1);
6686 }
6687 tmp->value = dictnsItem;
6688 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006689 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006690 wildc->nsSet = tmp;
6691 else
6692 lastNs->next = tmp;
6693 lastNs = tmp;
6694 }
6695
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006697 xmlFree(nsItem);
6698 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006699 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 }
6701 return (ret);
6702}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006703
6704static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006705xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6706 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006707 xmlNodePtr node,
6708 int minOccurs,
6709 int maxOccurs) {
6710
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006711 if ((maxOccurs == 0) && ( minOccurs == 0))
6712 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006713 if (maxOccurs != UNBOUNDED) {
6714 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006715 * TODO: Maybe we should better not create the particle,
6716 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006717 * content model.
6718 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006719 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006720 * 3.9.6 Schema Component Constraint: Particle Correct
6721 *
6722 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006723 if (maxOccurs < 1) {
6724 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006725 * 2.2 {max occurs} must be greater than or equal to 1.
6726 */
6727 xmlSchemaPCustomAttrErr(ctxt,
6728 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006729 NULL, NULL,
6730 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006731 "The value must be greater than or equal to 1");
6732 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6733 } else if (minOccurs > maxOccurs) {
6734 /*
6735 * 2.1 {min occurs} must not be greater than {max occurs}.
6736 */
6737 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006738 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006739 NULL, NULL,
6740 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006741 "The value must not be greater than the value of 'maxOccurs'");
6742 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6743 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006744 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006745 return (0);
6746}
6747
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006749 * xmlSchemaParseAny:
6750 * @ctxt: a schema validation context
6751 * @schema: the schema being built
6752 * @node: a subtree containing XML Schema informations
6753 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006754 * Parsea a XML schema <any> element. A particle and wildcard
6755 * will be created (except if minOccurs==maxOccurs==0, in this case
6756 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006757 * *WARNING* this interface is highly subject to change
6758 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006759 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006761static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006762xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6763 xmlNodePtr node)
6764{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006765 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006766 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006767 xmlSchemaWildcardPtr wild;
6768 int min, max;
6769 xmlAttrPtr attr;
6770 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006771
6772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6773 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006774 /*
6775 * Check for illegal attributes.
6776 */
6777 attr = node->properties;
6778 while (attr != NULL) {
6779 if (attr->ns == NULL) {
6780 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6781 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6782 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6783 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6784 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006785 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006786 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006787 }
6788 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006789 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006790 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006791 }
6792 attr = attr->next;
6793 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006794 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006795 /*
6796 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006797 */
6798 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6799 "(xs:nonNegativeInteger | unbounded)");
6800 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6801 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006802 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6803 /*
6804 * Create & parse the wildcard.
6805 */
6806 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6807 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006808 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006809 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006810 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006811 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006812 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006813 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006814 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006815 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006816 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006817 }
6818 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006819 xmlSchemaPContentErr(ctxt,
6820 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006821 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006822 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006823 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006824 /*
6825 * No component if minOccurs==maxOccurs==0.
6826 */
6827 if ((min == 0) && (max == 0)) {
6828 /* Don't free the wildcard, since it's already on the list. */
6829 return (NULL);
6830 }
6831 /*
6832 * Create the particle.
6833 */
6834 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6835 if (particle == NULL)
6836 return (NULL);
6837 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006838 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006839
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006840 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006841}
6842
6843/**
6844 * xmlSchemaParseNotation:
6845 * @ctxt: a schema validation context
6846 * @schema: the schema being built
6847 * @node: a subtree containing XML Schema informations
6848 *
6849 * parse a XML schema Notation declaration
6850 *
6851 * Returns the new structure or NULL in case of error
6852 */
6853static xmlSchemaNotationPtr
6854xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006855 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006856{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006857 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006858 xmlSchemaNotationPtr ret;
6859 xmlNodePtr child = NULL;
6860
6861 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6862 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006863 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006864 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006865 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6866 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006867 return (NULL);
6868 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006869 ret = xmlSchemaAddNotation(ctxt, schema, name,
6870 ctxt->targetNamespace, node);
6871 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00006872 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006873 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006874
6875 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006876 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006877 child = child->next;
6878 }
6879
Daniel Veillard4255d502002-04-16 15:50:10 +00006880 child = node->children;
6881 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006882 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006883 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006884 }
6885 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006886 xmlSchemaPContentErr(ctxt,
6887 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006888 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006889 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006890 }
6891
6892 return (ret);
6893}
6894
6895/**
6896 * xmlSchemaParseAnyAttribute:
6897 * @ctxt: a schema validation context
6898 * @schema: the schema being built
6899 * @node: a subtree containing XML Schema informations
6900 *
6901 * parse a XML schema AnyAttrribute declaration
6902 * *WARNING* this interface is highly subject to change
6903 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006904 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006906static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006907xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6908 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006909{
Daniel Veillard3646d642004-06-02 19:19:14 +00006910 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006911 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006912 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006913
6914 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6915 return (NULL);
6916
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006917 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6918 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006919 if (ret == NULL) {
6920 return (NULL);
6921 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006922 /*
6923 * Check for illegal attributes.
6924 */
6925 attr = node->properties;
6926 while (attr != NULL) {
6927 if (attr->ns == NULL) {
6928 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6929 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6930 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006931 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006932 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006933 }
6934 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006935 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006936 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006937 }
6938 attr = attr->next;
6939 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006940 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006941 /*
6942 * Parse the namespace list.
6943 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006944 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006945 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006946 /*
6947 * And now for the children...
6948 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 child = node->children;
6950 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006951 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006953 }
6954 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006955 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006956 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006957 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006958 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006959 }
6960
6961 return (ret);
6962}
6963
6964
6965/**
6966 * xmlSchemaParseAttribute:
6967 * @ctxt: a schema validation context
6968 * @schema: the schema being built
6969 * @node: a subtree containing XML Schema informations
6970 *
6971 * parse a XML schema Attrribute declaration
6972 * *WARNING* this interface is highly subject to change
6973 *
William M. Bracke7091952004-05-11 15:09:58 +00006974 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006975 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006976static xmlSchemaBasicItemPtr
6977xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6978 xmlSchemaPtr schema,
6979 xmlNodePtr node,
6980 xmlSchemaItemListPtr uses,
6981 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00006982{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006983 const xmlChar *attrValue, *name = NULL, *ns = NULL;
6984 xmlSchemaAttributeUsePtr use = NULL;
6985 xmlNodePtr child = NULL;
6986 xmlAttrPtr attr;
6987 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
6988 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6989 int nberrors, hasForm = 0, defValueType = 0;
6990
6991#define WXS_ATTR_DEF_VAL_DEFAULT 1
6992#define WXS_ATTR_DEF_VAL_FIXED 2
6993
6994 /*
6995 * 3.2.3 Constraints on XML Representations of Attribute Declarations
6996 */
6997
6998 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
6999 return (NULL);
7000 attr = xmlSchemaGetPropNode(node, "ref");
7001 if (attr != NULL) {
7002 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7003 NULL, attr, &tmpNs, &tmpName) != 0) {
7004 return (NULL);
7005 }
7006 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7007 return(NULL);
7008 isRef = 1;
7009 }
7010 nberrors = pctxt->nberrors;
7011 /*
7012 * Check for illegal attributes.
7013 */
7014 attr = node->properties;
7015 while (attr != NULL) {
7016 if (attr->ns == NULL) {
7017 if (isRef) {
7018 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7019 xmlSchemaPValAttrNodeID(pctxt, attr);
7020 goto attr_next;
7021 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7022 goto attr_next;
7023 }
7024 } else {
7025 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7026 goto attr_next;
7027 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7028 xmlSchemaPValAttrNodeID(pctxt, attr);
7029 goto attr_next;
7030 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7031 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7032 attr, &tmpNs, &tmpName);
7033 goto attr_next;
7034 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7035 /*
7036 * Evaluate the target namespace
7037 */
7038 hasForm = 1;
7039 attrValue = xmlSchemaGetNodeContent(pctxt,
7040 (xmlNodePtr) attr);
7041 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7042 ns = pctxt->targetNamespace;
7043 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7044 {
7045 xmlSchemaPSimpleTypeErr(pctxt,
7046 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7047 NULL, (xmlNodePtr) attr,
7048 NULL, "(qualified | unqualified)",
7049 attrValue, NULL, NULL, NULL);
7050 }
7051 goto attr_next;
7052 }
7053 }
7054 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7055
7056 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7057 /* TODO: Maybe we need to normalize the value beforehand. */
7058 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7059 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7060 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7061 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7062 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7063 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7064 else {
7065 xmlSchemaPSimpleTypeErr(pctxt,
7066 XML_SCHEMAP_INVALID_ATTR_USE,
7067 NULL, (xmlNodePtr) attr,
7068 NULL, "(optional | prohibited | required)",
7069 attrValue, NULL, NULL, NULL);
7070 }
7071 goto attr_next;
7072 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7073 /*
7074 * 3.2.3 : 1
7075 * default and fixed must not both be present.
7076 */
7077 if (defValue) {
7078 xmlSchemaPMutualExclAttrErr(pctxt,
7079 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7080 NULL, attr, "default", "fixed");
7081 } else {
7082 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7083 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7084 }
7085 goto attr_next;
7086 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7087 /*
7088 * 3.2.3 : 1
7089 * default and fixed must not both be present.
7090 */
7091 if (defValue) {
7092 xmlSchemaPMutualExclAttrErr(pctxt,
7093 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7094 NULL, attr, "default", "fixed");
7095 } else {
7096 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7097 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7098 }
7099 goto attr_next;
7100 }
7101 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7102 goto attr_next;
7103
7104 xmlSchemaPIllegalAttrErr(pctxt,
7105 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7106
7107attr_next:
7108 attr = attr->next;
7109 }
7110 /*
7111 * 3.2.3 : 2
7112 * If default and use are both present, use must have
7113 * the actual value optional.
7114 */
7115 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7116 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7117 xmlSchemaPSimpleTypeErr(pctxt,
7118 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7119 NULL, node, NULL,
7120 "(optional | prohibited | required)", NULL,
7121 "The value of the attribute 'use' must be 'optional' "
7122 "if the attribute 'default' is present",
7123 NULL, NULL);
7124 }
7125 /*
7126 * We want correct attributes.
7127 */
7128 if (nberrors != pctxt->nberrors)
7129 return(NULL);
7130 if (! isRef) {
7131 xmlSchemaAttributePtr attrDecl;
7132
7133 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7134 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7135 ns = pctxt->targetNamespace;
7136 /*
7137 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7138 * TODO: Move this to the component layer.
7139 */
7140 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7141 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7142 XML_SCHEMAP_NO_XSI,
7143 node, NULL,
7144 "The target namespace must not match '%s'",
7145 xmlSchemaInstanceNs, NULL);
7146 }
7147 attr = xmlSchemaGetPropNode(node, "name");
7148 if (attr == NULL) {
7149 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7150 NULL, node, "name", NULL);
7151 return (NULL);
7152 }
7153 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7154 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7155 return (NULL);
7156 }
7157 /*
7158 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7159 * TODO: Move this to the component layer.
7160 */
7161 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7162 xmlSchemaPSimpleTypeErr(pctxt,
7163 XML_SCHEMAP_NO_XMLNS,
7164 NULL, (xmlNodePtr) attr,
7165 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7166 "The value of the attribute must not match 'xmlns'",
7167 NULL, NULL);
7168 return (NULL);
7169 }
7170 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7171 goto check_children;
7172 /*
7173 * Create the attribute use component.
7174 */
7175 use = xmlSchemaAddAttributeUse(pctxt, node);
7176 if (use == NULL)
7177 return(NULL);
7178 use->occurs = occurs;
7179 /*
7180 * Create the attribute declaration.
7181 */
7182 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7183 if (attrDecl == NULL)
7184 return (NULL);
7185 if (tmpName != NULL) {
7186 attrDecl->typeName = tmpName;
7187 attrDecl->typeNs = tmpNs;
7188 }
7189 use->attrDecl = attrDecl;
7190 /*
7191 * Value constraint.
7192 */
7193 if (defValue != NULL) {
7194 attrDecl->defValue = defValue;
7195 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7196 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7197 }
7198 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7199 xmlSchemaQNameRefPtr ref;
7200
7201 /*
7202 * Create the attribute use component.
7203 */
7204 use = xmlSchemaAddAttributeUse(pctxt, node);
7205 if (use == NULL)
7206 return(NULL);
7207 /*
7208 * We need to resolve the reference at later stage.
7209 */
7210 WXS_ADD_PENDING(pctxt, use);
7211 use->occurs = occurs;
7212 /*
7213 * Create a QName reference to the attribute declaration.
7214 */
7215 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7216 tmpName, tmpNs);
7217 if (ref == NULL)
7218 return(NULL);
7219 /*
7220 * Assign the reference. This will be substituted for the
7221 * referenced attribute declaration when the QName is resolved.
7222 */
7223 use->attrDecl = WXS_ATTR_CAST ref;
7224 /*
7225 * Value constraint.
7226 */
7227 if (defValue != NULL)
7228 use->defValue = defValue;
7229 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7230 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7231 }
7232
7233check_children:
7234 /*
7235 * And now for the children...
7236 */
7237 child = node->children;
7238 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7239 xmlSchemaAttributeUseProhibPtr prohib;
7240
7241 if (IS_SCHEMA(child, "annotation")) {
7242 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
7243 child = child->next;
7244 }
7245 if (child != NULL) {
7246 xmlSchemaPContentErr(pctxt,
7247 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7248 NULL, node, child, NULL,
7249 "(annotation?)");
7250 }
7251 /*
7252 * Check for pointlessness of attribute prohibitions.
7253 */
7254 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7255 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7256 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7257 node, NULL,
7258 "Skipping attribute use prohibition, since it is "
7259 "pointless inside an <attributeGroup>",
7260 NULL, NULL, NULL);
7261 return(NULL);
7262 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7263 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7264 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7265 node, NULL,
7266 "Skipping attribute use prohibition, since it is "
7267 "pointless when extending a type",
7268 NULL, NULL, NULL);
7269 return(NULL);
7270 }
7271 if (! isRef) {
7272 tmpName = name;
7273 tmpNs = ns;
7274 }
7275 /*
7276 * Check for duplicate attribute prohibitions.
7277 */
7278 if (uses) {
7279 int i;
7280
7281 for (i = 0; i < uses->nbItems; i++) {
7282 use = uses->items[i];
7283 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7284 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7285 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7286 {
7287 xmlChar *str = NULL;
7288
7289 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7290 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7291 node, NULL,
7292 "Skipping duplicate attribute use prohibition '%s'",
7293 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7294 NULL, NULL);
7295 FREE_AND_NULL(str)
7296 return(NULL);
7297 }
7298 }
7299 }
7300 /*
7301 * Create the attribute prohibition helper component.
7302 */
7303 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7304 if (prohib == NULL)
7305 return(NULL);
7306 prohib->node = node;
7307 prohib->name = tmpName;
7308 prohib->targetNamespace = tmpNs;
7309 if (isRef) {
7310 /*
7311 * We need at least to resolve to the attribute declaration.
7312 */
7313 WXS_ADD_PENDING(pctxt, prohib);
7314 }
7315 return(WXS_BASIC_CAST prohib);
7316 } else {
7317 if (IS_SCHEMA(child, "annotation")) {
7318 /*
7319 * TODO: Should this go into the attr decl?
7320 */
7321 use->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7322 child = child->next;
7323 }
7324 if (isRef) {
7325 if (child != NULL) {
7326 if (IS_SCHEMA(child, "simpleType"))
7327 /*
7328 * 3.2.3 : 3.2
7329 * If ref is present, then all of <simpleType>,
7330 * form and type must be absent.
7331 */
7332 xmlSchemaPContentErr(pctxt,
7333 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7334 NULL, node, child, NULL,
7335 "(annotation?)");
7336 else
7337 xmlSchemaPContentErr(pctxt,
7338 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7339 NULL, node, child, NULL,
7340 "(annotation?)");
7341 }
7342 } else {
7343 if (IS_SCHEMA(child, "simpleType")) {
7344 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7345 /*
7346 * 3.2.3 : 4
7347 * type and <simpleType> must not both be present.
7348 */
7349 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7350 NULL, node, child,
7351 "The attribute 'type' and the <simpleType> child "
7352 "are mutually exclusive", NULL);
7353 } else
7354 WXS_ATTRUSE_TYPEDEF(use) =
7355 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7356 child = child->next;
7357 }
7358 if (child != NULL)
7359 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7360 NULL, node, child, NULL,
7361 "(annotation?, simpleType?)");
7362 }
7363 }
7364 return (WXS_BASIC_CAST use);
7365}
7366
7367
7368static xmlSchemaAttributePtr
7369xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7370 xmlSchemaPtr schema,
7371 xmlNodePtr node)
7372{
7373 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007374 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007375 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007376 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007377
7378 /*
7379 * Note that the w3c spec assumes the schema to be validated with schema
7380 * for schemas beforehand.
7381 *
7382 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007383 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007384 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7385 return (NULL);
7386 /*
7387 * 3.2.3 : 3.1
7388 * One of ref or name must be present, but not both
7389 */
7390 attr = xmlSchemaGetPropNode(node, "name");
7391 if (attr == NULL) {
7392 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7393 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007394 return (NULL);
7395 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007396 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7397 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7398 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007400 /*
7401 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7402 * TODO: Move this to the component layer.
7403 */
7404 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7405 xmlSchemaPSimpleTypeErr(pctxt,
7406 XML_SCHEMAP_NO_XMLNS,
7407 NULL, (xmlNodePtr) attr,
7408 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7409 "The value of the attribute must not match 'xmlns'",
7410 NULL, NULL);
7411 return (NULL);
7412 }
7413 /*
7414 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7415 * TODO: Move this to the component layer.
7416 * Or better leave it here and add it to the component layer
7417 * if we have a schema construction API.
7418 */
7419 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7420 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7421 XML_SCHEMAP_NO_XSI, node, NULL,
7422 "The target namespace must not match '%s'",
7423 xmlSchemaInstanceNs, NULL);
7424 }
7425
7426 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7427 pctxt->targetNamespace, node, 1);
7428 if (ret == NULL)
7429 return (NULL);
7430 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7431
7432 /*
7433 * Check for illegal attributes.
7434 */
7435 attr = node->properties;
7436 while (attr != NULL) {
7437 if (attr->ns == NULL) {
7438 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7439 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7440 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7441 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7442 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7443 {
7444 xmlSchemaPIllegalAttrErr(pctxt,
7445 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7446 }
7447 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7448 xmlSchemaPIllegalAttrErr(pctxt,
7449 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7450 }
7451 attr = attr->next;
7452 }
7453 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7454 node, "type", &ret->typeNs, &ret->typeName);
7455
7456 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007457 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007458 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007459 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007460 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007461 if (ret->defValue != NULL)
7462 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007463 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007464 * Attribute "default".
7465 */
7466 attr = xmlSchemaGetPropNode(node, "default");
7467 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007468 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007469 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007470 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 */
7472 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007473 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7474 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007475 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007476 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007477 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007478 /*
7479 * And now for the children...
7480 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007481 child = node->children;
7482 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007483 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007484 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007485 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007486 if (IS_SCHEMA(child, "simpleType")) {
7487 if (ret->typeName != NULL) {
7488 /*
7489 * 3.2.3 : 4
7490 * type and <simpleType> must not both be present.
7491 */
7492 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7493 NULL, node, child,
7494 "The attribute 'type' and the <simpleType> child "
7495 "are mutually exclusive", NULL);
7496 } else
7497 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7498 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007499 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007500 if (child != NULL)
7501 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7502 NULL, node, child, NULL,
7503 "(annotation?, simpleType?)");
7504
Daniel Veillard4255d502002-04-16 15:50:10 +00007505 return (ret);
7506}
7507
7508/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007509 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007510 * @ctxt: a schema validation context
7511 * @schema: the schema being built
7512 * @node: a subtree containing XML Schema informations
7513 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007514 * Parse an attribute group definition reference.
7515 * Note that a reference to an attribute group does not
7516 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007517 * *WARNING* this interface is highly subject to change
7518 *
7519 * Returns the attribute group or NULL in case of error.
7520 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007521static xmlSchemaQNameRefPtr
7522xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7523 xmlSchemaPtr schema,
7524 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007525{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007526 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007527 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007528 xmlAttrPtr attr;
7529 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007530
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007531 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007532 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007533
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007535 if (attr == NULL) {
7536 xmlSchemaPMissingAttrErr(pctxt,
7537 XML_SCHEMAP_S4S_ATTR_MISSING,
7538 NULL, node, "ref", NULL);
7539 return (NULL);
7540 }
7541 xmlSchemaPValAttrNodeQName(pctxt, schema,
7542 NULL, attr, &refNs, &ref);
7543 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7544 return(NULL);
7545
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007546 /*
7547 * Check for illegal attributes.
7548 */
7549 attr = node->properties;
7550 while (attr != NULL) {
7551 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007552 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007554 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007555 xmlSchemaPIllegalAttrErr(pctxt,
7556 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007557 }
7558 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007559 xmlSchemaPIllegalAttrErr(pctxt,
7560 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007561 }
7562 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007564 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007565 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7566
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007567 /*
7568 * And now for the children...
7569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007570 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007572 /*
7573 * TODO: We do not have a place to store the annotation, do we?
7574 */
7575 xmlSchemaParseAnnotation(pctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007576 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007577 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007578 if (child != NULL) {
7579 xmlSchemaPContentErr(pctxt,
7580 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7581 NULL, node, child, NULL,
7582 "(annotation?)");
7583 }
7584
7585 /*
7586 * Handle attribute group redefinitions.
7587 */
7588 if (pctxt->isRedefine && pctxt->redef &&
7589 (pctxt->redef->item->type ==
7590 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7591 (ref == pctxt->redef->refName) &&
7592 (refNs == pctxt->redef->refTargetNs))
7593 {
7594 /*
7595 * SPEC src-redefine:
7596 * (7.1) "If it has an <attributeGroup> among its contents
7597 * the ·actual value· of whose ref [attribute] is the same
7598 * as the ·actual value· of its own name attribute plus
7599 * target namespace, then it must have exactly one such group."
7600 */
7601 if (pctxt->redefCounter != 0) {
7602 xmlChar *str = NULL;
7603
7604 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7605 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7606 "The redefining attribute group definition "
7607 "'%s' must not contain more than one "
7608 "reference to the redefined definition",
7609 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7610 FREE_AND_NULL(str);
7611 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007612 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007613 pctxt->redefCounter++;
7614 /*
7615 * URGENT TODO: How to ensure that the reference will not be
7616 * handled by the normal component resolution mechanism?
7617 */
7618 ret = xmlSchemaNewQNameRef(pctxt,
7619 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7620 if (ret == NULL)
7621 return(NULL);
7622 ret->node = node;
7623 pctxt->redef->reference = WXS_BASIC_CAST ret;
7624 } else {
7625 /*
7626 * Create a QName-reference helper component. We will substitute this
7627 * component for the attribute uses of the referenced attribute group
7628 * definition.
7629 */
7630 ret = xmlSchemaNewQNameRef(pctxt,
7631 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7632 if (ret == NULL)
7633 return(NULL);
7634 ret->node = node;
7635 /* Add to pending items, to be able to resolve the reference. */
7636 WXS_ADD_PENDING(pctxt, ret);
7637 }
7638 return (ret);
7639}
7640
7641/**
7642 * xmlSchemaParseAttributeGroupDefinition:
7643 * @pctxt: a schema validation context
7644 * @schema: the schema being built
7645 * @node: a subtree containing XML Schema informations
7646 *
7647 * parse a XML schema Attribute Group declaration
7648 * *WARNING* this interface is highly subject to change
7649 *
7650 * Returns the attribute group definition or NULL in case of error.
7651 */
7652static xmlSchemaAttributeGroupPtr
7653xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7654 xmlSchemaPtr schema,
7655 xmlNodePtr node)
7656{
7657 const xmlChar *name;
7658 xmlSchemaAttributeGroupPtr ret;
7659 xmlNodePtr child = NULL;
7660 xmlAttrPtr attr;
7661 int hasRefs = 0;
7662
7663 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7664 return (NULL);
7665
7666 attr = xmlSchemaGetPropNode(node, "name");
7667 if (attr == NULL) {
7668 xmlSchemaPMissingAttrErr(pctxt,
7669 XML_SCHEMAP_S4S_ATTR_MISSING,
7670 NULL, node, "name", NULL);
7671 return (NULL);
7672 }
7673 /*
7674 * The name is crucial, exit if invalid.
7675 */
7676 if (xmlSchemaPValAttrNode(pctxt,
7677 NULL, attr,
7678 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7679 return (NULL);
7680 }
7681 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7682 name, pctxt->targetNamespace, node);
7683 if (ret == NULL)
7684 return (NULL);
7685 /*
7686 * Check for illegal attributes.
7687 */
7688 attr = node->properties;
7689 while (attr != NULL) {
7690 if (attr->ns == NULL) {
7691 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7692 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7693 {
7694 xmlSchemaPIllegalAttrErr(pctxt,
7695 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7696 }
7697 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7698 xmlSchemaPIllegalAttrErr(pctxt,
7699 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7700 }
7701 attr = attr->next;
7702 }
7703 /* Attribute ID */
7704 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7705 /*
7706 * And now for the children...
7707 */
7708 child = node->children;
7709 if (IS_SCHEMA(child, "annotation")) {
7710 ret->annot = xmlSchemaParseAnnotation(pctxt, schema, child, 1);
7711 child = child->next;
7712 }
7713 /*
7714 * Parse contained attribute decls/refs.
7715 */
7716 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7717 (xmlSchemaItemListPtr *) &(ret->attrUses),
7718 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7719 return(NULL);
7720 if (hasRefs)
7721 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7722 /*
7723 * Parse the attribute wildcard.
7724 */
7725 if (IS_SCHEMA(child, "anyAttribute")) {
7726 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7727 schema, child);
7728 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007729 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007730 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007731 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007732 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007733 NULL, node, child, NULL,
7734 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007735 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007736 return (ret);
7737}
7738
7739/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007740 * xmlSchemaPValAttrFormDefault:
7741 * @value: the value
7742 * @flags: the flags to be modified
7743 * @flagQualified: the specific flag for "qualified"
7744 *
7745 * Returns 0 if the value is valid, 1 otherwise.
7746 */
7747static int
7748xmlSchemaPValAttrFormDefault(const xmlChar *value,
7749 int *flags,
7750 int flagQualified)
7751{
7752 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7753 if ((*flags & flagQualified) == 0)
7754 *flags |= flagQualified;
7755 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 return (1);
7757
William M. Brack2f2a6632004-08-20 23:09:47 +00007758 return (0);
7759}
7760
7761/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007762 * xmlSchemaPValAttrBlockFinal:
7763 * @value: the value
7764 * @flags: the flags to be modified
7765 * @flagAll: the specific flag for "#all"
7766 * @flagExtension: the specific flag for "extension"
7767 * @flagRestriction: the specific flag for "restriction"
7768 * @flagSubstitution: the specific flag for "substitution"
7769 * @flagList: the specific flag for "list"
7770 * @flagUnion: the specific flag for "union"
7771 *
7772 * Validates the value of the attribute "final" and "block". The value
7773 * is converted into the specified flag values and returned in @flags.
7774 *
7775 * Returns 0 if the value is valid, 1 otherwise.
7776 */
7777
7778static int
7779xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007780 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007781 int flagAll,
7782 int flagExtension,
7783 int flagRestriction,
7784 int flagSubstitution,
7785 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007786 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007787{
7788 int ret = 0;
7789
7790 /*
7791 * TODO: This does not check for dublicate entries.
7792 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007793 if ((flags == NULL) || (value == NULL))
7794 return (-1);
7795 if (value[0] == 0)
7796 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007797 if (xmlStrEqual(value, BAD_CAST "#all")) {
7798 if (flagAll != -1)
7799 *flags |= flagAll;
7800 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007801 if (flagExtension != -1)
7802 *flags |= flagExtension;
7803 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007804 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007805 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007806 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007807 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007808 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007809 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007810 *flags |= flagUnion;
7811 }
7812 } else {
7813 const xmlChar *end, *cur = value;
7814 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007815
Daniel Veillardc0826a72004-08-10 14:17:33 +00007816 do {
7817 while (IS_BLANK_CH(*cur))
7818 cur++;
7819 end = cur;
7820 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7821 end++;
7822 if (end == cur)
7823 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007824 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007825 if (xmlStrEqual(item, BAD_CAST "extension")) {
7826 if (flagExtension != -1) {
7827 if ((*flags & flagExtension) == 0)
7828 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007829 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007830 ret = 1;
7831 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7832 if (flagRestriction != -1) {
7833 if ((*flags & flagRestriction) == 0)
7834 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007835 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007836 ret = 1;
7837 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7838 if (flagSubstitution != -1) {
7839 if ((*flags & flagSubstitution) == 0)
7840 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007841 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007842 ret = 1;
7843 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7844 if (flagList != -1) {
7845 if ((*flags & flagList) == 0)
7846 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007847 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007848 ret = 1;
7849 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7850 if (flagUnion != -1) {
7851 if ((*flags & flagUnion) == 0)
7852 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007854 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007856 ret = 1;
7857 if (item != NULL)
7858 xmlFree(item);
7859 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007860 } while ((ret == 0) && (*cur != 0));
7861 }
7862
Daniel Veillardc0826a72004-08-10 14:17:33 +00007863 return (ret);
7864}
7865
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007866static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007867xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007868 xmlSchemaIDCPtr idc,
7869 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007870 xmlAttrPtr attr,
7871 int isField)
7872{
7873 xmlNodePtr node;
7874
7875 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007876 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007877 * Schema Component Constraint: Selector Value OK
7878 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007879 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007880 * in [XPath].
7881 */
7882 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007883 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007884 XML_SCHEMAP_INTERNAL,
7885 "Internal error: xmlSchemaCheckCSelectorXPath, "
7886 "the selector is not specified.\n", NULL, NULL);
7887 return (-1);
7888 }
7889 if (attr == NULL)
7890 node = idc->node;
7891 else
7892 node = (xmlNodePtr) attr;
7893 if (selector->xpath == NULL) {
7894 xmlSchemaPCustomErr(ctxt,
7895 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007896 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007897 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007898 "The XPath expression of the selector is not valid", NULL);
7899 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7900 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007901 const xmlChar **nsArray = NULL;
7902 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007903 /*
7904 * Compile the XPath expression.
7905 */
7906 /*
7907 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007908 * TODO: Call xmlPatterncompile with different options for selector/
7909 * field.
7910 */
7911 nsList = xmlGetNsList(attr->doc, attr->parent);
7912 /*
7913 * Build an array of prefixes and namespaces.
7914 */
7915 if (nsList != NULL) {
7916 int i, count = 0;
7917 xmlNsPtr ns;
7918
7919 for (i = 0; nsList[i] != NULL; i++)
7920 count++;
7921
7922 nsArray = (const xmlChar **) xmlMalloc(
7923 (count * 2 + 1) * sizeof(const xmlChar *));
7924 if (nsArray == NULL) {
7925 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7926 NULL);
7927 return (-1);
7928 }
7929 for (i = 0; i < count; i++) {
7930 ns = nsList[i];
7931 nsArray[2 * i] = nsList[i]->href;
7932 nsArray[2 * i + 1] = nsList[i]->prefix;
7933 }
7934 nsArray[count * 2] = NULL;
7935 xmlFree(nsList);
7936 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 /*
7938 * TODO: Differentiate between "selector" and "field".
7939 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007940 if (isField)
7941 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007942 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007943 else
7944 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007945 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007946 if (nsArray != NULL)
7947 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007948
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007949 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007950 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007951 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007952 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007953 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007954 "The XPath expression '%s' could not be "
7955 "compiled", selector->xpath);
7956 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007957 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007958 }
7959 return (0);
7960}
7961
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007962#define ADD_ANNOTATION(annot) \
7963 xmlSchemaAnnotPtr cur = item->annot; \
7964 if (item->annot == NULL) { \
7965 item->annot = annot; \
7966 return (annot); \
7967 } \
7968 cur = item->annot; \
7969 if (cur->next != NULL) { \
7970 cur = cur->next; \
7971 } \
7972 cur->next = annot;
7973
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007974/**
7975 * xmlSchemaAssignAnnotation:
7976 * @item: the schema component
7977 * @annot: the annotation
7978 *
7979 * Adds the annotation to the given schema component.
7980 *
7981 * Returns the given annotaion.
7982 */
7983static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007984xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7985 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007986{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 if ((annItem == NULL) || (annot == NULL))
7988 return (NULL);
7989 switch (annItem->type) {
7990 case XML_SCHEMA_TYPE_ELEMENT: {
7991 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7992 ADD_ANNOTATION(annot)
7993 }
7994 break;
7995 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7996 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7997 ADD_ANNOTATION(annot)
7998 }
7999 break;
8000 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8001 case XML_SCHEMA_TYPE_ANY: {
8002 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8003 ADD_ANNOTATION(annot)
8004 }
8005 break;
8006 case XML_SCHEMA_TYPE_PARTICLE:
8007 case XML_SCHEMA_TYPE_IDC_KEY:
8008 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008009 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008010 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8011 ADD_ANNOTATION(annot)
8012 }
8013 break;
8014 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8015 xmlSchemaAttributeGroupPtr item =
8016 (xmlSchemaAttributeGroupPtr) annItem;
8017 ADD_ANNOTATION(annot)
8018 }
8019 break;
8020 case XML_SCHEMA_TYPE_NOTATION: {
8021 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8022 ADD_ANNOTATION(annot)
8023 }
8024 break;
8025 case XML_SCHEMA_FACET_MININCLUSIVE:
8026 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8027 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8028 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8029 case XML_SCHEMA_FACET_TOTALDIGITS:
8030 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8031 case XML_SCHEMA_FACET_PATTERN:
8032 case XML_SCHEMA_FACET_ENUMERATION:
8033 case XML_SCHEMA_FACET_WHITESPACE:
8034 case XML_SCHEMA_FACET_LENGTH:
8035 case XML_SCHEMA_FACET_MAXLENGTH:
8036 case XML_SCHEMA_FACET_MINLENGTH: {
8037 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8038 ADD_ANNOTATION(annot)
8039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008040 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008041 case XML_SCHEMA_TYPE_SIMPLE:
8042 case XML_SCHEMA_TYPE_COMPLEX: {
8043 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8044 ADD_ANNOTATION(annot)
8045 }
8046 break;
8047 case XML_SCHEMA_TYPE_GROUP: {
8048 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8049 ADD_ANNOTATION(annot)
8050 }
8051 break;
8052 case XML_SCHEMA_TYPE_SEQUENCE:
8053 case XML_SCHEMA_TYPE_CHOICE:
8054 case XML_SCHEMA_TYPE_ALL: {
8055 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8056 ADD_ANNOTATION(annot)
8057 }
8058 break;
8059 default:
8060 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008061 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008062 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008063 "Internal error: xmlSchemaAddAnnotation, "
8064 "The item is not a annotated schema component", NULL);
8065 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008066 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008067 return (annot);
8068}
8069
8070/**
8071 * xmlSchemaParseIDCSelectorAndField:
8072 * @ctxt: a schema validation context
8073 * @schema: the schema being built
8074 * @node: a subtree containing XML Schema informations
8075 *
8076 * Parses a XML Schema identity-contraint definition's
8077 * <selector> and <field> elements.
8078 *
8079 * Returns the parsed identity-constraint definition.
8080 */
8081static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008082xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008083 xmlSchemaPtr schema,
8084 xmlSchemaIDCPtr idc,
8085 xmlNodePtr node,
8086 int isField)
8087{
8088 xmlSchemaIDCSelectPtr item;
8089 xmlNodePtr child = NULL;
8090 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008091
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008092 /*
8093 * Check for illegal attributes.
8094 */
8095 attr = node->properties;
8096 while (attr != NULL) {
8097 if (attr->ns == NULL) {
8098 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8099 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008100 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008101 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008102 }
8103 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008104 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008105 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008106 }
8107 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008108 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008109 /*
8110 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008111 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008112 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8113 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008114 xmlSchemaPErrMemory(ctxt,
8115 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008116 NULL);
8117 return (NULL);
8118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008119 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008120 /*
8121 * Attribute "xpath" (mandatory).
8122 */
8123 attr = xmlSchemaGetPropNode(node, "xpath");
8124 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008125 xmlSchemaPMissingAttrErr(ctxt,
8126 XML_SCHEMAP_S4S_ATTR_MISSING,
8127 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008128 "name", NULL);
8129 } else {
8130 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8131 /*
8132 * URGENT TODO: "field"s have an other syntax than "selector"s.
8133 */
8134
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008135 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8136 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008137 xmlSchemaPErr(ctxt,
8138 (xmlNodePtr) attr,
8139 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008140 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008141 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008142 NULL, NULL);
8143 }
8144
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008145 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008146 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008147 /*
8148 * And now for the children...
8149 */
8150 child = node->children;
8151 if (IS_SCHEMA(child, "annotation")) {
8152 /*
8153 * Add the annotation to the parent IDC.
8154 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008155 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008156 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008157 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008159 if (child != NULL) {
8160 xmlSchemaPContentErr(ctxt,
8161 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008162 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008163 NULL, "(annotation?)");
8164 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008165
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008166 return (item);
8167}
8168
8169/**
8170 * xmlSchemaParseIDC:
8171 * @ctxt: a schema validation context
8172 * @schema: the schema being built
8173 * @node: a subtree containing XML Schema informations
8174 *
8175 * Parses a XML Schema identity-contraint definition.
8176 *
8177 * Returns the parsed identity-constraint definition.
8178 */
8179static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008180xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008181 xmlSchemaPtr schema,
8182 xmlNodePtr node,
8183 xmlSchemaTypeType idcCategory,
8184 const xmlChar *targetNamespace)
8185{
8186 xmlSchemaIDCPtr item = NULL;
8187 xmlNodePtr child = NULL;
8188 xmlAttrPtr attr;
8189 const xmlChar *name = NULL;
8190 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008192 /*
8193 * Check for illegal attributes.
8194 */
8195 attr = node->properties;
8196 while (attr != NULL) {
8197 if (attr->ns == NULL) {
8198 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8199 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8200 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8201 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008202 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008203 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008204 }
8205 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008207 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008208 }
8209 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008210 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008211 /*
8212 * Attribute "name" (mandatory).
8213 */
8214 attr = xmlSchemaGetPropNode(node, "name");
8215 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008216 xmlSchemaPMissingAttrErr(ctxt,
8217 XML_SCHEMAP_S4S_ATTR_MISSING,
8218 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008219 "name", NULL);
8220 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008222 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008223 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8224 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008225 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008226 /* Create the component. */
8227 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8228 idcCategory, node);
8229 if (item == NULL)
8230 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008231
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008232 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008233 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8234 /*
8235 * Attribute "refer" (mandatory).
8236 */
8237 attr = xmlSchemaGetPropNode(node, "refer");
8238 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlSchemaPMissingAttrErr(ctxt,
8240 XML_SCHEMAP_S4S_ATTR_MISSING,
8241 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008242 "refer", NULL);
8243 } else {
8244 /*
8245 * Create a reference item.
8246 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008247 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008248 NULL, NULL);
8249 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008250 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008251 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008252 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008253 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008254 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008255 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008256 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008257 }
8258 }
8259 /*
8260 * And now for the children...
8261 */
8262 child = node->children;
8263 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008264 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008265 child = child->next;
8266 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008267 if (child == NULL) {
8268 xmlSchemaPContentErr(ctxt,
8269 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008270 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008271 "A child element is missing",
8272 "(annotation?, (selector, field+))");
8273 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008274 /*
8275 * Child element <selector>.
8276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008277 if (IS_SCHEMA(child, "selector")) {
8278 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008279 item, child, 0);
8280 child = child->next;
8281 /*
8282 * Child elements <field>.
8283 */
8284 if (IS_SCHEMA(child, "field")) {
8285 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008286 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008287 item, child, 1);
8288 if (field != NULL) {
8289 field->index = item->nbFields;
8290 item->nbFields++;
8291 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008292 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008293 else
8294 item->fields = field;
8295 lastField = field;
8296 }
8297 child = child->next;
8298 } while (IS_SCHEMA(child, "field"));
8299 } else {
8300 xmlSchemaPContentErr(ctxt,
8301 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008302 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008303 NULL, "(annotation?, (selector, field+))");
8304 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008305 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008306 if (child != NULL) {
8307 xmlSchemaPContentErr(ctxt,
8308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008309 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008310 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008311 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008312
8313 return (item);
8314}
8315
Daniel Veillardc0826a72004-08-10 14:17:33 +00008316/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008317 * xmlSchemaParseElement:
8318 * @ctxt: a schema validation context
8319 * @schema: the schema being built
8320 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008321 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008322 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008323 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008324 * *WARNING* this interface is highly subject to change
8325 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008326 * Returns the element declaration or a particle; NULL in case
8327 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008328 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008330xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008331 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008332{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008333 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008334 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008335 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008336 xmlNodePtr child = NULL;
8337 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008338 int min, max, isRef = 0;
8339 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008340
8341 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8342 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008343
Daniel Veillard4255d502002-04-16 15:50:10 +00008344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008345 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008346
8347 if (isElemRef != NULL)
8348 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008349 /*
8350 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 * robust.
8353 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008354 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008355 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008356 if ((topLevel) || (attr == NULL)) {
8357 if (nameAttr == NULL) {
8358 xmlSchemaPMissingAttrErr(ctxt,
8359 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008360 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008361 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008362 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008363 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008364 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008365
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008366 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008367 child = node->children;
8368 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008369 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008370 child = child->next;
8371 }
8372 /*
8373 * Skip particle part if a global declaration.
8374 */
8375 if (topLevel)
8376 goto declaration_part;
8377 /*
8378 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008379 */
8380 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8381 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8382 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008383 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8384 if (particle == NULL)
8385 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008389 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008390 const xmlChar *refNs = NULL, *ref = NULL;
8391 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008392 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008393 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008394 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008395 if (isElemRef != NULL)
8396 *isElemRef = 1;
8397
Daniel Veillardc0826a72004-08-10 14:17:33 +00008398 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008399 NULL, attr, &refNs, &ref);
8400 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008401 /*
8402 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008403 */
8404 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008406 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008407 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008408 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008409 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008410 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008411 attr = node->properties;
8412 while (attr != NULL) {
8413 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008414 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8415 xmlStrEqual(attr->name, BAD_CAST "name") ||
8416 xmlStrEqual(attr->name, BAD_CAST "id") ||
8417 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8418 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8419 {
8420 attr = attr->next;
8421 continue;
8422 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008423 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008424 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008425 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008426 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008427 "Only the attributes 'minOccurs', 'maxOccurs' and "
8428 "'id' are allowed in addition to 'ref'");
8429 break;
8430 }
8431 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8432 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008433 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008434 }
8435 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008436 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008437 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008438 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008439 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008440 if (child != NULL) {
8441 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008442 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008443 }
8444 if ((min == 0) && (max == 0))
8445 goto return_null;
8446 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008447 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008448 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008449 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008450 ref, refNs);
8451 if (refer == NULL)
8452 goto return_null;
8453 particle->children = (xmlSchemaTreeItemPtr) refer;
8454 particle->annot = annot;
8455 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008456 * Add the particle to pending components, since the reference
8457 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008458 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008459 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008460 return ((xmlSchemaBasicItemPtr) particle);
8461 }
8462 /*
8463 * The declaration part ===============================================
8464 */
8465declaration_part:
8466 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008467 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008468 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8469
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008470 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008471 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008472 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008473 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008474 * Evaluate the target namespace.
8475 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008476 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008477 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008478 } else {
8479 attr = xmlSchemaGetPropNode(node, "form");
8480 if (attr != NULL) {
8481 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8482 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008483 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008484 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008485 xmlSchemaPSimpleTypeErr(ctxt,
8486 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8487 NULL, (xmlNodePtr) attr,
8488 NULL, "(qualified | unqualified)",
8489 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008490 }
8491 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008492 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008493 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008494 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008495 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008496 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008497 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008498 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008499 * Check for illegal attributes.
8500 */
William M. Bracke7091952004-05-11 15:09:58 +00008501 attr = node->properties;
8502 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008503 if (attr->ns == NULL) {
8504 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8505 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008506 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008507 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008508 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008509 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008510 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8511 {
8512 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008513 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008514 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008515 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008516 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008517 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008518 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008519 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008520 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8521 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008522 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8523
8524 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008526 }
8527 }
8528 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008529
Daniel Veillardc0826a72004-08-10 14:17:33 +00008530 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008532 }
8533 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008534 }
William M. Bracke7091952004-05-11 15:09:58 +00008535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008536 * Extract/validate attributes.
8537 */
8538 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008539 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008540 * Process top attributes of global element declarations here.
8541 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008542 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8543 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008544 xmlSchemaPValAttrQName(ctxt, schema,
8545 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008546 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008547 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008548 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008549 /*
8550 * Attribute "final".
8551 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008552 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008553 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008554 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8555 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8556 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8557 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008558 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008559 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8560 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008561 -1,
8562 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8563 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008564 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008565 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008566 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008567 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008568 attrValue, NULL, NULL, NULL);
8569 }
8570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008572 /*
8573 * Attribute "block".
8574 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008575 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008576 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008577 /*
8578 * Apply default "block" values.
8579 */
8580 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8581 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8582 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8583 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8584 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8585 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008586 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008587 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8588 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008589 -1,
8590 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008592 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8593 xmlSchemaPSimpleTypeErr(ctxt,
8594 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008595 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 "restriction | substitution))", attrValue,
8598 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008599 }
8600 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008601 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008602 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008603
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008604 attr = xmlSchemaGetPropNode(node, "type");
8605 if (attr != NULL) {
8606 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008607 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008608 &(decl->namedTypeNs), &(decl->namedType));
8609 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008610 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611 }
8612 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8613 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008614 if (attr != NULL) {
8615 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008616 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 /*
8618 * 3.3.3 : 1
8619 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008620 */
8621 xmlSchemaPMutualExclAttrErr(ctxt,
8622 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008623 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008624 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008625 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8626 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008627 }
William M. Bracke7091952004-05-11 15:09:58 +00008628 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008629 /*
8630 * And now for the children...
8631 */
William M. Bracke7091952004-05-11 15:09:58 +00008632 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 /*
8634 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008635 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008637 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008638 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 xmlSchemaPContentErr(ctxt,
8640 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008641 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008642 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008643 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008644 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008645 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008646 child = child->next;
8647 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 /*
8649 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008650 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008652 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008653 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 xmlSchemaPContentErr(ctxt,
8655 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008656 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008657 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008658 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008659 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008660 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008661 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008662 }
William M. Bracke7091952004-05-11 15:09:58 +00008663 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008664 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008665 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008666 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008667 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008668 } else if (IS_SCHEMA(child, "key")) {
8669 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008670 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008671 } else if (IS_SCHEMA(child, "keyref")) {
8672 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008673 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008674 }
8675 if (lastIDC != NULL)
8676 lastIDC->next = curIDC;
8677 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008678 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008679 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008680 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008681 }
8682 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008683 xmlSchemaPContentErr(ctxt,
8684 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008685 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008686 NULL, "(annotation?, ((simpleType | complexType)?, "
8687 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008689 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008690 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008692 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008693 * different layer.
8694 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008695 FREE_AND_NULL(des)
8696 if (topLevel)
8697 return ((xmlSchemaBasicItemPtr) decl);
8698 else {
8699 particle->children = (xmlSchemaTreeItemPtr) decl;
8700 return ((xmlSchemaBasicItemPtr) particle);
8701 }
8702
8703return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 FREE_AND_NULL(des);
8705 if (annot != NULL) {
8706 if (particle != NULL)
8707 particle->annot = NULL;
8708 if (decl != NULL)
8709 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008710 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008711 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008712 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008713}
8714
8715/**
8716 * xmlSchemaParseUnion:
8717 * @ctxt: a schema validation context
8718 * @schema: the schema being built
8719 * @node: a subtree containing XML Schema informations
8720 *
8721 * parse a XML schema Union definition
8722 * *WARNING* this interface is highly subject to change
8723 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008724 * Returns -1 in case of internal error, 0 in case of success and a positive
8725 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008726 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008727static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008728xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008729 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008730{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008731 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008732 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008733 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008734 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008735
8736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008737 return (-1);
8738 /* Not a component, don't create it. */
8739 type = ctxt->ctxtType;
8740 /*
8741 * Mark the simple type as being of variety "union".
8742 */
8743 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008745 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8746 * then the ·simple ur-type definition·."
8747 */
8748 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008749 /*
8750 * Check for illegal attributes.
8751 */
8752 attr = node->properties;
8753 while (attr != NULL) {
8754 if (attr->ns == NULL) {
8755 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8756 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008757 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008758 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008759 }
8760 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008761 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008762 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008763 }
8764 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008765 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008766 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008767 /*
8768 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008769 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008770 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008771 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008772 if (attr != NULL) {
8773 const xmlChar *end;
8774 xmlChar *tmp;
8775 const xmlChar *localName, *nsName;
8776 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8777 xmlSchemaQNameRefPtr ref;
8778
8779 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008780 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008781 do {
8782 while (IS_BLANK_CH(*cur))
8783 cur++;
8784 end = cur;
8785 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8786 end++;
8787 if (end == cur)
8788 break;
8789 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008790 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008791 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008792 /*
8793 * Create the member type link.
8794 */
8795 link = (xmlSchemaTypeLinkPtr)
8796 xmlMalloc(sizeof(xmlSchemaTypeLink));
8797 if (link == NULL) {
8798 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8799 "allocating a type link", NULL);
8800 return (-1);
8801 }
8802 link->type = NULL;
8803 link->next = NULL;
8804 if (lastLink == NULL)
8805 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008807 lastLink->next = link;
8808 lastLink = link;
8809 /*
8810 * Create a reference item.
8811 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008812 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008813 localName, nsName);
8814 if (ref == NULL) {
8815 FREE_AND_NULL(tmp)
8816 return (-1);
8817 }
8818 /*
8819 * Assign the reference to the link, it will be resolved
8820 * later during fixup of the union simple type.
8821 */
8822 link->type = (xmlSchemaTypePtr) ref;
8823 }
8824 FREE_AND_NULL(tmp)
8825 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008826 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008827
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008828 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008829 /*
8830 * And now for the children...
8831 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008832 child = node->children;
8833 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008834 /*
8835 * Add the annotation to the simple type ancestor.
8836 */
8837 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008838 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008839 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008840 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008841 if (IS_SCHEMA(child, "simpleType")) {
8842 xmlSchemaTypePtr subtype, last = NULL;
8843
8844 /*
8845 * Anchor the member types in the "subtypes" field of the
8846 * simple type.
8847 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008849 subtype = (xmlSchemaTypePtr)
8850 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8851 if (subtype != NULL) {
8852 if (last == NULL) {
8853 type->subtypes = subtype;
8854 last = subtype;
8855 } else {
8856 last->next = subtype;
8857 last = subtype;
8858 }
8859 last->next = NULL;
8860 }
8861 child = child->next;
8862 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008863 }
8864 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008865 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008866 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008867 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008868 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008869 if ((attr == NULL) && (type->subtypes == NULL)) {
8870 /*
8871 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008872 * Either the memberTypes [attribute] of the <union> element must
8873 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008874 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008875 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008876 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008877 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008878 "Either the attribute 'memberTypes' or "
8879 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008880 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008881 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008882}
8883
8884/**
8885 * xmlSchemaParseList:
8886 * @ctxt: a schema validation context
8887 * @schema: the schema being built
8888 * @node: a subtree containing XML Schema informations
8889 *
8890 * parse a XML schema List definition
8891 * *WARNING* this interface is highly subject to change
8892 *
William M. Bracke7091952004-05-11 15:09:58 +00008893 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008894 * 1 in case of success.
8895 */
8896static xmlSchemaTypePtr
8897xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008898 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008899{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008900 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008901 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008902 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008903
8904 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8905 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008906 /* Not a component, don't create it. */
8907 type = ctxt->ctxtType;
8908 /*
8909 * Mark the type as being of variety "list".
8910 */
8911 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008913 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8914 * then the ·simple ur-type definition·."
8915 */
8916 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008917 /*
8918 * Check for illegal attributes.
8919 */
8920 attr = node->properties;
8921 while (attr != NULL) {
8922 if (attr->ns == NULL) {
8923 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8924 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008925 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008926 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008927 }
8928 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008929 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008930 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008931 }
8932 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008934
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008935 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008936
William M. Brack2f2a6632004-08-20 23:09:47 +00008937 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008938 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8939 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008940 *
8941 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
8942 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00008943 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008944 xmlSchemaPValAttrQName(ctxt, schema, NULL,
8945 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00008946 /*
8947 * And now for the children...
8948 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008949 child = node->children;
8950 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008951 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008952 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008953 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008954 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008955 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008956 /*
8957 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008958 * Either the itemType [attribute] or the <simpleType> [child] of
8959 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008960 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008961 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008962 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008963 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008964 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008965 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008966 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008968 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008969 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008970 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008971 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008972 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008973 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008974 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008975 "Either the attribute 'itemType' or the <simpleType> child "
8976 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008977 }
8978 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008979 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008981 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008982 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008983 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008984 (type->subtypes == NULL) &&
8985 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008987 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008988 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008989 "Either the attribute 'itemType' or the <simpleType> child "
8990 "must be present", NULL);
8991 }
8992 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008993}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008994
Daniel Veillard4255d502002-04-16 15:50:10 +00008995/**
8996 * xmlSchemaParseSimpleType:
8997 * @ctxt: a schema validation context
8998 * @schema: the schema being built
8999 * @node: a subtree containing XML Schema informations
9000 *
9001 * parse a XML schema Simple Type definition
9002 * *WARNING* this interface is highly subject to change
9003 *
William M. Bracke7091952004-05-11 15:09:58 +00009004 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009005 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009006 */
9007static xmlSchemaTypePtr
9008xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009009 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009010{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009011 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009012 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009013 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009014 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009015 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009016
9017 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9018 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009019
Daniel Veillardc0826a72004-08-10 14:17:33 +00009020 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009021 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009022 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023 xmlSchemaPMissingAttrErr(ctxt,
9024 XML_SCHEMAP_S4S_ATTR_MISSING,
9025 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009026 "name", NULL);
9027 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009028 } else {
9029 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009030 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009031 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9032 return (NULL);
9033 /*
9034 * Skip built-in types.
9035 */
9036 if (ctxt->isS4S) {
9037 xmlSchemaTypePtr biType;
9038
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009039 if (ctxt->isRedefine) {
9040 /*
9041 * REDEFINE: Disallow redefinition of built-in-types.
9042 * TODO: It seems that the spec does not say anything
9043 * about this case.
9044 */
9045 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009046 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009047 "Redefinition of built-in simple types is not "
9048 "supported", NULL);
9049 return(NULL);
9050 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009051 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9052 if (biType != NULL)
9053 return (biType);
9054 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009055 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009056 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009057 /*
9058 * TargetNamespace:
9059 * SPEC "The ·actual value· of the targetNamespace [attribute]
9060 * of the <schema> ancestor element information item if present,
9061 * otherwise ·absent·.
9062 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009063 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009064#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009065 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009066#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009067 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009068 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009069 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009070#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009071 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009072 type = xmlSchemaAddType(ctxt, schema,
9073 XML_SCHEMA_TYPE_SIMPLE,
9074 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009075 ctxt->targetNamespace, node, 0);
9076#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009077 type = xmlSchemaAddType(ctxt, schema,
9078 XML_SCHEMA_TYPE_SIMPLE,
9079 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009080#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009081 if (type == NULL)
9082 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009083 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009084 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009085 /*
9086 * Check for illegal attributes.
9087 */
9088 attr = node->properties;
9089 while (attr != NULL) {
9090 if (attr->ns == NULL) {
9091 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009092 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009094 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009095 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009096 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009097 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009098 }
9099 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009101 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009102 /*
9103 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009104 *
9105 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009106 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009107 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9108 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009109 if (type == NULL)
9110 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009111 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009113 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9114 /*
9115 * Check for illegal attributes.
9116 */
9117 attr = node->properties;
9118 while (attr != NULL) {
9119 if (attr->ns == NULL) {
9120 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9121 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009122 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009123 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009124 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009125 }
9126 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009127 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009128 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009129 }
9130 attr = attr->next;
9131 }
9132 /*
9133 * Attribute "final".
9134 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009135 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009136 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009137 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9138 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9139 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9140 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9141 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9142 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009143 } else {
9144 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009145 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9146 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009147 XML_SCHEMAS_TYPE_FINAL_LIST,
9148 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9149
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009150 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009152 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009153 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009154 attrValue, NULL, NULL, NULL);
9155 }
9156 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009158 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009159 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 /*
9161 * And now for the children...
9162 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009163 oldCtxtType = ctxt->ctxtType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009164
Daniel Veillardc0826a72004-08-10 14:17:33 +00009165 ctxt->ctxtType = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009166
Daniel Veillard4255d502002-04-16 15:50:10 +00009167 child = node->children;
9168 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009169 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009170 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009172 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009174 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009175 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009176 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009177 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009178 XML_SCHEMA_TYPE_SIMPLE);
9179 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009180 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009181 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009182 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009183 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009184 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009185 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009186 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009187 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009188 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009189 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009190 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009191 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009192 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009193 /*
9194 * REDEFINE: SPEC src-redefine (5)
9195 * "Within the [children], each <simpleType> must have a
9196 * <restriction> among its [children] ... the ·actual value· of whose
9197 * base [attribute] must be the same as the ·actual value· of its own
9198 * name attribute plus target namespace;"
9199 */
9200 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9201 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009202 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009203 "<simpleType> must have a <restriction> child", NULL);
9204 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009205
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009206 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009207 return (type);
9208}
9209
Daniel Veillard4255d502002-04-16 15:50:10 +00009210/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009211 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009212 * @ctxt: the parser context
9213 * @schema: the schema being built
9214 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009215 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009216 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009217 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009218 * We will return a particle component with a qname-component or
9219 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009220 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009221static xmlSchemaTreeItemPtr
9222xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9223 xmlSchemaPtr schema,
9224 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009225{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009226 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009227 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009228 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009229 const xmlChar *ref = NULL, *refNs = NULL;
9230 int min, max;
9231
9232 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009233 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009234
9235 attr = xmlSchemaGetPropNode(node, "ref");
9236 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009237 xmlSchemaPMissingAttrErr(ctxt,
9238 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009239 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009240 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009241 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009243 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009244 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009245 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009246 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009247 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009248 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009249 /*
9250 * Check for illegal attributes.
9251 */
9252 attr = node->properties;
9253 while (attr != NULL) {
9254 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009255 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009256 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9257 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9258 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009259 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009261 }
9262 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009263 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009265 }
9266 attr = attr->next;
9267 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009268 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009269 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9270 if (item == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009271 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009272 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009273 * Create a qname-reference and set as the term; it will be substituted
9274 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009275 */
9276 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009277 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009278 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9279 /*
9280 * And now for the children...
9281 */
9282 child = node->children;
9283 /* TODO: Is annotation even allowed for a model group reference? */
9284 if (IS_SCHEMA(child, "annotation")) {
9285 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009286 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009287 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009288 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009289 child = child->next;
9290 }
9291 if (child != NULL) {
9292 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009293 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009294 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009295 "(annotation?)");
9296 }
9297 /*
9298 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9299 */
9300 if ((min == 0) && (max == 0))
9301 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009302
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009303 return ((xmlSchemaTreeItemPtr) item);
9304}
9305
9306/**
9307 * xmlSchemaParseModelGroupDefinition:
9308 * @ctxt: a schema validation context
9309 * @schema: the schema being built
9310 * @node: a subtree containing XML Schema informations
9311 *
9312 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009313 *
9314 * Note that the contraint src-redefine (6.2) can't be applied until
9315 * references have been resolved. So we will do this at the
9316 * component fixup level.
9317 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009318 * *WARNING* this interface is highly subject to change
9319 *
9320 * Returns -1 in case of error, 0 if the declaration is improper and
9321 * 1 in case of success.
9322 */
9323static xmlSchemaModelGroupDefPtr
9324xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9325 xmlSchemaPtr schema,
9326 xmlNodePtr node)
9327{
9328 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009330 xmlAttrPtr attr;
9331 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009332
9333 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009334 return (NULL);
9335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009336 attr = xmlSchemaGetPropNode(node, "name");
9337 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009338 xmlSchemaPMissingAttrErr(ctxt,
9339 XML_SCHEMAP_S4S_ATTR_MISSING,
9340 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009341 "name", NULL);
9342 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009343 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009344 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9345 return (NULL);
9346 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009347 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9348 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009349 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009350 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009351 /*
9352 * Check for illegal attributes.
9353 */
9354 attr = node->properties;
9355 while (attr != NULL) {
9356 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009357 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009358 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009359 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009360 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009361 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009362 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009363 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009364 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009365 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009366 attr = attr->next;
9367 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009368 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009369 /*
9370 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009371 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009372 child = node->children;
9373 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009374 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009375 child = child->next;
9376 }
9377 if (IS_SCHEMA(child, "all")) {
9378 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9379 XML_SCHEMA_TYPE_ALL, 0);
9380 child = child->next;
9381 } else if (IS_SCHEMA(child, "choice")) {
9382 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9383 XML_SCHEMA_TYPE_CHOICE, 0);
9384 child = child->next;
9385 } else if (IS_SCHEMA(child, "sequence")) {
9386 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9387 XML_SCHEMA_TYPE_SEQUENCE, 0);
9388 child = child->next;
9389 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009390
9391
9392
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009393 if (child != NULL) {
9394 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009396 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009397 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009398 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009399 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009400}
9401
9402/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009403 * xmlSchemaCleanupDoc:
9404 * @ctxt: a schema validation context
9405 * @node: the root of the document.
9406 *
9407 * removes unwanted nodes in a schemas document tree
9408 */
9409static void
9410xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9411{
9412 xmlNodePtr delete, cur;
9413
9414 if ((ctxt == NULL) || (root == NULL)) return;
9415
9416 /*
9417 * Remove all the blank text nodes
9418 */
9419 delete = NULL;
9420 cur = root;
9421 while (cur != NULL) {
9422 if (delete != NULL) {
9423 xmlUnlinkNode(delete);
9424 xmlFreeNode(delete);
9425 delete = NULL;
9426 }
9427 if (cur->type == XML_TEXT_NODE) {
9428 if (IS_BLANK_NODE(cur)) {
9429 if (xmlNodeGetSpacePreserve(cur) != 1) {
9430 delete = cur;
9431 }
9432 }
9433 } else if ((cur->type != XML_ELEMENT_NODE) &&
9434 (cur->type != XML_CDATA_SECTION_NODE)) {
9435 delete = cur;
9436 goto skip_children;
9437 }
9438
9439 /*
9440 * Skip to next node
9441 */
9442 if (cur->children != NULL) {
9443 if ((cur->children->type != XML_ENTITY_DECL) &&
9444 (cur->children->type != XML_ENTITY_REF_NODE) &&
9445 (cur->children->type != XML_ENTITY_NODE)) {
9446 cur = cur->children;
9447 continue;
9448 }
9449 }
9450 skip_children:
9451 if (cur->next != NULL) {
9452 cur = cur->next;
9453 continue;
9454 }
9455
9456 do {
9457 cur = cur->parent;
9458 if (cur == NULL)
9459 break;
9460 if (cur == root) {
9461 cur = NULL;
9462 break;
9463 }
9464 if (cur->next != NULL) {
9465 cur = cur->next;
9466 break;
9467 }
9468 } while (cur != NULL);
9469 }
9470 if (delete != NULL) {
9471 xmlUnlinkNode(delete);
9472 xmlFreeNode(delete);
9473 delete = NULL;
9474 }
9475}
9476
William M. Brack2f2a6632004-08-20 23:09:47 +00009477
William M. Brack2f2a6632004-08-20 23:09:47 +00009478static void
9479xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9480{
9481 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9482 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9483
9484 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9485 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9486
9487 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9488 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9489 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9490 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9491 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9492 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9493 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9494 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9495
9496 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9497 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9498 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9499 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9500 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9501 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9502}
9503
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009504static int
9505xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009506 xmlSchemaPtr schema,
9507 xmlNodePtr node)
9508{
9509 xmlAttrPtr attr;
9510 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009511 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009512
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009513 /*
9514 * Those flags should be moved to the parser context flags,
9515 * since they are not visible at the component level. I.e.
9516 * they are used if processing schema *documents* only.
9517 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009518 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009519 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009520
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009521 /*
9522 * Since the version is of type xs:token, we won't bother to
9523 * check it.
9524 */
9525 /* REMOVED:
9526 attr = xmlSchemaGetPropNode(node, "version");
9527 if (attr != NULL) {
9528 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9529 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9530 HFAILURE;
9531 }
9532 */
9533 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9534 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009535 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009536 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9537 HFAILURE;
9538 if (res != 0) {
9539 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9540 goto exit;
9541 }
9542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009543 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009544 if (attr != NULL) {
9545 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009546 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9547 XML_SCHEMAS_QUALIF_ELEM);
9548 HFAILURE;
9549 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009550 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009551 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009552 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009553 "(qualified | unqualified)", val, NULL, NULL, NULL);
9554 }
9555 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009556 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009557 if (attr != NULL) {
9558 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009559 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9560 XML_SCHEMAS_QUALIF_ATTR);
9561 HFAILURE;
9562 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009563 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009564 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009565 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009566 "(qualified | unqualified)", val, NULL, NULL, NULL);
9567 }
9568 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009569 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009570 if (attr != NULL) {
9571 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009572 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009573 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9574 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9575 -1,
9576 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009577 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9578 HFAILURE;
9579 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009580 xmlSchemaPSimpleTypeErr(ctxt,
9581 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009582 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009583 "(#all | List of (extension | restriction | list | union))",
9584 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009585 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009588 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009589 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9590 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009591 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9592 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009593 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9594 HFAILURE;
9595 if (res != 0) {
9596 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009597 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009599 "(#all | List of (extension | restriction | substitution))",
9600 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009602 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009603
9604exit:
9605 if (oldErrs != ctxt->nberrors)
9606 res = ctxt->err;
9607 return(res);
9608exit_failure:
9609 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009610}
9611
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009612/**
9613 * xmlSchemaParseSchemaTopLevel:
9614 * @ctxt: a schema validation context
9615 * @schema: the schemas
9616 * @nodes: the list of top level nodes
9617 *
9618 * Returns the internal XML Schema structure built from the resource or
9619 * NULL in case of error
9620 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009621static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009622xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9623 xmlSchemaPtr schema, xmlNodePtr nodes)
9624{
9625 xmlNodePtr child;
9626 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009627 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009628
9629 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009630 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009631
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009632 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009633 child = nodes;
9634 while ((IS_SCHEMA(child, "include")) ||
9635 (IS_SCHEMA(child, "import")) ||
9636 (IS_SCHEMA(child, "redefine")) ||
9637 (IS_SCHEMA(child, "annotation"))) {
9638 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009639 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009640 if (schema->annot == NULL)
9641 schema->annot = annot;
9642 else
9643 xmlSchemaFreeAnnot(annot);
9644 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009645 tmpOldErrs = ctxt->nberrors;
9646 res = xmlSchemaParseImport(ctxt, schema, child);
9647 HFAILURE;
9648 HSTOP(ctxt);
9649 if (tmpOldErrs != ctxt->nberrors)
9650 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009651 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009652 tmpOldErrs = ctxt->nberrors;
9653 res = xmlSchemaParseInclude(ctxt, schema, child);
9654 HFAILURE;
9655 HSTOP(ctxt);
9656 if (tmpOldErrs != ctxt->nberrors)
9657 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009658 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009659 tmpOldErrs = ctxt->nberrors;
9660 res = xmlSchemaParseRedefine(ctxt, schema, child);
9661 HFAILURE;
9662 HSTOP(ctxt);
9663 if (tmpOldErrs != ctxt->nberrors)
9664 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009665 }
9666 child = child->next;
9667 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009668 /*
9669 * URGENT TODO: Change the functions to return int results.
9670 * We need especially to catch internal errors.
9671 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009672 while (child != NULL) {
9673 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009674 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009675 child = child->next;
9676 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009677 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009678 child = child->next;
9679 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009680 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009681 child = child->next;
9682 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009683 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009684 child = child->next;
9685 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009686 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009687 child = child->next;
9688 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009689 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009690 child = child->next;
9691 } else if (IS_SCHEMA(child, "notation")) {
9692 xmlSchemaParseNotation(ctxt, schema, child);
9693 child = child->next;
9694 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009695 xmlSchemaPContentErr(ctxt,
9696 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009697 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009698 NULL, "((include | import | redefine | annotation)*, "
9699 "(((simpleType | complexType | group | attributeGroup) "
9700 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009701 child = child->next;
9702 }
9703 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009704 /*
9705 * TODO: We should add all annotations.
9706 */
9707 annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009708 if (schema->annot == NULL)
9709 schema->annot = annot;
9710 else
9711 xmlSchemaFreeAnnot(annot);
9712 child = child->next;
9713 }
9714 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009715exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009716 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009717 if (oldErrs != ctxt->nberrors)
9718 res = ctxt->err;
9719 return(res);
9720exit_failure:
9721 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009722}
9723
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009724static xmlSchemaSchemaRelationPtr
9725xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009726{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009727 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009728
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009729 ret = (xmlSchemaSchemaRelationPtr)
9730 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009731 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009732 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009733 return(NULL);
9734 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009735 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009736 return(ret);
9737}
9738
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009739#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009740static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009741xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009742{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009743 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009744}
9745#endif
9746
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009747static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009748xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9749{
9750 xmlSchemaRedefPtr prev;
9751
9752 while (redef != NULL) {
9753 prev = redef;
9754 redef = redef->next;
9755 xmlFree(prev);
9756 }
9757}
9758
9759static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009760xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9761{
9762 /*
9763 * After the construction context has been freed, there will be
9764 * no schema graph available any more. Only the schema buckets
9765 * will stay alive, which are put into the "schemasImports" and
9766 * "includes" slots of the xmlSchema.
9767 */
9768 if (con->buckets != NULL)
9769 xmlSchemaItemListFree(con->buckets);
9770 if (con->pending != NULL)
9771 xmlSchemaItemListFree(con->pending);
9772 if (con->substGroups != NULL)
9773 xmlHashFree(con->substGroups,
9774 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009775 if (con->redefs != NULL)
9776 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009777 if (con->dict != NULL)
9778 xmlDictFree(con->dict);
9779 xmlFree(con);
9780}
9781
9782static xmlSchemaConstructionCtxtPtr
9783xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9784{
9785 xmlSchemaConstructionCtxtPtr ret;
9786
9787 ret = (xmlSchemaConstructionCtxtPtr)
9788 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9789 if (ret == NULL) {
9790 xmlSchemaPErrMemory(NULL,
9791 "allocating schema construction context", NULL);
9792 return (NULL);
9793 }
9794 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9795
9796 ret->buckets = xmlSchemaItemListCreate();
9797 if (ret->buckets == NULL) {
9798 xmlSchemaPErrMemory(NULL,
9799 "allocating list of schema buckets", NULL);
9800 xmlFree(ret);
9801 return (NULL);
9802 }
9803 ret->pending = xmlSchemaItemListCreate();
9804 if (ret->pending == NULL) {
9805 xmlSchemaPErrMemory(NULL,
9806 "allocating list of pending global components", NULL);
9807 xmlSchemaConstructionCtxtFree(ret);
9808 return (NULL);
9809 }
9810 ret->dict = dict;
9811 xmlDictReference(dict);
9812 return(ret);
9813}
9814
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009815static xmlSchemaParserCtxtPtr
9816xmlSchemaParserCtxtCreate(void)
9817{
9818 xmlSchemaParserCtxtPtr ret;
9819
9820 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9821 if (ret == NULL) {
9822 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9823 NULL);
9824 return (NULL);
9825 }
9826 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9827 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009828 ret->attrProhibs = xmlSchemaItemListCreate();
9829 if (ret->attrProhibs == NULL) {
9830 xmlFree(ret);
9831 return(NULL);
9832 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009833 return(ret);
9834}
9835
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009836/**
9837 * xmlSchemaNewParserCtxtUseDict:
9838 * @URL: the location of the schema
9839 * @dict: the dictionary to be used
9840 *
9841 * Create an XML Schemas parse context for that file/resource expected
9842 * to contain an XML Schemas file.
9843 *
9844 * Returns the parser context or NULL in case of error
9845 */
9846static xmlSchemaParserCtxtPtr
9847xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9848{
9849 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009851 ret = xmlSchemaParserCtxtCreate();
9852 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009853 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009854 ret->dict = dict;
9855 xmlDictReference(dict);
9856 if (URL != NULL)
9857 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 return (ret);
9859}
9860
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009861static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009862xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9863{
9864 if (vctxt->pctxt == NULL) {
9865 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009866 vctxt->pctxt =
9867 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009868 else
9869 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9870 if (vctxt->pctxt == NULL) {
9871 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9872 "failed to create a temp. parser context");
9873 return (-1);
9874 }
9875 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009876 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9877 vctxt->warning, vctxt->userData);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009878 }
9879 return (0);
9880}
9881
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009882/**
9883 * xmlSchemaGetSchemaBucket:
9884 * @pctxt: the schema parser context
9885 * @schemaLocation: the URI of the schema document
9886 *
9887 * Returns a schema bucket if it was already parsed.
9888 *
9889 * Returns a schema bucket if it was already parsed from
9890 * @schemaLocation, NULL otherwise.
9891 */
9892static xmlSchemaBucketPtr
9893xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9894 const xmlChar *schemaLocation)
9895{
9896 xmlSchemaBucketPtr cur;
9897 xmlSchemaItemListPtr list;
9898
9899 list = pctxt->constructor->buckets;
9900 if (list->nbItems == 0)
9901 return(NULL);
9902 else {
9903 int i;
9904 for (i = 0; i < list->nbItems; i++) {
9905 cur = (xmlSchemaBucketPtr) list->items[i];
9906 /* Pointer comparison! */
9907 if (cur->schemaLocation == schemaLocation)
9908 return(cur);
9909 }
9910 }
9911 return(NULL);
9912}
9913
9914static xmlSchemaBucketPtr
9915xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9916 const xmlChar *schemaLocation,
9917 const xmlChar *targetNamespace)
9918{
9919 xmlSchemaBucketPtr cur;
9920 xmlSchemaItemListPtr list;
9921
9922 list = pctxt->constructor->buckets;
9923 if (list->nbItems == 0)
9924 return(NULL);
9925 else {
9926 int i;
9927 for (i = 0; i < list->nbItems; i++) {
9928 cur = (xmlSchemaBucketPtr) list->items[i];
9929 /* Pointer comparison! */
9930 if ((cur->origTargetNamespace == NULL) &&
9931 (cur->schemaLocation == schemaLocation) &&
9932 (cur->targetNamespace == targetNamespace))
9933 return(cur);
9934 }
9935 }
9936 return(NULL);
9937}
9938
9939
9940#define IS_BAD_SCHEMA_DOC(b) \
9941 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
9942
9943static xmlSchemaBucketPtr
9944xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
9945 const xmlChar *targetNamespace,
9946 int imported)
9947{
9948 xmlSchemaBucketPtr cur;
9949 xmlSchemaItemListPtr list;
9950
9951 list = pctxt->constructor->buckets;
9952 if (list->nbItems == 0)
9953 return(NULL);
9954 else {
9955 int i;
9956 for (i = 0; i < list->nbItems; i++) {
9957 cur = (xmlSchemaBucketPtr) list->items[i];
9958 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
9959 (cur->origTargetNamespace == targetNamespace) &&
9960 ((imported && cur->imported) ||
9961 ((!imported) && (!cur->imported))))
9962 return(cur);
9963 }
9964 }
9965 return(NULL);
9966}
9967
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009968static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009969xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
9970 xmlSchemaPtr schema,
9971 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009972{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009973 int oldFlags;
9974 xmlDocPtr oldDoc;
9975 xmlNodePtr node;
9976 int ret, oldErrs;
9977 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
9978
9979 /*
9980 * Save old values; reset the *main* schema.
9981 * URGENT TODO: This is not good; move the per-document information
9982 * to the parser.
9983 */
9984 oldFlags = schema->flags;
9985 oldDoc = schema->doc;
9986 if (schema->flags != 0)
9987 xmlSchemaClearSchemaDefaults(schema);
9988 schema->doc = bucket->doc;
9989 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
9990 pctxt->schema = schema;
9991 /*
9992 * Keep the current target namespace on the parser *not* on the
9993 * main schema.
9994 */
9995 pctxt->targetNamespace = bucket->targetNamespace;
9996 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009997
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009998 if ((bucket->targetNamespace != NULL) &&
9999 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010000 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010001 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010002 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010003 pctxt->isS4S = 1;
10004 }
10005 /* Mark it as parsed, even if parsing fails. */
10006 bucket->parsed++;
10007 /* Compile the schema doc. */
10008 node = xmlDocGetRootElement(bucket->doc);
10009 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10010 if (ret != 0)
10011 goto exit;
10012 /* An empty schema; just get out. */
10013 if (node->children == NULL)
10014 goto exit;
10015 oldErrs = pctxt->nberrors;
10016 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10017 if (ret != 0)
10018 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010019 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010020 * TODO: Not nice, but I'm not 100% sure we will get always an error
10021 * as a result of the obove functions; so better rely on pctxt->err
10022 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010023 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010024 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10025 ret = pctxt->err;
10026 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010027 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010028
10029exit:
10030 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10031 /* Restore schema values. */
10032 schema->doc = oldDoc;
10033 schema->flags = oldFlags;
10034 return(ret);
10035}
10036
10037static int
10038xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10039 xmlSchemaPtr schema,
10040 xmlSchemaBucketPtr bucket)
10041{
10042 xmlSchemaParserCtxtPtr newpctxt;
10043 int res = 0;
10044
10045 if (bucket == NULL)
10046 return(0);
10047 if (bucket->parsed) {
10048 PERROR_INT("xmlSchemaParseNewDoc",
10049 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010050 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010051 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010052 if (bucket->doc == NULL) {
10053 PERROR_INT("xmlSchemaParseNewDoc",
10054 "parsing a schema doc, but there's no doc");
10055 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010056 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010057 if (pctxt->constructor == NULL) {
10058 PERROR_INT("xmlSchemaParseNewDoc",
10059 "no constructor");
10060 return(-1);
10061 }
10062 /* Create and init the temporary parser context. */
10063 newpctxt = xmlSchemaNewParserCtxtUseDict(
10064 (const char *) bucket->schemaLocation, pctxt->dict);
10065 if (newpctxt == NULL)
10066 return(-1);
10067 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010068 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010069 * TODO: Can we avoid that the parser knows about the main schema?
10070 * It would be better if he knows about the current schema bucket
10071 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010072 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010073 newpctxt->schema = schema;
10074 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10075 pctxt->userData);
10076 newpctxt->counter = pctxt->counter;
10077
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010078
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010079 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10080
10081 /* Channel back errors and cleanup the temporary parser context. */
10082 if (res != 0)
10083 pctxt->err = res;
10084 pctxt->nberrors += newpctxt->nberrors;
10085 pctxt->counter = newpctxt->counter;
10086 newpctxt->constructor = NULL;
10087 /* Free the parser context. */
10088 xmlSchemaFreeParserCtxt(newpctxt);
10089 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010090}
William M. Brack2f2a6632004-08-20 23:09:47 +000010091
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010092static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010093xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10094 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010095{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010096 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010097
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010098 if (cur == NULL) {
10099 bucket->relations = rel;
10100 return;
10101 }
10102 while (cur->next != NULL)
10103 cur = cur->next;
10104 cur->next = rel;
10105}
10106
10107
10108static const xmlChar *
10109xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10110 xmlNodePtr ctxtNode)
10111{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010112 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010113 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010114 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010115 if (location != NULL) {
10116 if (ctxtNode == NULL)
10117 return(location);
10118 else {
10119 xmlChar *base, *URI;
10120 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010121
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010122 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10123 if (base == NULL) {
10124 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10125 } else {
10126 URI = xmlBuildURI(location, base);
10127 xmlFree(base);
10128 }
10129 if (URI != NULL) {
10130 ret = xmlDictLookup(dict, URI, -1);
10131 xmlFree(URI);
10132 return(ret);
10133 }
10134 }
10135 }
10136 return(NULL);
10137}
10138
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010139
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010140
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010141/**
10142 * xmlSchemaAddSchemaDoc:
10143 * @pctxt: a schema validation context
10144 * @schema: the schema being built
10145 * @node: a subtree containing XML Schema informations
10146 *
10147 * Parse an included (and to-be-redefined) XML schema document.
10148 *
10149 * Returns 0 on success, a positive error code on errors and
10150 * -1 in case of an internal or API error.
10151 */
10152
10153static int
10154xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10155 int type, /* import or include or redefine */
10156 const xmlChar *schemaLocation,
10157 xmlDocPtr schemaDoc,
10158 const char *schemaBuffer,
10159 int schemaBufferLen,
10160 xmlNodePtr invokingNode,
10161 const xmlChar *sourceTargetNamespace,
10162 const xmlChar *importNamespace,
10163 xmlSchemaBucketPtr *bucket)
10164{
10165 const xmlChar *targetNamespace = NULL;
10166 xmlSchemaSchemaRelationPtr relation = NULL;
10167 xmlDocPtr doc = NULL;
10168 int res = 0, err = 0, located = 0, preserveDoc = 0;
10169 xmlSchemaBucketPtr bkt = NULL;
10170
10171 if (bucket != NULL)
10172 *bucket = NULL;
10173
10174 switch (type) {
10175 case XML_SCHEMA_SCHEMA_IMPORT:
10176 case XML_SCHEMA_SCHEMA_MAIN:
10177 err = XML_SCHEMAP_SRC_IMPORT;
10178 break;
10179 case XML_SCHEMA_SCHEMA_INCLUDE:
10180 err = XML_SCHEMAP_SRC_INCLUDE;
10181 break;
10182 case XML_SCHEMA_SCHEMA_REDEFINE:
10183 err = XML_SCHEMAP_SRC_REDEFINE;
10184 break;
10185 }
10186
10187
10188 /* Special handling for the main schema:
10189 * skip the location and relation logic and just parse the doc.
10190 * We need just a bucket to be returned in this case.
10191 */
10192 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10193 goto doc_load;
10194
10195 /* Note that we expect the location to be an absulute URI. */
10196 if (schemaLocation != NULL) {
10197 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10198 if ((bkt != NULL) &&
10199 (pctxt->constructor->bucket == bkt)) {
10200 /* Report self-imports/inclusions/redefinitions. */
10201
10202 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10203 invokingNode, NULL,
10204 "The schema must not import/include/redefine itself",
10205 NULL, NULL);
10206 goto exit;
10207 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010208 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010209 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010210 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010211 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010212 relation = xmlSchemaSchemaRelationCreate();
10213 if (relation == NULL)
10214 return(-1);
10215 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10216 relation);
10217 relation->type = type;
10218
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010219 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010220 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010221 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010222 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010223 relation->importNamespace = importNamespace;
10224 if (schemaLocation == NULL) {
10225 /*
10226 * No location; this is just an import of the namespace.
10227 * Note that we don't assign a bucket to the relation
10228 * in this case.
10229 */
10230 goto exit;
10231 }
10232 targetNamespace = importNamespace;
10233 }
10234
10235 /* Did we already fetch the doc? */
10236 if (bkt != NULL) {
10237 /* TODO: The following nasty cases will produce an error. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010238 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010239 /* We included/redefined and then try to import a schema. */
10240 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10241 invokingNode, NULL,
10242 "The schema document '%s' cannot be imported, since "
10243 "it was already included or redefined",
10244 schemaLocation, NULL);
10245 goto exit;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010246 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010247 /* We imported and then try to include/redefine a schema. */
10248 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10249 invokingNode, NULL,
10250 "The schema document '%s' cannot be included or "
10251 "redefined, since it was already imported",
10252 schemaLocation, NULL);
10253 goto exit;
10254 }
10255 }
10256
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010257 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010258 /*
10259 * Given that the schemaLocation [attribute] is only a hint, it is open
10260 * to applications to ignore all but the first <import> for a given
10261 * namespace, regardless of the ·actual value· of schemaLocation, but
10262 * such a strategy risks missing useful information when new
10263 * schemaLocations are offered.
10264 *
10265 * We will use the first <import> that comes with a location.
10266 * Further <import>s *with* a location, will result in an error.
10267 * TODO: Better would be to just report a warning here, but
10268 * we'll try it this way until someone complains.
10269 *
10270 * Schema Document Location Strategy:
10271 * 3 Based on the namespace name, identify an existing schema document,
10272 * either as a resource which is an XML document or a <schema> element
10273 * information item, in some local schema repository;
10274 * 5 Attempt to resolve the namespace name to locate such a resource.
10275 *
10276 * NOTE: (3) and (5) are not supported.
10277 */
10278 if (bkt != NULL) {
10279 relation->bucket = bkt;
10280 goto exit;
10281 }
10282 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10283 importNamespace, 1);
10284
10285 if (bkt != NULL) {
10286 relation->bucket = bkt;
10287 if (bkt->schemaLocation == NULL) {
10288 /* First given location of the schema; load the doc. */
10289 bkt->schemaLocation = schemaLocation;
10290 } else {
10291 if (!xmlStrEqual(schemaLocation,
10292 bkt->schemaLocation)) {
10293 /*
10294 * Additional location given; just skip it.
10295 * URGENT TODO: We should report a warning here.
10296 * res = XML_SCHEMAP_SRC_IMPORT;
10297 */
10298 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10299 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10300 invokingNode, NULL,
10301 "Skipping import of schema located at '%s' for the "
10302 "namespace '%s', since this namespace was already "
10303 "imported with the schema located at '%s'",
10304 schemaLocation, importNamespace, bkt->schemaLocation);
10305 }
10306 goto exit;
10307 }
10308 }
10309 /*
10310 * No bucket + first location: load the doc and create a
10311 * bucket.
10312 */
10313 } else {
10314 /* <include> and <redefine> */
10315 if (bkt != NULL) {
10316
10317 if ((bkt->origTargetNamespace == NULL) &&
10318 (bkt->targetNamespace != sourceTargetNamespace)) {
10319 xmlSchemaBucketPtr chamel;
10320
10321 /*
10322 * Chameleon include/redefine: skip loading only if it was
10323 * aleady build for the targetNamespace of the including
10324 * schema.
10325 */
10326 /*
10327 * URGENT TODO: If the schema is a chameleon-include then copy
10328 * the components into the including schema and modify the
10329 * targetNamespace of those components, do nothing otherwise.
10330 * NOTE: This is currently worked-around by compiling the
10331 * chameleon for every destinct including targetNamespace; thus
10332 * not performant at the moment.
10333 * TODO: Check when the namespace in wildcards for chameleons
10334 * needs to be converted: before we built wildcard intersections
10335 * or after.
10336 * Answer: after!
10337 */
10338 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10339 schemaLocation, sourceTargetNamespace);
10340 if (chamel != NULL) {
10341 /* A fitting chameleon was already parsed; NOP. */
10342 relation->bucket = chamel;
10343 goto exit;
10344 }
10345 /*
10346 * We need to parse the chameleon again for a different
10347 * targetNamespace.
10348 * CHAMELEON TODO: Optimize this by only parsing the
10349 * chameleon once, and then copying the components to
10350 * the new targetNamespace.
10351 */
10352 bkt = NULL;
10353 } else {
10354 relation->bucket = bkt;
10355 goto exit;
10356 }
10357 }
10358 }
10359 if ((bkt != NULL) && (bkt->doc != NULL)) {
10360 PERROR_INT("xmlSchemaAddSchemaDoc",
10361 "trying to load a schema doc, but a doc is already "
10362 "assigned to the schema bucket");
10363 goto exit_failure;
10364 }
10365
10366doc_load:
10367 /*
10368 * Load the document.
10369 */
10370 if (schemaDoc != NULL) {
10371 doc = schemaDoc;
10372 /* Don' free this one, since it was provided by the caller. */
10373 preserveDoc = 1;
10374 /* TODO: Does the context or the doc hold the location? */
10375 if (schemaDoc->URL != NULL)
10376 schemaLocation = xmlDictLookup(pctxt->dict,
10377 schemaDoc->URL, -1);
10378
10379 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10380 xmlParserCtxtPtr parserCtxt;
10381
10382 parserCtxt = xmlNewParserCtxt();
10383 if (parserCtxt == NULL) {
10384 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10385 "allocating a parser context", NULL);
10386 goto exit_failure;
10387 }
10388 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10389 /*
10390 * TODO: Do we have to burden the schema parser dict with all
10391 * the content of the schema doc?
10392 */
10393 xmlDictFree(parserCtxt->dict);
10394 parserCtxt->dict = pctxt->dict;
10395 xmlDictReference(parserCtxt->dict);
10396 }
10397 if (schemaLocation != NULL) {
10398 /* Parse from file. */
10399 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10400 NULL, SCHEMAS_PARSE_OPTIONS);
10401 } else if (schemaBuffer != NULL) {
10402 /* Parse from memory buffer. */
10403 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10404 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10405 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10406 if (doc != NULL)
10407 doc->URL = schemaLocation;
10408 }
10409 /*
10410 * For <import>:
10411 * 2.1 The referent is (a fragment of) a resource which is an
10412 * XML document (see clause 1.1), which in turn corresponds to
10413 * a <schema> element information item in a well-formed information
10414 * set, which in turn corresponds to a valid schema.
10415 * TODO: (2.1) fragments of XML documents are not supported.
10416 *
10417 * 2.2 The referent is a <schema> element information item in
10418 * a well-formed information set, which in turn corresponds
10419 * to a valid schema.
10420 * TODO: (2.2) is not supported.
10421 */
10422 if (doc == NULL) {
10423 xmlErrorPtr lerr;
10424 lerr = xmlGetLastError();
10425 /*
10426 * Check if this a parser error, or if the document could
10427 * just not be located.
10428 * TODO: Try to find specific error codes to react only on
10429 * localisation failures.
10430 */
10431 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10432 /*
10433 * We assume a parser error here.
10434 */
10435 located = 1;
10436 /* TODO: Error code ?? */
10437 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10438 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10439 invokingNode, NULL,
10440 "Failed to parse the XML resource '%s'",
10441 schemaLocation, NULL);
10442 }
10443 }
10444 xmlFreeParserCtxt(parserCtxt);
10445 if ((doc == NULL) && located)
10446 goto exit_error;
10447 } else {
10448 xmlSchemaPErr(pctxt, NULL,
10449 XML_SCHEMAP_NOTHING_TO_PARSE,
10450 "No information for parsing was provided with the "
10451 "given schema parser context.\n",
10452 NULL, NULL);
10453 goto exit_failure;
10454 }
10455 /*
10456 * Preprocess the document.
10457 */
10458 if (doc != NULL) {
10459 xmlNodePtr docElem = NULL;
10460
10461 located = 1;
10462 docElem = xmlDocGetRootElement(doc);
10463 if (docElem == NULL) {
10464 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10465 invokingNode, NULL,
10466 "The document '%s' has no document element",
10467 schemaLocation, NULL);
10468 xmlFreeDoc(doc);
10469 doc = NULL;
10470 goto exit_error;
10471 }
10472 /*
10473 * Remove all the blank text nodes.
10474 */
10475 xmlSchemaCleanupDoc(pctxt, docElem);
10476 /*
10477 * Check the schema's top level element.
10478 */
10479 if (!IS_SCHEMA(docElem, "schema")) {
10480 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10481 invokingNode, NULL,
10482 "The XML document '%s' is not a schema document",
10483 schemaLocation, NULL);
10484 xmlFreeDoc(doc);
10485 doc = NULL;
10486 goto exit_error;
10487 }
10488 /*
10489 * Note that we don't apply a type check for the
10490 * targetNamespace value here.
10491 */
10492 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10493 "targetNamespace");
10494 }
10495
10496/* after_doc_loading: */
10497 if ((bkt == NULL) && located) {
10498 /* Only create a bucket if the schema was located. */
10499 bkt = xmlSchemaBucketCreate(pctxt, type,
10500 targetNamespace);
10501 if (bkt == NULL)
10502 goto exit_failure;
10503 }
10504 if (bkt != NULL) {
10505 bkt->schemaLocation = schemaLocation;
10506 bkt->located = located;
10507 if (doc != NULL) {
10508 bkt->doc = doc;
10509 bkt->targetNamespace = targetNamespace;
10510 bkt->origTargetNamespace = targetNamespace;
10511 if (preserveDoc)
10512 bkt->preserveDoc = 1;
10513 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010514 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010515 bkt->imported++;
10516 /*
10517 * Add it to the graph of schemas.
10518 */
10519 if (relation != NULL)
10520 relation->bucket = bkt;
10521 }
10522
10523exit:
10524 /*
10525 * Return the bucket explicitely; this is needed for the
10526 * main schema.
10527 */
10528 if (bucket != NULL)
10529 *bucket = bkt;
10530 return (0);
10531
10532exit_error:
10533 if ((doc != NULL) && (! preserveDoc)) {
10534 xmlFreeDoc(doc);
10535 if (bkt != NULL)
10536 bkt->doc = NULL;
10537 }
10538 return(pctxt->err);
10539
10540exit_failure:
10541 if ((doc != NULL) && (! preserveDoc)) {
10542 xmlFreeDoc(doc);
10543 if (bkt != NULL)
10544 bkt->doc = NULL;
10545 }
10546 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010547}
10548
William M. Brack2f2a6632004-08-20 23:09:47 +000010549/**
10550 * xmlSchemaParseImport:
10551 * @ctxt: a schema validation context
10552 * @schema: the schema being built
10553 * @node: a subtree containing XML Schema informations
10554 *
10555 * parse a XML schema Import definition
10556 * *WARNING* this interface is highly subject to change
10557 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010558 * Returns 0 in case of success, a positive error code if
10559 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010560 */
10561static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010562xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010563 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010564{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010565 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010566 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10567 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010568 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010569 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010570 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010571
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010572 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010573 return (-1);
10574
10575 /*
10576 * Check for illegal attributes.
10577 */
10578 attr = node->properties;
10579 while (attr != NULL) {
10580 if (attr->ns == NULL) {
10581 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10582 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10583 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010584 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010585 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010586 }
10587 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010588 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010590 }
10591 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010592 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010593 /*
10594 * Extract and validate attributes.
10595 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010596 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010597 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010598 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010599 xmlSchemaPSimpleTypeErr(pctxt,
10600 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010601 NULL, node,
10602 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010603 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010604 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010605 }
10606
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010607 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010608 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010609 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010610 xmlSchemaPSimpleTypeErr(pctxt,
10611 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010612 NULL, node,
10613 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010614 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010615 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010616 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010617 /*
10618 * And now for the children...
10619 */
10620 child = node->children;
10621 if (IS_SCHEMA(child, "annotation")) {
10622 /*
10623 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010624 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010625 */
10626 child = child->next;
10627 }
10628 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010629 xmlSchemaPContentErr(pctxt,
10630 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010631 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010632 "(annotation?)");
10633 }
10634 /*
10635 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010636 *
10637 * Note that it is important to use the original @targetNamespace
10638 * (or none at all), to rule out imports of schemas _with_ a
10639 * @targetNamespace if the importing schema is a chameleon schema
10640 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010641 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010642 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010643 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010644 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010645 * 1.1 If the namespace [attribute] is present, then its ·actual value·
10646 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010647 * targetNamespace [attribute].
10648 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010649 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010650 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010651 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010652 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010653 "The value of the attribute 'namespace' must not match "
10654 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010655 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010656 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010657 }
10658 } else {
10659 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010660 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010661 * <schema> must have a targetNamespace [attribute].
10662 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010663 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010664 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010665 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010666 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010667 "The attribute 'namespace' must be existent if "
10668 "the importing schema has no target namespace",
10669 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010670 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010671 }
10672 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010673 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010674 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010675 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010676 if (schemaLocation != NULL)
10677 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10678 schemaLocation, node);
10679 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010680 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010681 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010682
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010683 if (ret != 0)
10684 return(ret);
10685
10686 /*
10687 * For <import>: "It is *not* an error for the application
10688 * schema reference strategy to fail."
10689 * So just don't parse if no schema document was found.
10690 * Note that we will get no bucket if the schema could not be
10691 * located or if there was no schemaLocation.
10692 */
10693 if ((bucket == NULL) && (schemaLocation != NULL)) {
10694 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10695 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10696 node, NULL,
10697 "Failed to locate a schema at location '%s'. "
10698 "Skipping the import", schemaLocation, NULL, NULL);
10699 }
10700
10701 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10702 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10703 }
10704
10705 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010706}
10707
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010708static int
10709xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10710 xmlSchemaPtr schema,
10711 xmlNodePtr node,
10712 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010713 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010714{
10715 xmlAttrPtr attr;
10716
10717 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10718 (schemaLocation == NULL))
10719 return (-1);
10720
10721 *schemaLocation = NULL;
10722 /*
10723 * Check for illegal attributes.
10724 * Applies for both <include> and <redefine>.
10725 */
10726 attr = node->properties;
10727 while (attr != NULL) {
10728 if (attr->ns == NULL) {
10729 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10730 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10731 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010732 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010733 }
10734 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10735 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010736 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010737 }
10738 attr = attr->next;
10739 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010740 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010741 /*
10742 * Preliminary step, extract the URI-Reference and make an URI
10743 * from the base.
10744 */
10745 /*
10746 * Attribute "schemaLocation" is mandatory.
10747 */
10748 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10749 if (attr != NULL) {
10750 xmlChar *base = NULL;
10751 xmlChar *uri = NULL;
10752
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010753 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010754 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10755 (const xmlChar **) schemaLocation) != 0)
10756 goto exit_error;
10757 base = xmlNodeGetBase(node->doc, node);
10758 if (base == NULL) {
10759 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10760 } else {
10761 uri = xmlBuildURI(*schemaLocation, base);
10762 xmlFree(base);
10763 }
10764 if (uri == NULL) {
10765 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10766 "could not build an URI from the schemaLocation")
10767 goto exit_failure;
10768 }
10769 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10770 xmlFree(uri);
10771 } else {
10772 xmlSchemaPMissingAttrErr(pctxt,
10773 XML_SCHEMAP_S4S_ATTR_MISSING,
10774 NULL, node, "schemaLocation", NULL);
10775 goto exit_error;
10776 }
10777 /*
10778 * Report self-inclusion and self-redefinition.
10779 */
10780 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010781 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010782 xmlSchemaPCustomErr(pctxt,
10783 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010784 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010785 "The schema document '%s' cannot redefine itself.",
10786 *schemaLocation);
10787 } else {
10788 xmlSchemaPCustomErr(pctxt,
10789 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010790 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010791 "The schema document '%s' cannot include itself.",
10792 *schemaLocation);
10793 }
10794 goto exit_error;
10795 }
10796
10797 return(0);
10798exit_error:
10799 return(pctxt->err);
10800exit_failure:
10801 return(-1);
10802}
10803
10804static int
10805xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10806 xmlSchemaPtr schema,
10807 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010808 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010809{
10810 xmlNodePtr child = NULL;
10811 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010812 int res = 0, /* docRes = 0, located = 0, */ hasRedefinitions = 0;
10813 int isChameleon = 0, wasChameleon = 0;
10814 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010815
10816 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10817 return (-1);
10818
10819 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010820 * Parse attributes. Note that the returned schemaLocation will
10821 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010822 */
10823 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010824 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010825 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010826 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010827 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010828 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010829 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010830 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10831 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010832 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010833 return(res);
10834 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010835 * If we get no schema bucket back, then this means that the schema
10836 * document could not be located or was broken XML or was not
10837 * a schema document.
10838 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010839 if ((bucket == NULL) || (bucket->doc == NULL)) {
10840 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10841 /*
10842 * WARNING for <include>:
10843 * We will raise an error if the schema cannot be located
10844 * for inclusions, since the that was the feedback from the
10845 * schema people. I.e. the following spec piece will *not* be
10846 * satisfied:
10847 * SPEC src-include: "It is not an error for the ·actual value· of the
10848 * schemaLocation [attribute] to fail to resolve it all, in which
10849 * case no corresponding inclusion is performed.
10850 * So do we need a warning report here?"
10851 */
10852 res = XML_SCHEMAP_SRC_INCLUDE;
10853 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10854 node, NULL,
10855 "Failed to load the document '%s' for inclusion",
10856 schemaLocation, NULL);
10857 } else {
10858 /*
10859 * NOTE: This was changed to raise an error even if no redefinitions
10860 * are specified.
10861 *
10862 * SPEC src-redefine (1)
10863 * "If there are any element information items among the [children]
10864 * other than <annotation> then the ·actual value· of the
10865 * schemaLocation [attribute] must successfully resolve."
10866 * TODO: Ask the WG if a the location has always to resolve
10867 * here as well!
10868 */
10869 res = XML_SCHEMAP_SRC_REDEFINE;
10870 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10871 node, NULL,
10872 "Failed to load the document '%s' for redefinition",
10873 schemaLocation, NULL);
10874 }
10875 } else {
10876 /*
10877 * Check targetNamespace sanity before parsing the new schema.
10878 * TODO: Note that we won't check further content if the
10879 * targetNamespace was bad.
10880 */
10881 if (bucket->origTargetNamespace != NULL) {
10882 /*
10883 * SPEC src-include (2.1)
10884 * "SII has a targetNamespace [attribute], and its ·actual
10885 * value· is identical to the ·actual value· of the targetNamespace
10886 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10887 */
10888 if (pctxt->targetNamespace == NULL) {
10889 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10890 XML_SCHEMAP_SRC_INCLUDE,
10891 node, NULL,
10892 "The target namespace of the included/redefined schema "
10893 "'%s' has to be absent, since the including/redefining "
10894 "schema has no target namespace",
10895 schemaLocation, NULL);
10896 goto exit_error;
10897 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10898 pctxt->targetNamespace)) {
10899 /* TODO: Change error function. */
10900 xmlSchemaPCustomErrExt(pctxt,
10901 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010902 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010903 "The target namespace '%s' of the included/redefined "
10904 "schema '%s' differs from '%s' of the "
10905 "including/redefining schema",
10906 bucket->origTargetNamespace, schemaLocation,
10907 pctxt->targetNamespace);
10908 goto exit_error;
10909 }
10910 } else if (pctxt->targetNamespace != NULL) {
10911 /*
10912 * Chameleons: the original target namespace will
10913 * differ from the resulting namespace.
10914 */
10915 isChameleon = 1;
10916 if (bucket->parsed &&
10917 (bucket->targetNamespace != pctxt->targetNamespace)) {
10918 /*
10919 * This is a sanity check, I dunno yet if this can happen.
10920 */
10921 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10922 "trying to use an already parsed schema for a "
10923 "different targetNamespace");
10924 return(-1);
10925 }
10926 bucket->targetNamespace = pctxt->targetNamespace;
10927 }
10928 }
10929 /*
10930 * Parse the schema.
10931 */
10932 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
10933 if (isChameleon) {
10934 /* TODO: Get rid of this flag on the schema itself. */
10935 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
10936 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
10937 } else
10938 wasChameleon = 1;
10939 }
10940 xmlSchemaParseNewDoc(pctxt, schema, bucket);
10941 /* Restore chameleon flag. */
10942 if (isChameleon && (!wasChameleon))
10943 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
10944 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010945 /*
10946 * And now for the children...
10947 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010948 child = node->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010949 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010950 /*
10951 * Parse (simpleType | complexType | group | attributeGroup))*
10952 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010953 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010954 /*
10955 * How to proceed if the redefined schema was not located?
10956 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010957 pctxt->isRedefine = 1;
10958 while (IS_SCHEMA(child, "annotation") ||
10959 IS_SCHEMA(child, "simpleType") ||
10960 IS_SCHEMA(child, "complexType") ||
10961 IS_SCHEMA(child, "group") ||
10962 IS_SCHEMA(child, "attributeGroup")) {
10963 if (IS_SCHEMA(child, "annotation")) {
10964 /*
10965 * TODO: discard or not?
10966 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010967 } else if (IS_SCHEMA(child, "simpleType")) {
10968 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
10969 } else if (IS_SCHEMA(child, "complexType")) {
10970 xmlSchemaParseComplexType(pctxt, schema, child, 1);
10971 hasRedefinitions = 1;
10972 } else if (IS_SCHEMA(child, "group")) {
10973 hasRedefinitions = 1;
10974 xmlSchemaParseModelGroupDefinition(pctxt,
10975 schema, child);
10976 } else if (IS_SCHEMA(child, "attributeGroup")) {
10977 hasRedefinitions = 1;
10978 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
10979 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010980 }
10981 child = child->next;
10982 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010983 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010984 pctxt->isRedefine = 0;
10985 } else {
10986 if (IS_SCHEMA(child, "annotation")) {
10987 /*
10988 * TODO: discard or not?
10989 */
10990 child = child->next;
10991 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010992 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010993 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010994 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010995 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10996 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010997 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010998 "(annotation | (simpleType | complexType | group | attributeGroup))*");
10999 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011000 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011001 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011002 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011003 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011004 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011005 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011006
11007exit_error:
11008 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011009}
11010
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011011static int
11012xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11013 xmlNodePtr node)
11014{
11015 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011016#ifndef ENABLE_REDEFINE
11017 TODO
11018 return(0);
11019#endif
11020 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11021 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011022 if (res != 0)
11023 return(res);
11024 return(0);
11025}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011026
11027static int
11028xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11029 xmlNodePtr node)
11030{
11031 int res;
11032
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011033 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11034 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011035 if (res != 0)
11036 return(res);
11037 return(0);
11038}
11039
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011040/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011042 * @ctxt: a schema validation context
11043 * @schema: the schema being built
11044 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011045 * @type: the "compositor" type
11046 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011047 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011048 * parse a XML schema Sequence definition.
11049 * Applies parts of:
11050 * Schema Representation Constraint:
11051 * Redefinition Constraints and Semantics (src-redefine)
11052 * (6.1), (6.1.1), (6.1.2)
11053 *
11054 * Schema Component Constraint:
11055 * All Group Limited (cos-all-limited) (2)
11056 * TODO: Actually this should go to component-level checks,
11057 * but is done here due to performance. Move it to an other layer
11058 * is schema construction via an API is implemented.
11059 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011060 * *WARNING* this interface is highly subject to change
11061 *
William M. Bracke7091952004-05-11 15:09:58 +000011062 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011063 * 1 in case of success.
11064 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011065static xmlSchemaTreeItemPtr
11066xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11067 xmlNodePtr node, xmlSchemaTypeType type,
11068 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011069{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011070 xmlSchemaModelGroupPtr item;
11071 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011072 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011073 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011074 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011075
11076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011077 return (NULL);
11078 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011079 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011080 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011081 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011082 if (item == NULL)
11083 return (NULL);
11084
11085 if (withParticle) {
11086 if (type == XML_SCHEMA_TYPE_ALL) {
11087 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011088 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011089 } else {
11090 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011091 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11092 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11093 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011094 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011095 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11096 /*
11097 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011098 */
11099 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
11100 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011101 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011102 particle->children = (xmlSchemaTreeItemPtr) item;
11103 /*
11104 * Check for illegal attributes.
11105 */
11106 attr = node->properties;
11107 while (attr != NULL) {
11108 if (attr->ns == NULL) {
11109 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11110 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11111 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011112 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011114 }
11115 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011116 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011118 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011120 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011121 } else {
11122 /*
11123 * Check for illegal attributes.
11124 */
11125 attr = node->properties;
11126 while (attr != NULL) {
11127 if (attr->ns == NULL) {
11128 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011129 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011131 }
11132 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011133 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011134 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011135 }
11136 attr = attr->next;
11137 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011138 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011139
William M. Brack2f2a6632004-08-20 23:09:47 +000011140 /*
11141 * Extract and validate attributes.
11142 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011143 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011144 /*
11145 * And now for the children...
11146 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011147 child = node->children;
11148 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011149 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011150 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011151 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 if (type == XML_SCHEMA_TYPE_ALL) {
11153 xmlSchemaParticlePtr part, last = NULL;
11154
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011155 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011157 schema, child, &isElemRef, 0);
11158 /*
11159 * SPEC cos-all-limited (2)
11160 * "The {max occurs} of all the particles in the {particles}
11161 * of the ('all') group must be 0 or 1.
11162 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011163 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011164 if (isElemRef)
11165 hasRefs++;
11166 if (part->minOccurs > 1) {
11167 xmlSchemaPCustomErr(ctxt,
11168 XML_SCHEMAP_COS_ALL_LIMITED,
11169 NULL, child,
11170 "Invalid value for minOccurs (must be 0 or 1)",
11171 NULL);
11172 /* Reset to 1. */
11173 part->minOccurs = 1;
11174 }
11175 if (part->maxOccurs > 1) {
11176 xmlSchemaPCustomErr(ctxt,
11177 XML_SCHEMAP_COS_ALL_LIMITED,
11178 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 "Invalid value for maxOccurs (must be 0 or 1)",
11180 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011181 /* Reset to 1. */
11182 part->maxOccurs = 1;
11183 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011184 if (last == NULL)
11185 item->children = (xmlSchemaTreeItemPtr) part;
11186 else
11187 last->next = (xmlSchemaTreeItemPtr) part;
11188 last = part;
11189 }
11190 child = child->next;
11191 }
11192 if (child != NULL) {
11193 xmlSchemaPContentErr(ctxt,
11194 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011195 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 "(annotation?, (annotation?, element*)");
11197 }
11198 } else {
11199 /* choice + sequence */
11200 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11201
11202 while ((IS_SCHEMA(child, "element")) ||
11203 (IS_SCHEMA(child, "group")) ||
11204 (IS_SCHEMA(child, "any")) ||
11205 (IS_SCHEMA(child, "choice")) ||
11206 (IS_SCHEMA(child, "sequence"))) {
11207
11208 if (IS_SCHEMA(child, "element")) {
11209 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011210 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11211 if (part && isElemRef)
11212 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011214 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011216 if (part != NULL)
11217 hasRefs++;
11218 /*
11219 * Handle redefinitions.
11220 */
11221 if (ctxt->isRedefine && ctxt->redef &&
11222 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11223 part && part->children)
11224 {
11225 if ((xmlSchemaGetQNameRefName(part->children) ==
11226 ctxt->redef->refName) &&
11227 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11228 ctxt->redef->refTargetNs))
11229 {
11230 /*
11231 * SPEC src-redefine:
11232 * (6.1) "If it has a <group> among its contents at
11233 * some level the ·actual value· of whose ref
11234 * [attribute] is the same as the ·actual value· of
11235 * its own name attribute plus target namespace, then
11236 * all of the following must be true:"
11237 * (6.1.1) "It must have exactly one such group."
11238 */
11239 if (ctxt->redefCounter != 0) {
11240 xmlChar *str = NULL;
11241
11242 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11243 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11244 "The redefining model group definition "
11245 "'%s' must not contain more than one "
11246 "reference to the redefined definition",
11247 xmlSchemaFormatQName(&str,
11248 ctxt->redef->refTargetNs,
11249 ctxt->redef->refName),
11250 NULL);
11251 FREE_AND_NULL(str)
11252 part = NULL;
11253 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11254 ((WXS_PARTICLE(part))->maxOccurs != 1))
11255 {
11256 xmlChar *str = NULL;
11257 /*
11258 * SPEC src-redefine:
11259 * (6.1.2) "The ·actual value· of both that
11260 * group's minOccurs and maxOccurs [attribute]
11261 * must be 1 (or ·absent·).
11262 */
11263 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11264 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11265 "The redefining model group definition "
11266 "'%s' must not contain a reference to the "
11267 "redefined definition with a "
11268 "maxOccurs/minOccurs other than 1",
11269 xmlSchemaFormatQName(&str,
11270 ctxt->redef->refTargetNs,
11271 ctxt->redef->refName),
11272 NULL);
11273 FREE_AND_NULL(str)
11274 part = NULL;
11275 }
11276 ctxt->redef->reference = WXS_BASIC_CAST part;
11277 ctxt->redefCounter++;
11278 }
11279 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011280 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011281 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 xmlSchemaParseAny(ctxt, schema, child);
11283 } else if (IS_SCHEMA(child, "choice")) {
11284 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11285 XML_SCHEMA_TYPE_CHOICE, 1);
11286 } else if (IS_SCHEMA(child, "sequence")) {
11287 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11288 XML_SCHEMA_TYPE_SEQUENCE, 1);
11289 }
11290 if (part != NULL) {
11291 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011292 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 else
11294 last->next = part;
11295 last = part;
11296 }
11297 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011298 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 if (child != NULL) {
11300 xmlSchemaPContentErr(ctxt,
11301 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011302 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011303 "(annotation?, (element | group | choice | sequence | any)*)");
11304 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011305 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011306 if ((max == 0) && (min == 0))
11307 return (NULL);
11308 if (hasRefs) {
11309 /*
11310 * We need to resolve references.
11311 */
11312 WXS_ADD_PENDING(ctxt, item);
11313 }
11314 if (withParticle)
11315 return ((xmlSchemaTreeItemPtr) particle);
11316 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011318}
11319
11320/**
11321 * xmlSchemaParseRestriction:
11322 * @ctxt: a schema validation context
11323 * @schema: the schema being built
11324 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011325 *
11326 * parse a XML schema Restriction definition
11327 * *WARNING* this interface is highly subject to change
11328 *
11329 * Returns the type definition or NULL in case of error
11330 */
11331static xmlSchemaTypePtr
11332xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011334{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011336 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011337 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011338
11339 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11340 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011341 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 type = ctxt->ctxtType;
11343 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011344
11345 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011346 * Check for illegal attributes.
11347 */
11348 attr = node->properties;
11349 while (attr != NULL) {
11350 if (attr->ns == NULL) {
11351 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11352 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011353 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011355 }
11356 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011357 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011358 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011359 }
11360 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011361 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011362 /*
11363 * Extract and validate attributes.
11364 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011365 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011366 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011367 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011368 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011369 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011370 * Extract the base type. The "base" attribute is mandatory if inside
11371 * a complex type or if redefining.
11372 *
11373 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011374 * among its [children]), the simple type definition which is
11375 * the {content type} of the type definition ·resolved· to by
11376 * the ·actual value· of the base [attribute]"
11377 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011378 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011379 &(type->baseNs), &(type->base)) == 0)
11380 {
11381 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11382 xmlSchemaPMissingAttrErr(ctxt,
11383 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011384 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011385 } else if ((ctxt->isRedefine) &&
11386 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11387 {
11388 if (type->base == NULL) {
11389 xmlSchemaPMissingAttrErr(ctxt,
11390 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011391 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011392 } else if ((! xmlStrEqual(type->base, type->name)) ||
11393 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11394 {
11395 xmlChar *str1 = NULL, *str2 = NULL;
11396 /*
11397 * REDEFINE: SPEC src-redefine (5)
11398 * "Within the [children], each <simpleType> must have a
11399 * <restriction> among its [children] ... the ·actual value· of
11400 * whose base [attribute] must be the same as the ·actual value·
11401 * of its own name attribute plus target namespace;"
11402 */
11403 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011404 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011405 "value '%s' of the 'base' attribute does not match the "
11406 "type's designation '%s'",
11407 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11408 xmlSchemaFormatQName(&str1, type->targetNamespace,
11409 type->name), NULL);
11410 FREE_AND_NULL(str1);
11411 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011412 /* Avoid confusion and erase the values. */
11413 type->base = NULL;
11414 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011415 }
11416 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011417 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011418 /*
11419 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011420 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011421 child = node->children;
11422 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011423 /*
11424 * Add the annotation to the simple type ancestor.
11425 */
11426 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011427 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011428 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011429 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011430 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11431 /*
11432 * Corresponds to <simpleType><restriction><simpleType>.
11433 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011434 if (IS_SCHEMA(child, "simpleType")) {
11435 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 * Either the base [attribute] or the simpleType [child] of the
11439 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011440 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011441 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011442 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011443 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011444 "The attribute 'base' and the <simpleType> child are "
11445 "mutually exclusive", NULL);
11446 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011447 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011448 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011450 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011451 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011453 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011454 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011455 "Either the attribute 'base' or a <simpleType> child "
11456 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011457 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011458 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11459 /*
11460 * Corresponds to <complexType><complexContent><restriction>...
11461 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011462 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 * Model groups <all>, <choice> and <sequence>.
11464 */
11465 if (IS_SCHEMA(child, "all")) {
11466 type->subtypes = (xmlSchemaTypePtr)
11467 xmlSchemaParseModelGroup(ctxt, schema, child,
11468 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011469 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011470 } else if (IS_SCHEMA(child, "choice")) {
11471 type->subtypes = (xmlSchemaTypePtr)
11472 xmlSchemaParseModelGroup(ctxt,
11473 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11474 child = child->next;
11475 } else if (IS_SCHEMA(child, "sequence")) {
11476 type->subtypes = (xmlSchemaTypePtr)
11477 xmlSchemaParseModelGroup(ctxt, schema, child,
11478 XML_SCHEMA_TYPE_SEQUENCE, 1);
11479 child = child->next;
11480 /*
11481 * Model group reference <group>.
11482 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011483 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011484 type->subtypes = (xmlSchemaTypePtr)
11485 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011486 /*
11487 * Note that the reference will be resolved in
11488 * xmlSchemaResolveTypeReferences();
11489 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011490 child = child->next;
11491 }
11492 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011493 /*
11494 * Corresponds to <complexType><simpleContent><restriction>...
11495 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011496 * "1.1 the simple type definition corresponding to the <simpleType>
11497 * among the [children] of <restriction> if there is one;"
11498 */
11499 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011500 /*
11501 * We will store the to-be-restricted simple type in
11502 * type->contentTypeDef *temporarily*.
11503 */
11504 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011505 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011506 if ( type->contentTypeDef == NULL)
11507 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011508 child = child->next;
11509 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511
11512 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011514 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011515 /*
11516 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011517 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011518 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011519
Daniel Veillard01fa6152004-06-29 17:04:39 +000011520 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011521 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011522 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011523 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11525 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011526 * *Single Facet Value*
11527 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011528 while ((IS_SCHEMA(child, "minInclusive")) ||
11529 (IS_SCHEMA(child, "minExclusive")) ||
11530 (IS_SCHEMA(child, "maxInclusive")) ||
11531 (IS_SCHEMA(child, "maxExclusive")) ||
11532 (IS_SCHEMA(child, "totalDigits")) ||
11533 (IS_SCHEMA(child, "fractionDigits")) ||
11534 (IS_SCHEMA(child, "pattern")) ||
11535 (IS_SCHEMA(child, "enumeration")) ||
11536 (IS_SCHEMA(child, "whiteSpace")) ||
11537 (IS_SCHEMA(child, "length")) ||
11538 (IS_SCHEMA(child, "maxLength")) ||
11539 (IS_SCHEMA(child, "minLength"))) {
11540 facet = xmlSchemaParseFacet(ctxt, schema, child);
11541 if (facet != NULL) {
11542 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011543 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 else
11545 lastfacet->next = facet;
11546 lastfacet = facet;
11547 lastfacet->next = NULL;
11548 }
11549 child = child->next;
11550 }
11551 /*
11552 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011553 */
11554 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011555 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11556
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 facet = type->facets;
11558 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011559 facetLink = (xmlSchemaFacetLinkPtr)
11560 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011561 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011562 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011563 xmlFree(facetLink);
11564 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011565 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011566 facetLink->facet = facet;
11567 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011568 if (lastFacetLink == NULL)
11569 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011570 else
11571 lastFacetLink->next = facetLink;
11572 lastFacetLink = facetLink;
11573 facet = facet->next;
11574 } while (facet != NULL);
11575 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011577 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11578 /*
11579 * Attribute uses/declarations.
11580 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011581 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11582 (xmlSchemaItemListPtr *) &(type->attrUses),
11583 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11584 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011585 /*
11586 * Attribute wildcard.
11587 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011588 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 type->attributeWildcard =
11590 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011591 child = child->next;
11592 }
11593 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011594 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11596 xmlSchemaPContentErr(ctxt,
11597 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011598 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011599 "annotation?, (group | all | choice | sequence)?, "
11600 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011601 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011602 xmlSchemaPContentErr(ctxt,
11603 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011604 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011605 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11606 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11607 "length | minLength | maxLength | enumeration | whiteSpace | "
11608 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11609 } else {
11610 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011611 xmlSchemaPContentErr(ctxt,
11612 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011613 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011614 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11615 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11616 "length | minLength | maxLength | enumeration | whiteSpace | "
11617 "pattern)*))");
11618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011619 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011621}
11622
11623/**
11624 * xmlSchemaParseExtension:
11625 * @ctxt: a schema validation context
11626 * @schema: the schema being built
11627 * @node: a subtree containing XML Schema informations
11628 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011629 * Parses an <extension>, which is found inside a
11630 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011631 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011632 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011633 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011634 */
11635static xmlSchemaTypePtr
11636xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011637 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011638{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011639 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011640 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011641 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011642
11643 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11644 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011645 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011646 type = ctxt->ctxtType;
11647 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011648
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011649 /*
11650 * Check for illegal attributes.
11651 */
11652 attr = node->properties;
11653 while (attr != NULL) {
11654 if (attr->ns == NULL) {
11655 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11656 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011657 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011658 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011659 }
11660 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011661 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011662 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011663 }
11664 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011665 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011666
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011667 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011668
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011669 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011670 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011671 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011672 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11673 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011674 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011675 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011676 XML_SCHEMAP_S4S_ATTR_MISSING,
11677 NULL, node, "base", NULL);
11678 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011679 /*
11680 * And now for the children...
11681 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011682 child = node->children;
11683 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011684 /*
11685 * Add the annotation to the type ancestor.
11686 */
11687 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011688 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011689 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011690 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011691 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11692 /*
11693 * Corresponds to <complexType><complexContent><extension>... and:
11694 *
11695 * Model groups <all>, <choice>, <sequence> and <group>.
11696 */
11697 if (IS_SCHEMA(child, "all")) {
11698 type->subtypes = (xmlSchemaTypePtr)
11699 xmlSchemaParseModelGroup(ctxt, schema,
11700 child, XML_SCHEMA_TYPE_ALL, 1);
11701 child = child->next;
11702 } else if (IS_SCHEMA(child, "choice")) {
11703 type->subtypes = (xmlSchemaTypePtr)
11704 xmlSchemaParseModelGroup(ctxt, schema,
11705 child, XML_SCHEMA_TYPE_CHOICE, 1);
11706 child = child->next;
11707 } else if (IS_SCHEMA(child, "sequence")) {
11708 type->subtypes = (xmlSchemaTypePtr)
11709 xmlSchemaParseModelGroup(ctxt, schema,
11710 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11711 child = child->next;
11712 } else if (IS_SCHEMA(child, "group")) {
11713 type->subtypes = (xmlSchemaTypePtr)
11714 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011715 /*
11716 * Note that the reference will be resolved in
11717 * xmlSchemaResolveTypeReferences();
11718 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011719 child = child->next;
11720 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011721 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011722 if (child != NULL) {
11723 /*
11724 * Attribute uses/declarations.
11725 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011726 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11727 (xmlSchemaItemListPtr *) &(type->attrUses),
11728 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11729 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011730 /*
11731 * Attribute wildcard.
11732 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011733 if (IS_SCHEMA(child, "anyAttribute")) {
11734 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011735 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11736 child = child->next;
11737 }
11738 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011739 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011740 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11741 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 xmlSchemaPContentErr(ctxt,
11743 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011744 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011746 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011747 } else {
11748 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 xmlSchemaPContentErr(ctxt,
11750 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011751 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011752 "(annotation?, ((attribute | attributeGroup)*, "
11753 "anyAttribute?))");
11754 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011755 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011756 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011757}
11758
11759/**
11760 * xmlSchemaParseSimpleContent:
11761 * @ctxt: a schema validation context
11762 * @schema: the schema being built
11763 * @node: a subtree containing XML Schema informations
11764 *
11765 * parse a XML schema SimpleContent definition
11766 * *WARNING* this interface is highly subject to change
11767 *
11768 * Returns the type definition or NULL in case of error
11769 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011770static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011771xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011772 xmlSchemaPtr schema, xmlNodePtr node,
11773 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011774{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011775 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011776 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011777 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011778
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011779 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11780 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011781 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011782 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011783 /* Not a component, don't create it. */
11784 type = ctxt->ctxtType;
11785 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11786 /*
11787 * Check for illegal attributes.
11788 */
11789 attr = node->properties;
11790 while (attr != NULL) {
11791 if (attr->ns == NULL) {
11792 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011793 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011794 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011795 }
11796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011797 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011799 }
11800 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011801 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011802
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011803 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011804
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011805 /*
11806 * And now for the children...
11807 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011808 child = node->children;
11809 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011810 /*
11811 * Add the annotation to the complex type ancestor.
11812 */
11813 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011814 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011815 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011816 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011817 if (child == NULL) {
11818 xmlSchemaPContentErr(ctxt,
11819 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011820 NULL, node, NULL, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011821 "(annotation?, (restriction | extension))");
11822 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011823 if (child == NULL) {
11824 xmlSchemaPContentErr(ctxt,
11825 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011826 NULL, node, NULL, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011827 "(annotation?, (restriction | extension))");
11828 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011829 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011830 xmlSchemaParseRestriction(ctxt, schema, child,
11831 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011832 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011833 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011834 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011835 xmlSchemaParseExtension(ctxt, schema, child,
11836 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011837 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011838 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011839 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011840 if (child != NULL) {
11841 xmlSchemaPContentErr(ctxt,
11842 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011843 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011844 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011845 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011846 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011847}
11848
11849/**
11850 * xmlSchemaParseComplexContent:
11851 * @ctxt: a schema validation context
11852 * @schema: the schema being built
11853 * @node: a subtree containing XML Schema informations
11854 *
11855 * parse a XML schema ComplexContent definition
11856 * *WARNING* this interface is highly subject to change
11857 *
11858 * Returns the type definition or NULL in case of error
11859 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011860static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011861xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011862 xmlSchemaPtr schema, xmlNodePtr node,
11863 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011864{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011865 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011866 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011867 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011868
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011869 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11870 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011871 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011872 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011873 /* Not a component, don't create it. */
11874 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011875 /*
11876 * Check for illegal attributes.
11877 */
11878 attr = node->properties;
11879 while (attr != NULL) {
11880 if (attr->ns == NULL) {
11881 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011882 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011883 {
11884 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011885 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011886 }
11887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11888 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011890 }
11891 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011893
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011894 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011895
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011896 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011897 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011898 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011899 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011900 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11901 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011902 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011903 child = node->children;
11904 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011905 /*
11906 * Add the annotation to the complex type ancestor.
11907 */
11908 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011909 xmlSchemaParseAnnotation(ctxt, schema, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011910 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011911 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011912 if (child == NULL) {
11913 xmlSchemaPContentErr(ctxt,
11914 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011915 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011916 NULL, "(annotation?, (restriction | extension))");
11917 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011918 if (child == NULL) {
11919 xmlSchemaPContentErr(ctxt,
11920 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011921 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011922 NULL, "(annotation?, (restriction | extension))");
11923 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011924 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011925 xmlSchemaParseRestriction(ctxt, schema, child,
11926 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011927 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011928 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011929 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011930 xmlSchemaParseExtension(ctxt, schema, child,
11931 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011932 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011933 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011934 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011935 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011936 xmlSchemaPContentErr(ctxt,
11937 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011938 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011939 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011940 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011941 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011942}
11943
11944/**
11945 * xmlSchemaParseComplexType:
11946 * @ctxt: a schema validation context
11947 * @schema: the schema being built
11948 * @node: a subtree containing XML Schema informations
11949 *
11950 * parse a XML schema Complex Type definition
11951 * *WARNING* this interface is highly subject to change
11952 *
11953 * Returns the type definition or NULL in case of error
11954 */
11955static xmlSchemaTypePtr
11956xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000011957 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000011958{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011959 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000011960 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011961 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011962 xmlAttrPtr attr;
11963 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011964#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000011965 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011966#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011967 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000011968
Daniel Veillard4255d502002-04-16 15:50:10 +000011969
11970 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11971 return (NULL);
11972
Daniel Veillard01fa6152004-06-29 17:04:39 +000011973 ctxtType = ctxt->ctxtType;
11974
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011975 if (topLevel) {
11976 attr = xmlSchemaGetPropNode(node, "name");
11977 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011978 xmlSchemaPMissingAttrErr(ctxt,
11979 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011980 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011981 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011982 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
11983 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011984 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011986
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011987 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011988 /*
11989 * Parse as local complex type definition.
11990 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011991#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000011992 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011993 type = xmlSchemaAddType(ctxt, schema,
11994 XML_SCHEMA_TYPE_COMPLEX,
11995 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011996 ctxt->targetNamespace, node, 0);
11997#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011998 type = xmlSchemaAddType(ctxt, schema,
11999 XML_SCHEMA_TYPE_COMPLEX,
12000 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012001#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012002 if (type == NULL)
12003 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012004 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012005 type->node = node;
12006 type->type = XML_SCHEMA_TYPE_COMPLEX;
12007 /*
12008 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012009 */
12010 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012011 /*
12012 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012013 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012014 type = xmlSchemaAddType(ctxt, schema,
12015 XML_SCHEMA_TYPE_COMPLEX,
12016 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012017 if (type == NULL)
12018 return (NULL);
12019 type->node = node;
12020 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012021 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012022 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012023 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012024 /*
12025 * Handle attributes.
12026 */
12027 attr = node->properties;
12028 while (attr != NULL) {
12029 if (attr->ns == NULL) {
12030 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12031 /*
12032 * Attribute "id".
12033 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012034 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012035 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12036 /*
12037 * Attribute "mixed".
12038 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012039 if (xmlSchemaPGetBoolNodeValue(ctxt,
12040 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012041 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12042 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012043 /*
12044 * Attributes of global complex type definitions.
12045 */
12046 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12047 /* Pass. */
12048 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12049 /*
12050 * Attribute "abstract".
12051 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012052 if (xmlSchemaPGetBoolNodeValue(ctxt,
12053 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012054 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12055 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12056 /*
12057 * Attribute "final".
12058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012059 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012060 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012061 if (xmlSchemaPValAttrBlockFinal(attrValue,
12062 &(type->flags),
12063 -1,
12064 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12065 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12066 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012067 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012068 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012069 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012070 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012071 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012072 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012073 } else
12074 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012075 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12076 /*
12077 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012078 */
12079 attrValue = xmlSchemaGetNodeContent(ctxt,
12080 (xmlNodePtr) attr);
12081 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012082 -1,
12083 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012084 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012085 -1, -1, -1) != 0) {
12086 xmlSchemaPSimpleTypeErr(ctxt,
12087 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012088 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012089 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012090 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012091 } else
12092 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012093 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012094 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012095 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012096 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012097 } else {
12098 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012099 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012100 }
12101 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012102 xmlSchemaPIllegalAttrErr(ctxt,
12103 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012104 }
12105 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012106 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012107 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012108 /*
12109 * Apply default "block" values.
12110 */
12111 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12112 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12113 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12114 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116 if (! final) {
12117 /*
12118 * Apply default "block" values.
12119 */
12120 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12121 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12122 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12123 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12124 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012125 /*
12126 * And now for the children...
12127 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012128 child = node->children;
12129 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012130 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012132 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012134 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012135 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012136 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012137 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012138 * Specifying mixed='true' when the <simpleContent>
12139 * alternative is chosen has no effect
12140 */
William M. Bracke7091952004-05-11 15:09:58 +000012141 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12142 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012143 xmlSchemaParseSimpleContent(ctxt, schema, child,
12144 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012145 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012146 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012147 /*
12148 * <complexType><complexContent>...
12149 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012150 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012151 xmlSchemaParseComplexContent(ctxt, schema, child,
12152 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012153 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012154 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012155 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012156 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12157 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012158 * SPEC
12159 * "...the third alternative (neither <simpleContent> nor
12160 * <complexContent>) is chosen. This case is understood as shorthand
12161 * for complex content restricting the ·ur-type definition·, and the
12162 * details of the mappings should be modified as necessary.
12163 */
12164 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12165 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012166 /*
12167 * Parse model groups.
12168 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012169 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012170 type->subtypes = (xmlSchemaTypePtr)
12171 xmlSchemaParseModelGroup(ctxt, schema, child,
12172 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012173 child = child->next;
12174 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012175 type->subtypes = (xmlSchemaTypePtr)
12176 xmlSchemaParseModelGroup(ctxt, schema, child,
12177 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012178 child = child->next;
12179 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012180 type->subtypes = (xmlSchemaTypePtr)
12181 xmlSchemaParseModelGroup(ctxt, schema, child,
12182 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012183 child = child->next;
12184 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012185 type->subtypes = (xmlSchemaTypePtr)
12186 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012187 /*
12188 * Note that the reference will be resolved in
12189 * xmlSchemaResolveTypeReferences();
12190 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012191 child = child->next;
12192 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012193 /*
12194 * Parse attribute decls/refs.
12195 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012196 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12197 (xmlSchemaItemListPtr *) &(type->attrUses),
12198 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12199 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012200 /*
12201 * Parse attribute wildcard.
12202 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012204 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12205 child = child->next;
12206 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012207 }
12208 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012209 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012211 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012212 NULL, "(annotation?, (simpleContent | complexContent | "
12213 "((group | all | choice | sequence)?, ((attribute | "
12214 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012215 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012216 /*
12217 * REDEFINE: SPEC src-redefine (5)
12218 */
12219 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12220 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012221 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012222 "<complexType> must have a <restriction> or <extension> "
12223 "grand-child", NULL);
12224 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012225 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012226 return (type);
12227}
12228
Daniel Veillard4255d502002-04-16 15:50:10 +000012229/************************************************************************
12230 * *
12231 * Validating using Schemas *
12232 * *
12233 ************************************************************************/
12234
12235/************************************************************************
12236 * *
12237 * Reading/Writing Schemas *
12238 * *
12239 ************************************************************************/
12240
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012241#if 0 /* Will be enabled if it is clear what options are needed. */
12242/**
12243 * xmlSchemaParserCtxtSetOptions:
12244 * @ctxt: a schema parser context
12245 * @options: a combination of xmlSchemaParserOption
12246 *
12247 * Sets the options to be used during the parse.
12248 *
12249 * Returns 0 in case of success, -1 in case of an
12250 * API error.
12251 */
12252static int
12253xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12254 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012255
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012256{
12257 int i;
12258
12259 if (ctxt == NULL)
12260 return (-1);
12261 /*
12262 * WARNING: Change the start value if adding to the
12263 * xmlSchemaParseOption.
12264 */
12265 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12266 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012267 return (-1);
12268 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012269 }
12270 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012271 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012272}
12273
12274/**
12275 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012276 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012277 *
12278 * Returns the option combination of the parser context.
12279 */
12280static int
12281xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012282
12283{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012284 if (ctxt == NULL)
12285 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 else
12287 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012288}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012289#endif
12290
Daniel Veillard4255d502002-04-16 15:50:10 +000012291/**
12292 * xmlSchemaNewParserCtxt:
12293 * @URL: the location of the schema
12294 *
12295 * Create an XML Schemas parse context for that file/resource expected
12296 * to contain an XML Schemas file.
12297 *
12298 * Returns the parser context or NULL in case of error
12299 */
12300xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012301xmlSchemaNewParserCtxt(const char *URL)
12302{
Daniel Veillard4255d502002-04-16 15:50:10 +000012303 xmlSchemaParserCtxtPtr ret;
12304
12305 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012306 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012307
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012308 ret = xmlSchemaParserCtxtCreate();
12309 if (ret == NULL)
12310 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012311 ret->dict = xmlDictCreate();
12312 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012313 return (ret);
12314}
12315
12316/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012317 * xmlSchemaNewMemParserCtxt:
12318 * @buffer: a pointer to a char array containing the schemas
12319 * @size: the size of the array
12320 *
12321 * Create an XML Schemas parse context for that memory buffer expected
12322 * to contain an XML Schemas file.
12323 *
12324 * Returns the parser context or NULL in case of error
12325 */
12326xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012327xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12328{
Daniel Veillard6045c902002-10-09 21:13:59 +000012329 xmlSchemaParserCtxtPtr ret;
12330
12331 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012332 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012333 ret = xmlSchemaParserCtxtCreate();
12334 if (ret == NULL)
12335 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012336 ret->buffer = buffer;
12337 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012338 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012339 return (ret);
12340}
12341
12342/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012343 * xmlSchemaNewDocParserCtxt:
12344 * @doc: a preparsed document tree
12345 *
12346 * Create an XML Schemas parse context for that document.
12347 * NB. The document may be modified during the parsing process.
12348 *
12349 * Returns the parser context or NULL in case of error
12350 */
12351xmlSchemaParserCtxtPtr
12352xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12353{
12354 xmlSchemaParserCtxtPtr ret;
12355
12356 if (doc == NULL)
12357 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012358 ret = xmlSchemaParserCtxtCreate();
12359 if (ret == NULL)
12360 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012361 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012362 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012363 /* The application has responsibility for the document */
12364 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012365
12366 return (ret);
12367}
12368
12369/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012370 * xmlSchemaFreeParserCtxt:
12371 * @ctxt: the schema parser context
12372 *
12373 * Free the resources associated to the schema parser context
12374 */
12375void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012376xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12377{
Daniel Veillard4255d502002-04-16 15:50:10 +000012378 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012379 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012380 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012381 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012382 if (ctxt->vctxt != NULL) {
12383 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12384 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012385 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12386 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12387 ctxt->constructor = NULL;
12388 ctxt->ownsConstructor = 0;
12389 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012390 if (ctxt->attrProhibs != NULL)
12391 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012392 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012393 xmlFree(ctxt);
12394}
12395
12396/************************************************************************
12397 * *
12398 * Building the content models *
12399 * *
12400 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012401
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012402static void
12403xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012404 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012405{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012406 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012407 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012408 xmlSchemaSubstGroupPtr substGroup;
12409 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012410
12411 elemDecl = (xmlSchemaElementPtr) particle->children;
12412 /*
12413 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012415 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012416 if (end == NULL)
12417 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012418 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012419 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012420 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012421 XML_SCHEMAP_INTERNAL,
12422 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12423 "declaration is marked having a subst. group but none "
12424 "available.\n", elemDecl->name, NULL);
12425 return;
12426 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012427 if (counter >= 0) {
12428 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012429 * NOTE that we put the declaration in, even if it's abstract.
12430 * However, an error will be raised during *validation* if an element
12431 * information item shall be validated against an abstract element
12432 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012433 */
12434 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12435 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12436 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12437 /*
12438 * Add subst. group members.
12439 */
12440 for (i = 0; i < substGroup->members->nbItems; i++) {
12441 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12442 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12443 member->name, member->targetNamespace, member);
12444 }
12445 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012446 /*
12447 * NOTE that we put the declaration in, even if it's abstract,
12448 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012449 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012450 xmlAutomataNewTransition2(pctxt->am,
12451 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012452 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12453 /*
12454 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012455 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012456 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012457 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000012458 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12459 member->name, member->targetNamespace,
12460 1, 1, member);
12461 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012462 }
12463 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012464 xmlAutomataStatePtr hop;
12465 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12466 UNBOUNDED : particle->maxOccurs - 1;
12467 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12468
12469 counter =
12470 xmlAutomataNewCounter(pctxt->am, minOccurs,
12471 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012472 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012473
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012474 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012475 xmlAutomataNewTransition2(pctxt->am,
12476 start, NULL,
12477 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012478 hop);
12479 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012480 * Add subst. group members.
12481 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012482 for (i = 0; i < substGroup->members->nbItems; i++) {
12483 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12484 xmlAutomataNewEpsilon(pctxt->am,
12485 xmlAutomataNewTransition2(pctxt->am,
12486 start, NULL,
12487 member->name, member->targetNamespace, member),
12488 hop);
12489 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012490 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12491 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12492 }
12493 if (particle->minOccurs == 0)
12494 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012495 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012496}
12497
12498static void
12499xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12500 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012502 if (((xmlSchemaElementPtr) particle->children)->flags &
12503 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012504 /*
12505 * Substitution groups.
12506 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012507 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012508 } else {
12509 xmlSchemaElementPtr elemDecl;
12510 xmlAutomataStatePtr start;
12511
12512 elemDecl = (xmlSchemaElementPtr) particle->children;
12513
12514 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012515 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012516 if (particle->maxOccurs == 1) {
12517 start = ctxt->state;
12518 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012519 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12520 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12521 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012522 /* Special case. */
12523 start = ctxt->state;
12524 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12525 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012526 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012527 } else {
12528 int counter;
12529 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12530 UNBOUNDED : particle->maxOccurs - 1;
12531 int minOccurs = particle->minOccurs < 1 ?
12532 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012533
12534 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012535 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12536 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12537 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12538 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12539 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12540 NULL, counter);
12541 }
12542 if (particle->minOccurs == 0)
12543 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12544 }
12545}
12546
Daniel Veillard4255d502002-04-16 15:50:10 +000012547/**
12548 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012549 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012550 * @particle: the particle component
12551 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012552 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012553 * Create the automaton for the {content type} of a complex type.
12554 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012555 */
12556static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012557xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012558 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012559{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012560 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012561 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012562 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012563 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012564 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012565 /*
12566 * Just return in this case. A missing "term" of the particle
12567 * might arise due to an invalid "term" component.
12568 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012569 return;
12570 }
12571
12572 switch (particle->children->type) {
12573 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012574 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012575 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012576 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012577
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012578 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012579
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012580 start = pctxt->state;
12581 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012582
12583 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012584 if (wild->any == 1) {
12585 /*
12586 * We need to add both transitions:
12587 *
12588 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012589 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012590 pctxt->state =
12591 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012592 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012593 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012594 /*
12595 * 2. the {"*"} for elements in no namespace.
12596 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012597 pctxt->state =
12598 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012599 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012600 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012601
12602 } else if (wild->nsSet != NULL) {
12603 ns = wild->nsSet;
12604 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012605 pctxt->state = start;
12606 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12607 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12608 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012609 ns = ns->next;
12610 } while (ns != NULL);
12611
12612 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012613 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12614 start, end, BAD_CAST "*", wild->negNsSet->value,
12615 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012616 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012617 } else {
12618 int counter;
12619 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012620 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012621 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012623 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012624
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012625 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12626 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012628 pctxt->state =
12629 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012630 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012631 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12632 pctxt->state =
12633 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012634 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012635 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012636 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012637 ns = wild->nsSet;
12638 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012639 pctxt->state =
12640 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012641 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012642 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012643 ns = ns->next;
12644 } while (ns != NULL);
12645
12646 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012647 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012648 start, hop, BAD_CAST "*", wild->negNsSet->value,
12649 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012651 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12652 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012653 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012654 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012655 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012657 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012658 break;
12659 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012660 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012661 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012662 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012663 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012664 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012665
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012666 /*
12667 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012668 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012669 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012670 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12671 sub = particle->children->children;
12672 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012673 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012674 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012675 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012676 }
12677 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012678 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012679
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012680 if (particle->maxOccurs >= UNBOUNDED) {
12681 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012682 xmlAutomataStatePtr tmp;
12683 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012684
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012685 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012686 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012687 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012688
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012689 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012690 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012691
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012692 sub = particle->children->children;
12693 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012694 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012695 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012696 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012697 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012698 tmp = pctxt->state;
12699 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012700 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012701 pctxt->state =
12702 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012703 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000012704
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012705 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012706 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000012707 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012708 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012709
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012710 sub = particle->children->children;
12711 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012712 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012713 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012714 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012715 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012716 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012717 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000012718 /*
12719 * epsilon needed to block previous trans from
12720 * being allowed to enter back from another
12721 * construct
12722 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012723 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12724 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012725 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012726 xmlAutomataNewEpsilon(pctxt->am,
12727 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012728 }
12729 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012730 } else if ((particle->maxOccurs > 1)
12731 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012732 xmlAutomataStatePtr tmp;
12733 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012734
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012735 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012736 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012737 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012738
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012739 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012740 particle->minOccurs - 1,
12741 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012742
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012743 sub = particle->children->children;
12744 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012745 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012746 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012747 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012748 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012749 tmp = pctxt->state;
12750 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012751 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012752 pctxt->state =
12753 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012754 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012755 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012756 xmlAutomataNewEpsilon(pctxt->am,
12757 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012758 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012759 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012760 sub = particle->children->children;
12761 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012762 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012763 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012764 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012766 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012767 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12768 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012769 }
12770 }
12771 }
12772 break;
12773 }
12774 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012775 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012776 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000012777
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012778 start = pctxt->state;
12779 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000012780
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012781 /*
12782 * iterate over the subtypes and remerge the end with an
12783 * epsilon transition
12784 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012785 if (particle->maxOccurs == 1) {
12786 sub = particle->children->children;
12787 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012788 pctxt->state = start;
12789 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012790 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012791 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012792 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012793 }
12794 } else {
12795 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000012796 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012797 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12798 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012799 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012800 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000012801
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012802 /*
12803 * use a counter to keep track of the number of transtions
12804 * which went through the choice.
12805 */
12806 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012807 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12808 hop = xmlAutomataNewState(pctxt->am);
12809 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000012810
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012811 sub = particle->children->children;
12812 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012813 pctxt->state = base;
12814 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012815 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012816 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012817 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012818 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012819 xmlAutomataNewEpsilon(pctxt->am, start, base);
12820 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12821 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012822 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012823 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012824 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012825 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012826 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012827 break;
12828 }
12829 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000012830 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012831 xmlSchemaParticlePtr sub;
12832 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012833 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012834
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012835 sub = (xmlSchemaParticlePtr) particle->children->children;
12836 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012837 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012838 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012839 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012840 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012841
12842 elemDecl = (xmlSchemaElementPtr) sub->children;
12843 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012844 PERROR_INT("xmlSchemaBuildAContentModel",
12845 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012846 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012847 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012848 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012849 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000012850 * {particles} of the group must be 0 or 1; this is
12851 * already ensured during the parse of the content of
12852 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012853 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000012854 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12855 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012856
Daniel Veillarda980bef2005-07-18 21:34:03 +000012857 /*
12858 * This is an abstract group, we need to share
12859 * the same counter for all the element transitions
12860 * derived from the group
12861 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012862 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012863 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012864 xmlSchemaBuildContentModelForSubstGroup(pctxt,
12865 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012866 } else {
12867 if ((sub->minOccurs == 1) &&
12868 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012869 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12870 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012871 elemDecl->name,
12872 elemDecl->targetNamespace,
12873 1, 1, elemDecl);
12874 } else if ((sub->minOccurs == 0) &&
12875 (sub->maxOccurs == 1)) {
12876
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012877 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12878 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012879 elemDecl->name,
12880 elemDecl->targetNamespace,
12881 0,
12882 1,
12883 elemDecl);
12884 }
12885 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012886 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012887 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012888 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012889 pctxt->state =
12890 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012891 break;
12892 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012893 case XML_SCHEMA_TYPE_GROUP:
12894 /*
12895 * If we hit a model group definition, then this means that
12896 * it was empty, thus was not substituted for the containing
12897 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012898 * TODO: But the group should be substituted and not occur at
12899 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012900 */
12901 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012902 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012903 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12904 "xmlSchemaBuildAContentModel",
12905 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012906 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012908 }
12909}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012910
Daniel Veillard4255d502002-04-16 15:50:10 +000012911/**
12912 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012913 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012914 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012915 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012916 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012917 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012918 */
12919static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012920xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012921 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012922{
Daniel Veillard4255d502002-04-16 15:50:10 +000012923 xmlAutomataStatePtr start;
12924
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012925 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
12926 (type->contModel != NULL) ||
12927 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
12928 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012929 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012930
12931#ifdef DEBUG_CONTENT
12932 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012933 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012934#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012935 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012936 ctxt->am = xmlNewAutomata();
12937 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012938 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012939 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012940 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012941 }
12942 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012943 /*
12944 * Build the automaton.
12945 */
12946 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000012947 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012948 type->contModel = xmlAutomataCompile(ctxt->am);
12949 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012950 xmlSchemaPCustomErr(ctxt,
12951 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012952 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012953 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012954 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012955 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012956 XML_SCHEMAP_NOT_DETERMINISTIC,
12957 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012958 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012959 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000012960 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000012961#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012962 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012963 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012964 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000012965#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000012966 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012967 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012968 xmlFreeAutomata(ctxt->am);
12969 ctxt->am = NULL;
12970}
12971
12972/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012973 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000012974 * @elem: the schema element context
12975 * @ctxt: the schema parser context
12976 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000012977 * Resolves the references of an element declaration
12978 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012979 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000012980 */
12981static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012982xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
12983 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000012984{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012985 if ((ctxt == NULL) || (elemDecl == NULL) ||
12986 ((elemDecl != NULL) &&
12987 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012988 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012989 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012990
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012991 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012992 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012993
12994 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012995 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012996 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012997 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012998 elemDecl->namedTypeNs);
12999 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013000 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013001 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013002 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013003 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013004 XML_SCHEMA_TYPE_BASIC, "type definition");
13005 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013006 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013007 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013008 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013009 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013010
Daniel Veillardc0826a72004-08-10 14:17:33 +000013011 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013012 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013013 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013014 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013015 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13016 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013017 if (substHead == NULL) {
13018 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013019 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013020 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013021 "substitutionGroup", elemDecl->substGroup,
13022 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013023 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013024 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013025 /*
13026 * Set the "substitution group affiliation".
13027 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013028 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013029 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013030 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013031 * The type definitions is set to:
13032 * SPEC "...the {type definition} of the element
13033 * declaration ·resolved· to by the ·actual value·
13034 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013035 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013036 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013037 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013038 }
13039 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013040 /*
13041 * SPEC "The definition of anyType serves as the default type definition
13042 * for element declarations whose XML representation does not specify one."
13043 */
13044 if ((elemDecl->subtypes == NULL) &&
13045 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013046 (elemDecl->substGroup == NULL))
13047 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013048}
13049
13050/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013051 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013052 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013053 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013054 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013055 * Checks and builds the "member type definitions" property of the union
13056 * simple type. This handles part (1), part (2) is done in
13057 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13058 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013060 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013061static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013062xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13063 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013064{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013065
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013066 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013067 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013068
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013069 /*
13070 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13071 * define the explicit members as the type definitions ·resolved·
13072 * to by the items in the ·actual value· of the memberTypes [attribute],
13073 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013074 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013075 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013076 /*
13077 * Resolve references.
13078 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013079 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013080 lastLink = NULL;
13081 while (link != NULL) {
13082 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013083
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013084 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13085 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13086
13087 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013088 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013090 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13092 /*
13093 * Remove the member type link.
13094 */
13095 if (lastLink == NULL)
13096 type->memberTypes = link->next;
13097 else
13098 lastLink->next = link->next;
13099 newLink = link;
13100 link = link->next;
13101 xmlFree(newLink);
13102 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013103 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013104 lastLink = link;
13105 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013106 }
13107 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013108 /*
13109 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013110 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013111 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013112 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013113 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13114 if (link == NULL) {
13115 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13116 return (-1);
13117 }
13118 link->type = memberType;
13119 link->next = NULL;
13120 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013121 type->memberTypes = link;
13122 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013123 lastLink->next = link;
13124 lastLink = link;
13125 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013126 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013127 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013128}
13129
Daniel Veillard4255d502002-04-16 15:50:10 +000013130/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013131 * xmlSchemaIsDerivedFromBuiltInType:
13132 * @ctxt: the schema parser context
13133 * @type: the type definition
13134 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013135 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013136 *
13137 * Returns 1 if the type has the given value type, or
13138 * is derived from such a type.
13139 */
William M. Brack803812b2004-06-03 02:11:24 +000013140static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013141xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013142{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013143 if (type == NULL)
13144 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013145 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013146 return (0);
13147 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13148 if (type->builtInType == valType)
13149 return(1);
13150 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13151 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13152 return (0);
13153 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13154 } else
13155 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013156
13157 return (0);
13158}
13159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013160#if 0
13161/**
13162 * xmlSchemaIsDerivedFromBuiltInType:
13163 * @ctxt: the schema parser context
13164 * @type: the type definition
13165 * @valType: the value type
13166 *
13167 *
13168 * Returns 1 if the type has the given value type, or
13169 * is derived from such a type.
13170 */
13171static int
13172xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13173{
13174 if (type == NULL)
13175 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013176 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 return (0);
13178 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13179 if (type->builtInType == valType)
13180 return(1);
13181 return (0);
13182 } else
13183 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13184
13185 return (0);
13186}
13187#endif
13188
13189static xmlSchemaTypePtr
13190xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13191{
13192 if (type == NULL)
13193 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013194 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013195 return (NULL);
13196 if (type->type == XML_SCHEMA_TYPE_BASIC)
13197 return(type);
13198 else
13199 return(xmlSchemaQueryBuiltInType(type->subtypes));
13200
13201 return (NULL);
13202}
13203
Daniel Veillard3646d642004-06-02 19:19:14 +000013204/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013205 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013206 * @type: the simpleType definition
13207 *
13208 * Returns the primitive type of the given type or
13209 * NULL in case of error.
13210 */
13211static xmlSchemaTypePtr
13212xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13213{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013214
Daniel Veillard01fa6152004-06-29 17:04:39 +000013215 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013216 /*
13217 * Note that anySimpleType is actually not a primitive type
13218 * but we need that here.
13219 */
13220 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13221 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013222 return (type);
13223 type = type->baseType;
13224 }
13225
13226 return (NULL);
13227}
13228
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013229#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013230/**
13231 * xmlSchemaGetBuiltInTypeAncestor:
13232 * @type: the simpleType definition
13233 *
13234 * Returns the primitive type of the given type or
13235 * NULL in case of error.
13236 */
13237static xmlSchemaTypePtr
13238xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13239{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013240 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013241 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013242 while (type != NULL) {
13243 if (type->type == XML_SCHEMA_TYPE_BASIC)
13244 return (type);
13245 type = type->baseType;
13246 }
13247
13248 return (NULL);
13249}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013250#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013251
Daniel Veillard01fa6152004-06-29 17:04:39 +000013252/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013253 * xmlSchemaCloneWildcardNsConstraints:
13254 * @ctxt: the schema parser context
13255 * @dest: the destination wildcard
13256 * @source: the source wildcard
13257 *
13258 * Clones the namespace constraints of source
13259 * and assignes them to dest.
13260 * Returns -1 on internal error, 0 otherwise.
13261 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013262static int
13263xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013264 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013265 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013266{
13267 xmlSchemaWildcardNsPtr cur, tmp, last;
13268
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013269 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013270 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013271 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013272 cur = source->nsSet;
13273 last = NULL;
13274 while (cur != NULL) {
13275 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13276 if (tmp == NULL)
13277 return(-1);
13278 tmp->value = cur->value;
13279 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013280 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013281 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013282 last->next = tmp;
13283 last = tmp;
13284 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013286 if (dest->negNsSet != NULL)
13287 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013288 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013289 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13290 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013291 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013292 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013293 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013294 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013295 return(0);
13296}
13297
Daniel Veillard50355f02004-06-08 17:52:16 +000013298/**
13299 * xmlSchemaUnionWildcards:
13300 * @ctxt: the schema parser context
13301 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013302 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013303 *
13304 * Unions the namespace constraints of the given wildcards.
13305 * @completeWild will hold the resulting union.
13306 * Returns a positive error code on failure, -1 in case of an
13307 * internal error, 0 otherwise.
13308 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013309static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013310xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013311 xmlSchemaWildcardPtr completeWild,
13312 xmlSchemaWildcardPtr curWild)
13313{
13314 xmlSchemaWildcardNsPtr cur, curB, tmp;
13315
13316 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013317 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013318 * value.
13319 */
13320 if ((completeWild->any == curWild->any) &&
13321 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13322 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013323
Daniel Veillard3646d642004-06-02 19:19:14 +000013324 if ((completeWild->negNsSet == NULL) ||
13325 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013326
Daniel Veillard3646d642004-06-02 19:19:14 +000013327 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013328 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013329
13330 /*
13331 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013332 */
13333 cur = completeWild->nsSet;
13334 while (cur != NULL) {
13335 found = 0;
13336 curB = curWild->nsSet;
13337 while (curB != NULL) {
13338 if (cur->value == curB->value) {
13339 found = 1;
13340 break;
13341 }
13342 curB = curB->next;
13343 }
13344 if (!found)
13345 break;
13346 cur = cur->next;
13347 }
13348 if (found)
13349 return(0);
13350 } else
13351 return(0);
13352 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013353 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013354 /*
13355 * 2 If either O1 or O2 is any, then any must be the value
13356 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013357 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013358 if (completeWild->any == 0) {
13359 completeWild->any = 1;
13360 if (completeWild->nsSet != NULL) {
13361 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13362 completeWild->nsSet = NULL;
13363 }
13364 if (completeWild->negNsSet != NULL) {
13365 xmlFree(completeWild->negNsSet);
13366 completeWild->negNsSet = NULL;
13367 }
13368 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013369 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013370 }
13371 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013373 * then the union of those sets must be the value.
13374 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013375 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013376 int found;
13377 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013378
Daniel Veillard3646d642004-06-02 19:19:14 +000013379 cur = curWild->nsSet;
13380 start = completeWild->nsSet;
13381 while (cur != NULL) {
13382 found = 0;
13383 curB = start;
13384 while (curB != NULL) {
13385 if (cur->value == curB->value) {
13386 found = 1;
13387 break;
13388 }
13389 curB = curB->next;
13390 }
13391 if (!found) {
13392 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013393 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013394 return (-1);
13395 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013396 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013397 completeWild->nsSet = tmp;
13398 }
13399 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013400 }
13401
Daniel Veillard3646d642004-06-02 19:19:14 +000013402 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013403 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013404 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013405 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000013406 * or ·absent·), then a pair of not and ·absent· must be the value.
13407 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013409 (curWild->negNsSet != NULL) &&
13410 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13411 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013412
13413 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013415 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013416 * 5.
13417 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013419 (completeWild->negNsSet->value != NULL) &&
13420 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013421 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013422 (curWild->negNsSet->value != NULL) &&
13423 (completeWild->nsSet != NULL))) {
13424
13425 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013426
Daniel Veillard3646d642004-06-02 19:19:14 +000013427 if (completeWild->nsSet != NULL) {
13428 cur = completeWild->nsSet;
13429 curB = curWild->negNsSet;
13430 } else {
13431 cur = curWild->nsSet;
13432 curB = completeWild->negNsSet;
13433 }
13434 nsFound = 0;
13435 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013436 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013437 absentFound = 1;
13438 else if (cur->value == curB->value)
13439 nsFound = 1;
13440 if (nsFound && absentFound)
13441 break;
13442 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013443 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013444
13445 if (nsFound && absentFound) {
13446 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000013448 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013450 completeWild->any = 1;
13451 if (completeWild->nsSet != NULL) {
13452 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13453 completeWild->nsSet = NULL;
13454 }
13455 if (completeWild->negNsSet != NULL) {
13456 xmlFree(completeWild->negNsSet);
13457 completeWild->negNsSet = NULL;
13458 }
13459 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013460 /*
13461 * 5.2 If the set S includes the negated namespace name
13462 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000013463 * be the value.
13464 */
13465 if (completeWild->nsSet != NULL) {
13466 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13467 completeWild->nsSet = NULL;
13468 }
13469 if (completeWild->negNsSet == NULL) {
13470 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13471 if (completeWild->negNsSet == NULL)
13472 return (-1);
13473 }
13474 completeWild->negNsSet->value = NULL;
13475 } else if ((!nsFound) && absentFound) {
13476 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013477 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013478 * namespace name, then the union is not expressible.
13479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013480 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013481 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013482 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013483 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013484 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013485 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486 /*
13487 * 5.4 If the set S does not include either the negated namespace
13488 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013489 * and a namespace name must be the value.
13490 */
13491 if (completeWild->negNsSet == NULL) {
13492 if (completeWild->nsSet != NULL) {
13493 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13494 completeWild->nsSet = NULL;
13495 }
13496 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13497 if (completeWild->negNsSet == NULL)
13498 return (-1);
13499 completeWild->negNsSet->value = curWild->negNsSet->value;
13500 }
13501 }
13502 return (0);
13503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013505 * 6.
13506 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013507 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013508 (completeWild->negNsSet->value == NULL) &&
13509 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013511 (curWild->negNsSet->value == NULL) &&
13512 (completeWild->nsSet != NULL))) {
13513
13514 if (completeWild->nsSet != NULL) {
13515 cur = completeWild->nsSet;
13516 } else {
13517 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013519 while (cur != NULL) {
13520 if (cur->value == NULL) {
13521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013522 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013523 * value.
13524 */
13525 completeWild->any = 1;
13526 if (completeWild->nsSet != NULL) {
13527 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13528 completeWild->nsSet = NULL;
13529 }
13530 if (completeWild->negNsSet != NULL) {
13531 xmlFree(completeWild->negNsSet);
13532 completeWild->negNsSet = NULL;
13533 }
13534 return (0);
13535 }
13536 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013537 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013538 if (completeWild->negNsSet == NULL) {
13539 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013541 * and ·absent· must be the value.
13542 */
13543 if (completeWild->nsSet != NULL) {
13544 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13545 completeWild->nsSet = NULL;
13546 }
13547 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13548 if (completeWild->negNsSet == NULL)
13549 return (-1);
13550 completeWild->negNsSet->value = NULL;
13551 }
13552 return (0);
13553 }
13554 return (0);
13555
13556}
13557
Daniel Veillard50355f02004-06-08 17:52:16 +000013558/**
13559 * xmlSchemaIntersectWildcards:
13560 * @ctxt: the schema parser context
13561 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013562 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013563 *
13564 * Intersects the namespace constraints of the given wildcards.
13565 * @completeWild will hold the resulting intersection.
13566 * Returns a positive error code on failure, -1 in case of an
13567 * internal error, 0 otherwise.
13568 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013569static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013571 xmlSchemaWildcardPtr completeWild,
13572 xmlSchemaWildcardPtr curWild)
13573{
William M. Brack803812b2004-06-03 02:11:24 +000013574 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013575
13576 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013578 * value.
13579 */
13580 if ((completeWild->any == curWild->any) &&
13581 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13582 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013583
Daniel Veillard3646d642004-06-02 19:19:14 +000013584 if ((completeWild->negNsSet == NULL) ||
13585 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013586
Daniel Veillard3646d642004-06-02 19:19:14 +000013587 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013588 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013589
13590 /*
13591 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 */
13593 cur = completeWild->nsSet;
13594 while (cur != NULL) {
13595 found = 0;
13596 curB = curWild->nsSet;
13597 while (curB != NULL) {
13598 if (cur->value == curB->value) {
13599 found = 1;
13600 break;
13601 }
13602 curB = curB->next;
13603 }
13604 if (!found)
13605 break;
13606 cur = cur->next;
13607 }
13608 if (found)
13609 return(0);
13610 } else
13611 return(0);
13612 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013614 /*
13615 * 2 If either O1 or O2 is any, then the other must be the value.
13616 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013618 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013619 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013620 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013621 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013622 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013623 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13624 * name or ·absent·) and the other is a set of (namespace names or
13625 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000013626 * the set, minus ·absent· if it was in the set, must be the value.
13627 */
13628 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13629 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13630 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631
Daniel Veillard3646d642004-06-02 19:19:14 +000013632 if (completeWild->nsSet == NULL) {
13633 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013634 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013635 return(-1);
13636 } else
13637 neg = curWild->negNsSet->value;
13638 /*
13639 * Remove absent and negated.
13640 */
13641 prev = NULL;
13642 cur = completeWild->nsSet;
13643 while (cur != NULL) {
13644 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013646 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013647 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013648 prev->next = cur->next;
13649 xmlFree(cur);
13650 break;
13651 }
13652 prev = cur;
13653 cur = cur->next;
13654 }
13655 if (neg != NULL) {
13656 prev = NULL;
13657 cur = completeWild->nsSet;
13658 while (cur != NULL) {
13659 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013660 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013661 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013662 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013663 prev->next = cur->next;
13664 xmlFree(cur);
13665 break;
13666 }
13667 prev = cur;
13668 cur = cur->next;
13669 }
13670 }
13671
13672 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013673 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013674 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013675 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000013676 * then the intersection of those sets must be the value.
13677 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013678 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013679 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013680
Daniel Veillard3646d642004-06-02 19:19:14 +000013681 cur = completeWild->nsSet;
13682 prev = NULL;
13683 while (cur != NULL) {
13684 found = 0;
13685 curB = curWild->nsSet;
13686 while (curB != NULL) {
13687 if (cur->value == curB->value) {
13688 found = 1;
13689 break;
13690 }
13691 curB = curB->next;
13692 }
13693 if (!found) {
13694 if (prev == NULL)
13695 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013696 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013697 prev->next = cur->next;
13698 tmp = cur->next;
13699 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 continue;
13702 }
13703 prev = cur;
13704 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 }
13706
Daniel Veillard3646d642004-06-02 19:19:14 +000013707 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 }
13709 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013710 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 */
13712 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013713 (curWild->negNsSet != NULL) &&
13714 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013716 (curWild->negNsSet->value != NULL)) {
13717
13718 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013719 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013721 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 }
13723 /*
13724 * 6 If the one is a negation of a namespace name and the other
13725 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013726 * of a namespace name must be the value.
13727 */
13728 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13729 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013730 (completeWild->negNsSet->value == NULL)) {
13731 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013732 }
13733 return(0);
13734}
13735
Daniel Veillard50355f02004-06-08 17:52:16 +000013736/**
13737 * xmlSchemaIsWildcardNsConstraintSubset:
13738 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013739 * @sub: the first wildcard
13740 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013741 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013742 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13743 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013744 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013745 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013746 */
13747static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013748xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13749 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750{
Daniel Veillard50355f02004-06-08 17:52:16 +000013751 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013753 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013754 if (super->any)
13755 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013756 /*
13757 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
13758 * 2.2 super must be a pair of not and the same value.
13759 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013760 if ((sub->negNsSet != NULL) &&
13761 (super->negNsSet != NULL) &&
13762 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 return (0);
13764 /*
13765 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000013766 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013767 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013768 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013769 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000013770 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013771 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013772 xmlSchemaWildcardNsPtr cur, curB;
13773 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013775 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013776 while (cur != NULL) {
13777 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013778 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000013779 while (curB != NULL) {
13780 if (cur->value == curB->value) {
13781 found = 1;
13782 break;
13783 }
13784 curB = curB->next;
13785 }
13786 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013787 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013788 cur = cur->next;
13789 }
13790 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013792 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013793 xmlSchemaWildcardNsPtr cur;
13794 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795 * 3.2.2 super must be a pair of not and a namespace name or
13796 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000013797 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013798 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013800 if (cur->value == super->negNsSet->value)
13801 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013802 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013804 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013805 }
13806 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013807 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013808}
13809
Daniel Veillard50355f02004-06-08 17:52:16 +000013810static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013811xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013812 int *fixed,
13813 const xmlChar **value,
13814 xmlSchemaValPtr *val)
13815{
13816 *fixed = 0;
13817 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013819 *val = NULL;
13820
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013821 if (attruse->defValue != NULL) {
13822 *value = attruse->defValue;
13823 *val = attruse->defVal;
13824 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013825 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013826 return(1);
13827 } else if ((WXS_ATTRUSE_DECL(attruse) != NULL) &&
13828 (WXS_ATTRUSE_DECL(attruse)->defValue != NULL)) {
13829 *value = (WXS_ATTRUSE_DECL(attruse))->defValue;
13830 *val = (WXS_ATTRUSE_DECL(attruse))->defVal;
13831 if ((WXS_ATTRUSE_DECL(attruse))->flags & XML_SCHEMAS_ATTR_FIXED)
13832 *fixed = 1;
13833 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013834 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013835 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013836}
Daniel Veillard3646d642004-06-02 19:19:14 +000013837/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013839 * @wild: the wildcard
13840 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841 *
13842 * Validation Rule: Wildcard allows Namespace Name
13843 * (cvc-wildcard-namespace)
13844 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013845 * Returns 0 if the given namespace matches the wildcard,
13846 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000013847 */
13848static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013849xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13850 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013851{
13852 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013853 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013854
13855 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013856 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013857 else if (wild->nsSet != NULL) {
13858 xmlSchemaWildcardNsPtr cur;
13859
13860 cur = wild->nsSet;
13861 while (cur != NULL) {
13862 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013863 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013864 cur = cur->next;
13865 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013866 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013867 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013868 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013869
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013870 return(1);
13871}
13872
13873#define XML_SCHEMA_ACTION_DERIVE 0
13874#define XML_SCHEMA_ACTION_REDEFINE 1
13875
13876#define WXS_ACTION_STR(a) \
13877((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13878
13879/*
13880* Schema Component Constraint:
13881* Derivation Valid (Restriction, Complex)
13882* derivation-ok-restriction (2) - (4)
13883*
13884* ATTENTION:
13885* In XML Schema 1.1 this will be:
13886* Validation Rule:
13887* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13888*
13889*/
13890static int
13891xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13892 int action,
13893 xmlSchemaBasicItemPtr item,
13894 xmlSchemaBasicItemPtr baseItem,
13895 xmlSchemaItemListPtr uses,
13896 xmlSchemaItemListPtr baseUses,
13897 xmlSchemaWildcardPtr wild,
13898 xmlSchemaWildcardPtr baseWild)
13899{
13900 xmlSchemaAttributeUsePtr cur = NULL, bcur;
13901 int i, j, found, err = 0;
13902 const xmlChar *bEffValue;
13903 int effFixed;
13904
13905 if (uses != NULL) {
13906 for (i = 0; i < uses->nbItems; i++) {
13907 cur = uses->items[i];
13908 found = 0;
13909 if (baseUses == NULL)
13910 goto not_found;
13911 for (j = 0; j < baseUses->nbItems; j++) {
13912 bcur = baseUses->items[j];
13913 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
13914 WXS_ATTRUSE_DECL_NAME(bcur)) &&
13915 (WXS_ATTRUSE_DECL_TNS(cur) ==
13916 WXS_ATTRUSE_DECL_TNS(bcur)))
13917 {
13918 /*
13919 * (2.1) "If there is an attribute use in the {attribute
13920 * uses} of the {base type definition} (call this B) whose
13921 * {attribute declaration} has the same {name} and {target
13922 * namespace}, then all of the following must be true:"
13923 */
13924 found = 1;
13925
13926 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13927 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
13928 {
13929 xmlChar *str = NULL;
13930 /*
13931 * (2.1.1) "one of the following must be true:"
13932 * (2.1.1.1) "B's {required} is false."
13933 * (2.1.1.2) "R's {required} is true."
13934 */
13935 xmlSchemaPAttrUseErr4(pctxt,
13936 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
13937 WXS_ITEM_NODE(item), item, cur,
13938 "The 'optional' attribute use is inconsistent "
13939 "with the corresponding 'required' attribute use of "
13940 "the %s %s",
13941 WXS_ACTION_STR(action),
13942 xmlSchemaGetComponentDesignation(&str, baseItem),
13943 NULL, NULL);
13944 FREE_AND_NULL(str);
13945 err = pctxt->err;
13946 } else if (xmlSchemaCheckCOSSTDerivedOK(pctxt,
13947 WXS_ATTRUSE_TYPEDEF(cur),
13948 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
13949 {
13950 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
13951
13952 /*
13953 * SPEC (2.1.2) "R's {attribute declaration}'s
13954 * {type definition} must be validly derived from
13955 * B's {type definition} given the empty set as
13956 * defined in Type Derivation OK (Simple) (§3.14.6)."
13957 */
13958 xmlSchemaPAttrUseErr4(pctxt,
13959 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
13960 WXS_ITEM_NODE(item), item, cur,
13961 "The attribute declaration's %s "
13962 "is not validly derived from "
13963 "the corresponding %s of the "
13964 "attribute declaration in the %s %s",
13965 xmlSchemaGetComponentDesignation(&strA,
13966 WXS_ATTRUSE_TYPEDEF(cur)),
13967 xmlSchemaGetComponentDesignation(&strB,
13968 WXS_ATTRUSE_TYPEDEF(bcur)),
13969 WXS_ACTION_STR(action),
13970 xmlSchemaGetComponentDesignation(&strC, baseItem));
13971 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
13972 FREE_AND_NULL(strA);
13973 FREE_AND_NULL(strB);
13974 FREE_AND_NULL(strC);
13975 err = pctxt->err;
13976 } else {
13977 /*
13978 * 2.1.3 [Definition:] Let the effective value
13979 * constraint of an attribute use be its {value
13980 * constraint}, if present, otherwise its {attribute
13981 * declaration}'s {value constraint} .
13982 */
13983 xmlSchemaGetEffectiveValueConstraint(bcur,
13984 &effFixed, &bEffValue, NULL);
13985 /*
13986 * 2.1.3 ... one of the following must be true
13987 *
13988 * 2.1.3.1 B's ·effective value constraint· is
13989 * ·absent· or default.
13990 */
13991 if ((bEffValue != NULL) &&
13992 (effFixed == 1)) {
13993 const xmlChar *rEffValue = NULL;
13994
13995 xmlSchemaGetEffectiveValueConstraint(bcur,
13996 &effFixed, &rEffValue, NULL);
13997 /*
13998 * 2.1.3.2 R's ·effective value constraint· is
13999 * fixed with the same string as B's.
14000 * MAYBE TODO: Compare the computed values.
14001 * Hmm, it says "same string" so
14002 * string-equality might really be sufficient.
14003 */
14004 if ((effFixed == 0) ||
14005 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14006 {
14007 xmlChar *str = NULL;
14008
14009 xmlSchemaPAttrUseErr4(pctxt,
14010 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14011 WXS_ITEM_NODE(item), item, cur,
14012 "The effective value constraint of the "
14013 "attribute use is inconsistent with "
14014 "its correspondent in the %s %s",
14015 WXS_ACTION_STR(action),
14016 xmlSchemaGetComponentDesignation(&str,
14017 baseItem),
14018 NULL, NULL);
14019 FREE_AND_NULL(str);
14020 err = pctxt->err;
14021 }
14022 }
14023 }
14024 break;
14025 }
14026 }
14027not_found:
14028 if (!found) {
14029 /*
14030 * (2.2) "otherwise the {base type definition} must have an
14031 * {attribute wildcard} and the {target namespace} of the
14032 * R's {attribute declaration} must be ·valid· with respect
14033 * to that wildcard, as defined in Wildcard allows Namespace
14034 * Name (§3.10.4)."
14035 */
14036 if ((baseWild == NULL) ||
14037 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14038 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14039 {
14040 xmlChar *str = NULL;
14041
14042 xmlSchemaPAttrUseErr4(pctxt,
14043 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14044 WXS_ITEM_NODE(item), item, cur,
14045 "Neither a matching attribute use, "
14046 "nor a matching wildcard exists in the %s %s",
14047 WXS_ACTION_STR(action),
14048 xmlSchemaGetComponentDesignation(&str, baseItem),
14049 NULL, NULL);
14050 FREE_AND_NULL(str);
14051 err = pctxt->err;
14052 }
14053 }
14054 }
14055 }
14056 /*
14057 * SPEC derivation-ok-restriction (3):
14058 * (3) "For each attribute use in the {attribute uses} of the {base type
14059 * definition} whose {required} is true, there must be an attribute
14060 * use with an {attribute declaration} with the same {name} and
14061 * {target namespace} as its {attribute declaration} in the {attribute
14062 * uses} of the complex type definition itself whose {required} is true.
14063 */
14064 if (baseUses != NULL) {
14065 for (j = 0; j < baseUses->nbItems; j++) {
14066 bcur = baseUses->items[j];
14067 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14068 continue;
14069 found = 0;
14070 if (uses != NULL) {
14071 for (i = 0; i < uses->nbItems; i++) {
14072 cur = uses->items[i];
14073 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14074 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14075 (WXS_ATTRUSE_DECL_TNS(cur) ==
14076 WXS_ATTRUSE_DECL_TNS(bcur))) {
14077 found = 1;
14078 break;
14079 }
14080 }
14081 }
14082 if (!found) {
14083 xmlChar *strA = NULL, *strB = NULL;
14084
14085 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14086 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14087 NULL, item,
14088 "A matching attribute use for the "
14089 "'required' %s of the %s %s is missing",
14090 xmlSchemaGetComponentDesignation(&strA, bcur),
14091 WXS_ACTION_STR(action),
14092 xmlSchemaGetComponentDesignation(&strB, baseItem),
14093 NULL);
14094 FREE_AND_NULL(strA);
14095 FREE_AND_NULL(strB);
14096 }
14097 }
14098 }
14099 /*
14100 * derivation-ok-restriction (4)
14101 */
14102 if (wild != NULL) {
14103 /*
14104 * (4) "If there is an {attribute wildcard}, all of the
14105 * following must be true:"
14106 */
14107 if (baseWild == NULL) {
14108 xmlChar *str = NULL;
14109
14110 /*
14111 * (4.1) "The {base type definition} must also have one."
14112 */
14113 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14114 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14115 NULL, item,
14116 "The %s has an attribute wildcard, "
14117 "but the %s %s '%s' does not have one",
14118 WXS_ITEM_TYPE_NAME(item),
14119 WXS_ACTION_STR(action),
14120 WXS_ITEM_TYPE_NAME(baseItem),
14121 xmlSchemaGetComponentQName(&str, baseItem));
14122 FREE_AND_NULL(str);
14123 return(pctxt->err);
14124 } else if ((baseWild->any == 0) &&
14125 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14126 {
14127 xmlChar *str = NULL;
14128 /*
14129 * (4.2) "The complex type definition's {attribute wildcard}'s
14130 * {namespace constraint} must be a subset of the {base type
14131 * definition}'s {attribute wildcard}'s {namespace constraint},
14132 * as defined by Wildcard Subset (§3.10.6)."
14133 */
14134 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14135 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14136 NULL, item,
14137 "The attribute wildcard is not a valid "
14138 "subset of the wildcard in the %s %s '%s'",
14139 WXS_ACTION_STR(action),
14140 WXS_ITEM_TYPE_NAME(baseItem),
14141 xmlSchemaGetComponentQName(&str, baseItem),
14142 NULL);
14143 FREE_AND_NULL(str);
14144 return(pctxt->err);
14145 }
14146 /* 4.3 Unless the {base type definition} is the ·ur-type
14147 * definition·, the complex type definition's {attribute
14148 * wildcard}'s {process contents} must be identical to or
14149 * stronger than the {base type definition}'s {attribute
14150 * wildcard}'s {process contents}, where strict is stronger
14151 * than lax is stronger than skip.
14152 */
14153 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14154 (wild->processContents < baseWild->processContents)) {
14155 xmlChar *str = NULL;
14156 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14157 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14158 NULL, baseItem,
14159 "The {process contents} of the attribute wildcard is "
14160 "weaker than the one in the %s %s '%s'",
14161 WXS_ACTION_STR(action),
14162 WXS_ITEM_TYPE_NAME(baseItem),
14163 xmlSchemaGetComponentQName(&str, baseItem),
14164 NULL);
14165 FREE_AND_NULL(str)
14166 return(pctxt->err);
14167 }
14168 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014169 return(0);
14170}
14171
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014172
14173static int
14174xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14175 xmlSchemaBasicItemPtr item,
14176 xmlSchemaWildcardPtr *completeWild,
14177 xmlSchemaItemListPtr list,
14178 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014179/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014180 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014181 * @ctxt: the schema parser context
14182 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014183 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014184 *
14185 * Builds the wildcard and the attribute uses on the given complex type.
14186 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014187 *
14188 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14189 * strings, so recheck this if we start to hardcode some schemata, since
14190 * they might not be in the same dict.
14191 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014192 */
14193static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014194xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014195 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014196{
14197 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014198 xmlSchemaAttributeUsePtr use;
14199 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014200
Daniel Veillard01fa6152004-06-29 17:04:39 +000014201 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014202 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014203 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014204 return (-1);
14205 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014206 baseType = type->baseType;
14207 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14208 if (xmlSchemaTypeFixup(baseType, pctxt) == -1)
14209 return(-1);
14210
14211 uses = type->attrUses;
14212 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014213 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014214 * Expand attribute group references. And build the 'complete'
14215 * wildcard, i.e. intersect multiple wildcards.
14216 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014217 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014218 if (uses != NULL) {
14219 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014220 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014221 * This one will transfer all attr. prohibitions
14222 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014223 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014224 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14225 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14226 pctxt->attrProhibs) == -1)
14227 {
14228 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14229 "failed to expand attributes");
14230 }
14231 if (pctxt->attrProhibs->nbItems != 0)
14232 prohibs = pctxt->attrProhibs;
14233 } else {
14234 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14235 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14236 NULL) == -1)
14237 {
14238 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14239 "failed to expand attributes");
14240 }
14241 }
14242 }
14243 /*
14244 * Inherit the attribute uses of the base type.
14245 */
14246 if (baseUses != NULL) {
14247 int i, j;
14248 xmlSchemaAttributeUseProhibPtr pro;
14249
14250 if (WXS_IS_RESTRICTION(type)) {
14251 int usesCount;
14252 xmlSchemaAttributeUsePtr tmp;
14253
14254 if (uses != NULL)
14255 usesCount = uses->nbItems;
14256 else
14257 usesCount = 0;
14258
14259 /* Restriction. */
14260 for (i = 0; i < baseUses->nbItems; i++) {
14261 use = baseUses->items[i];
14262 if (prohibs) {
14263 /*
14264 * Filter out prohibited uses.
14265 */
14266 for (j = 0; j < prohibs->nbItems; j++) {
14267 pro = prohibs->items[j];
14268 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14269 (WXS_ATTRUSE_DECL_TNS(use) ==
14270 pro->targetNamespace))
14271 {
14272 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014273 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014274 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014275 }
14276 if (usesCount) {
14277 /*
14278 * Filter out existing uses.
14279 */
14280 for (j = 0; j < usesCount; j++) {
14281 tmp = uses->items[j];
14282 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14283 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14284 (WXS_ATTRUSE_DECL_TNS(use) ==
14285 WXS_ATTRUSE_DECL_TNS(tmp)))
14286 {
14287 goto inherit_next;
14288 }
14289 }
14290 }
14291 if (uses == NULL) {
14292 type->attrUses = xmlSchemaItemListCreate();
14293 if (type->attrUses == NULL)
14294 goto exit_failure;
14295 uses = type->attrUses;
14296 }
14297 xmlSchemaItemListAddSize(uses, 2, use);
14298inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014299 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014300 } else {
14301 /* Extension. */
14302 for (i = 0; i < baseUses->nbItems; i++) {
14303 use = baseUses->items[i];
14304 if (uses == NULL) {
14305 type->attrUses = xmlSchemaItemListCreate();
14306 if (type->attrUses == NULL)
14307 goto exit_failure;
14308 uses = type->attrUses;
14309 }
14310 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14311 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014312 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014313 }
14314 /*
14315 * Shrink attr. uses.
14316 */
14317 if (uses) {
14318 if (uses->nbItems == 0) {
14319 xmlSchemaItemListFree(uses);
14320 type->attrUses = NULL;
14321 }
14322 /*
14323 * TODO: We could shrink the size of the array
14324 * to fit the actual number of items.
14325 */
14326 }
14327 /*
14328 * Compute the complete wildcard.
14329 */
14330 if (WXS_IS_EXTENSION(type)) {
14331 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014332 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014333 * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then
14334 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014335 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014336 if (type->attributeWildcard != NULL) {
14337 /*
14338 * Union the complete wildcard with the base wildcard.
14339 * SPEC {attribute wildcard}
14340 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14341 * and {annotation} are those of the ·complete wildcard·,
14342 * and whose {namespace constraint} is the intensional union
14343 * of the {namespace constraint} of the ·complete wildcard·
14344 * and of the ·base wildcard·, as defined in Attribute
14345 * Wildcard Union (§3.10.6)."
14346 */
14347 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14348 baseType->attributeWildcard) == -1)
14349 goto exit_failure;
14350 } else {
14351 /*
14352 * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·,
14353 * then the ·base wildcard·."
14354 */
14355 type->attributeWildcard = baseType->attributeWildcard;
14356 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014357 } else {
14358 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014359 * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the
14360 * ·complete wildcard"
14361 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014362 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014363 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014364 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014365 /*
14366 * SPEC {attribute wildcard}
14367 * (3.1) "If the <restriction> alternative is chosen, then the
14368 * ·complete wildcard·;"
14369 * NOOP
14370 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014371 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014372
Daniel Veillard3646d642004-06-02 19:19:14 +000014373 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014374
14375exit_failure:
14376 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014377}
14378
14379/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014380 * xmlSchemaTypeFinalContains:
14381 * @schema: the schema
14382 * @type: the type definition
14383 * @final: the final
14384 *
14385 * Evaluates if a type definition contains the given "final".
14386 * This does take "finalDefault" into account as well.
14387 *
14388 * Returns 1 if the type does containt the given "final",
14389 * 0 otherwise.
14390 */
14391static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014392xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014393{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014394 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014395 return (0);
14396 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014397 return (1);
14398 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014399 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014400}
14401
14402/**
14403 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14404 * @type: the Union Simple Type
14405 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014406 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014407 * returns NULL otherwise.
14408 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014409static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014410xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14411{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014412 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014413 if (type->memberTypes != NULL)
14414 return (type->memberTypes);
14415 else
14416 type = type->baseType;
14417 }
14418 return (NULL);
14419}
14420
14421/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014422 * xmlSchemaGetParticleTotalRangeMin:
14423 * @particle: the particle
14424 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014425 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014426 * (all and sequence) + (choice)
14427 *
14428 * Returns the minimun Effective Total Range.
14429 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014430static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014431xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014432{
14433 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014434 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014435 return (0);
14436 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014437 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014438 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014439 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014440
14441 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014442 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014443 while (part != NULL) {
14444 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14445 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014446 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014447 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014448 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014449 if (cur == 0)
14450 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014451 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014452 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014453 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014454 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014455 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014456 } else {
14457 /* <all> and <sequence> */
14458 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014459 xmlSchemaParticlePtr part =
14460 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014461
14462 if (part == NULL)
14463 return (0);
14464 do {
14465 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14466 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014467 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014468 else
14469 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014470 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014471 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014472 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014473 }
14474}
14475
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014476/**
14477 * xmlSchemaGetParticleTotalRangeMax:
14478 * @particle: the particle
14479 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014480 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014481 * (all and sequence) + (choice)
14482 *
14483 * Returns the maximum Effective Total Range.
14484 */
14485static int
14486xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14487{
14488 if ((particle->children == NULL) ||
14489 (particle->children->children == NULL))
14490 return (0);
14491 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14492 int max = -1, cur;
14493 xmlSchemaParticlePtr part =
14494 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014495
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014496 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14497 if (part->children == NULL)
14498 continue;
14499 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14500 (part->children->type == XML_SCHEMA_TYPE_ANY))
14501 cur = part->maxOccurs;
14502 else
14503 cur = xmlSchemaGetParticleTotalRangeMax(part);
14504 if (cur == UNBOUNDED)
14505 return (UNBOUNDED);
14506 if ((max < cur) || (max == -1))
14507 max = cur;
14508 }
14509 /* TODO: Handle overflows? */
14510 return (particle->maxOccurs * max);
14511 } else {
14512 /* <all> and <sequence> */
14513 int sum = 0, cur;
14514 xmlSchemaParticlePtr part =
14515 (xmlSchemaParticlePtr) particle->children->children;
14516
14517 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14518 if (part->children == NULL)
14519 continue;
14520 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14521 (part->children->type == XML_SCHEMA_TYPE_ANY))
14522 cur = part->maxOccurs;
14523 else
14524 cur = xmlSchemaGetParticleTotalRangeMax(part);
14525 if (cur == UNBOUNDED)
14526 return (UNBOUNDED);
14527 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14528 return (UNBOUNDED);
14529 sum += cur;
14530 }
14531 /* TODO: Handle overflows? */
14532 return (particle->maxOccurs * sum);
14533 }
14534}
14535
14536/**
14537 * xmlSchemaIsParticleEmptiable:
14538 * @particle: the particle
14539 *
14540 * Schema Component Constraint: Particle Emptiable
14541 * Checks whether the given particle is emptiable.
14542 *
14543 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014544 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014545static int
14546xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14547{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014548 /*
14549 * SPEC (1) "Its {min occurs} is 0."
14550 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 if ((particle == NULL) || (particle->minOccurs == 0) ||
14552 (particle->children == NULL))
14553 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014554 /*
14555 * SPEC (2) "Its {term} is a group and the minimum part of the
14556 * effective total range of that group, [...] is 0."
14557 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014558 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014559 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014560 return (1);
14561 }
14562 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014563}
14564
14565/**
14566 * xmlSchemaCheckCOSSTDerivedOK:
14567 * @type: the derived simple type definition
14568 * @baseType: the base type definition
14569 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014570 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014571 * Type Derivation OK (Simple) (cos-st-derived-OK)
14572 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014573 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014574 * derived from @baseType.
14575 *
14576 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014577 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014578static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014579xmlSchemaCheckCOSSTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
14580 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014581 xmlSchemaTypePtr baseType,
14582 int subset)
14583{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014584 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014585 * 1 They are the same type definition.
14586 * TODO: The identy check might have to be more complex than this.
14587 */
14588 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014589 return (0);
14590 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014591 * 2.1 restriction is not in the subset, or in the {final}
14592 * of its own {base type definition};
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014593 * TODO: Revise this, it looks strange.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014594 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014595 if (WXS_IS_TYPE_NOT_FIXED(type))
14596 if (xmlSchemaTypeFixup(type, ctxt) == -1)
14597 return(-1);
14598 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14599 if (xmlSchemaTypeFixup(baseType, ctxt) == -1)
14600 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014601 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014602 (xmlSchemaTypeFinalContains(type->baseType,
14603 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14604 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014605 }
14606 /* 2.2 */
14607 if (type->baseType == baseType) {
14608 /*
14609 * 2.2.1 D's ·base type definition· is B.
14610 */
14611 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014612 }
14613 /*
14614 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14615 * and is validly derived from B given the subset, as defined by this
14616 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014617 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014618 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14619 (xmlSchemaCheckCOSSTDerivedOK(ctxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014620 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014621 return (0);
14622 }
14623 /*
14624 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 * definition·.
14626 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014627 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14628 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014629 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014630 }
14631 /*
14632 * 2.2.4 B's {variety} is union and D is validly derived from a type
14633 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014634 * defined by this constraint.
14635 *
14636 * NOTE: This seems not to involve built-in types, since there is no
14637 * built-in Union Simple Type.
14638 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014639 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014640 xmlSchemaTypeLinkPtr cur;
14641
14642 cur = baseType->memberTypes;
14643 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014644 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14645 if (xmlSchemaTypeFixup(cur->type, ctxt) == -1)
14646 return(-1);
14647 if (xmlSchemaCheckCOSSTDerivedOK(ctxt,
14648 type, cur->type, subset) == 0)
14649 {
14650 /*
14651 * It just has to be validly derived from at least one
14652 * member-type.
14653 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014654 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014655 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014656 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014657 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014659 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14660}
14661
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014662/**
14663 * xmlSchemaCheckTypeDefCircularInternal:
14664 * @pctxt: the schema parser context
14665 * @ctxtType: the type definition
14666 * @ancestor: an ancestor of @ctxtType
14667 *
14668 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014669 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014670 *
14671 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14672 * circular, 0 otherwise.
14673 */
14674static int
14675xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14676 xmlSchemaTypePtr ctxtType,
14677 xmlSchemaTypePtr ancestor)
14678{
14679 int ret;
14680
14681 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14682 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014683
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014684 if (ctxtType == ancestor) {
14685 xmlSchemaPCustomErr(pctxt,
14686 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014687 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014688 "The definition is circular", NULL);
14689 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14690 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014691 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14692 /*
14693 * Avoid inifinite recursion on circular types not yet checked.
14694 */
14695 return (0);
14696 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014697 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14698 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14699 ancestor->baseType);
14700 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14701 return (ret);
14702}
14703
14704/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014705 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706 * @item: the complex/simple type definition
14707 * @ctxt: the parser context
14708 * @name: the name
14709 *
14710 * Checks for circular type definitions.
14711 */
14712static void
14713xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014714 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014715{
14716 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014717 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14718 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014719 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014720 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14721 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014722}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014723
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014724/*
14725* Simple Type Definition Representation OK (src-simple-type) 4
14726*
14727* "4 Circular union type definition is disallowed. That is, if the
14728* <union> alternative is chosen, there must not be any entries in the
14729* memberTypes [attribute] at any depth which resolve to the component
14730* corresponding to the <simpleType>."
14731*
14732* Note that this should work on the *representation* of a component,
14733* thus assumes any union types in the member types not being yet
14734* substituted. At this stage we need the variety of the types
14735* to be already computed.
14736*/
14737static int
14738xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14739 xmlSchemaTypePtr ctxType,
14740 xmlSchemaTypeLinkPtr members)
14741{
14742 xmlSchemaTypeLinkPtr member;
14743 xmlSchemaTypePtr memberType;
14744
14745 member = members;
14746 while (member != NULL) {
14747 memberType = member->type;
14748 while ((memberType != NULL) &&
14749 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14750 if (memberType == ctxType) {
14751 xmlSchemaPCustomErr(pctxt,
14752 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014753 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014754 "The union type definition is circular", NULL);
14755 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14756 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014757 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014758 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14759 {
14760 int res;
14761 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14762 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14763 ctxType,
14764 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14765 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14766 if (res != 0)
14767 return(res);
14768 }
14769 memberType = memberType->baseType;
14770 }
14771 member = member->next;
14772 }
14773 return(0);
14774}
14775
14776static int
14777xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14778 xmlSchemaTypePtr type)
14779{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014780 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014781 return(0);
14782 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14783 type->memberTypes));
14784}
14785
Daniel Veillard01fa6152004-06-29 17:04:39 +000014786/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014787 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014788 * @item: the complex/simple type definition
14789 * @ctxt: the parser context
14790 * @name: the name
14791 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014792 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014793 */
14794static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014795xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014796 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014797{
14798 if (typeDef == NULL)
14799 return;
14800
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014801 /*
14802 * Resolve the base type.
14803 */
14804 if (typeDef->baseType == NULL) {
14805 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14806 typeDef->base, typeDef->baseNs);
14807 if (typeDef->baseType == NULL) {
14808 xmlSchemaPResCompAttrErr(ctxt,
14809 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014810 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014811 "base", typeDef->base, typeDef->baseNs,
14812 XML_SCHEMA_TYPE_SIMPLE, NULL);
14813 return;
14814 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014815 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014816 if (WXS_IS_SIMPLE(typeDef)) {
14817 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014818 /*
14819 * Resolve the memberTypes.
14820 */
14821 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14822 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014823 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014824 /*
14825 * Resolve the itemType.
14826 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014827 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14828
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014830 typeDef->base, typeDef->baseNs);
14831
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014832 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014833 (! WXS_IS_SIMPLE(typeDef->subtypes)))
14834 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014835 typeDef->subtypes = NULL;
14836 xmlSchemaPResCompAttrErr(ctxt,
14837 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014838 WXS_BASIC_CAST typeDef, typeDef->node,
14839 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014840 XML_SCHEMA_TYPE_SIMPLE, NULL);
14841 }
14842 }
14843 return;
14844 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014845 }
14846 /*
14847 * The ball of letters below means, that if we have a particle
14848 * which has a QName-helper component as its {term}, we want
14849 * to resolve it...
14850 */
14851 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14852 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14853 XML_SCHEMA_TYPE_PARTICLE) &&
14854 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14855 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14856 XML_SCHEMA_EXTRA_QNAMEREF))
14857 {
14858 xmlSchemaQNameRefPtr ref =
14859 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14860 xmlSchemaModelGroupDefPtr groupDef;
14861
14862 /*
14863 * URGENT TODO: Test this.
14864 */
14865 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14866 /*
14867 * Resolve the MG definition reference.
14868 */
14869 groupDef =
14870 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14871 ref->itemType, ref->name, ref->targetNamespace);
14872 if (groupDef == NULL) {
14873 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14874 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14875 "ref", ref->name, ref->targetNamespace, ref->itemType,
14876 NULL);
14877 /* Remove the particle. */
14878 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14879 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14880 /* Remove the particle. */
14881 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14882 else {
14883 /*
14884 * Assign the MG definition's {model group} to the
14885 * particle's {term}.
14886 */
14887 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14888
14889 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
14890 /*
14891 * SPEC cos-all-limited (1.2)
14892 * "1.2 the {term} property of a particle with
14893 * {max occurs}=1 which is part of a pair which constitutes
14894 * the {content type} of a complex type definition."
14895 */
14896 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
14897 xmlSchemaCustomErr(ACTXT_CAST ctxt,
14898 /* TODO: error code */
14899 XML_SCHEMAP_COS_ALL_LIMITED,
14900 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
14901 "The particle's {max occurs} must be 1, since the "
14902 "reference resolves to an 'all' model group",
14903 NULL, NULL);
14904 }
14905 }
14906 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014907 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014908}
14909
14910
14911
14912/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014913 * xmlSchemaCheckSTPropsCorrect:
14914 * @ctxt: the schema parser context
14915 * @type: the simple type definition
14916 *
14917 * Checks st-props-correct.
14918 *
14919 * Returns 0 if the properties are correct,
14920 * if not, a positive error code and -1 on internal
14921 * errors.
14922 */
14923static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014924xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014925 xmlSchemaTypePtr type)
14926{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014927 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014928 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014929
Daniel Veillardc0826a72004-08-10 14:17:33 +000014930 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014931 /*
14932 * Schema Component Constraint: Simple Type Definition Properties Correct
14933 *
14934 * NOTE: This is somehow redundant, since we actually built a simple type
14935 * to have all the needed information; this acts as an self test.
14936 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014937 /* Base type: If the datatype has been ·derived· by ·restriction·
14938 * then the Simple Type Definition component from which it is ·derived·,
14939 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014940 */
14941 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014942 /*
14943 * TODO: Think about: "modulo the impact of Missing
14944 * Sub-components (§5.3)."
14945 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014946 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014947 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014948 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014949 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014950 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014951
Daniel Veillard01fa6152004-06-29 17:04:39 +000014952 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014953 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014954 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014955 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014956 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014957 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014958 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014959 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014960 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14961 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014962 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014963 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014964 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014965 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014966 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014967 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014968 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014969 "the simple ur-type definition as base type, not '%s'",
14970 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014971 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014972 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14973 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014974 /*
14975 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014976 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014977 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
14978 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014979 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014980 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014981 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014982 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014983 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14984 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014985 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014986
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014987 /*
14988 * 3 The {final} of the {base type definition} must not contain restriction.
14989 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014990 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014991 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
14992 xmlSchemaPCustomErr(ctxt,
14993 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014994 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014995 "The 'final' of its base type '%s' must not contain "
14996 "'restriction'",
14997 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014998 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014999 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015000 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015001
15002 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015003 * 2 All simple type definitions must be derived ultimately from the ·simple
15004 * ur-type definition (so· circular definitions are disallowed). That is, it
15005 * must be possible to reach a built-in primitive datatype or the ·simple
15006 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015007 *
15008 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015009 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015010 return (0);
15011}
15012
15013/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015014 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015015 * @ctxt: the schema parser context
15016 * @type: the simple type definition
15017 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015018 * Schema Component Constraint:
15019 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15020
15021 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015022 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015023 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015024 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015025 * a positive error code otherwise.
15026 */
15027static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015028xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015029 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015030{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015031 xmlChar *str = NULL;
15032
Daniel Veillard01fa6152004-06-29 17:04:39 +000015033 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015034 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15035 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015036 return (-1);
15037 }
15038
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015039 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015040 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015041 /*
15042 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015044 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015045 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015046 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015047 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015048 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015049 "The base type '%s' is not an atomic simple type",
15050 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015051 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015052 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15053 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015054 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015055 * restriction.
15056 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015057 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015058 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015059 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015060 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015061 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015062 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015063 "The final of its base type '%s' must not contain 'restriction'",
15064 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015065 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015066 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015068
15069 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015070 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015071 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015072 * Primitive datatypes.
15073 */
15074 if (type->facets != NULL) {
15075 xmlSchemaFacetPtr facet;
15076 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015077
Daniel Veillard01fa6152004-06-29 17:04:39 +000015078 primitive = xmlSchemaGetPrimitiveType(type);
15079 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015080 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15081 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015082 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015084 facet = type->facets;
15085 do {
15086 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015087 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015088 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015089 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015090 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015091 }
15092 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015093 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015094 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015095 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015096 }
15097 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015098 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15099 * of the {base type definition} (call this BF),then the DF's {value}
15100 * must be a valid restriction of BF's {value} as defined in
15101 * [XML Schemas: Datatypes]."
15102 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015103 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015104 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015105 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015106 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015107 xmlSchemaTypePtr itemType = NULL;
15108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015109 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015110 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015111 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15112 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015113 return (-1);
15114 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015115 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015116 xmlSchemaTypeFixup(itemType, pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015117 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015118 * 2.1 The {item type definition} must have a {variety} of atomic or
15119 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015120 * must be atomic).
15121 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015122 if ((! WXS_IS_ATOMIC(itemType)) &&
15123 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015124 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015125 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015126 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015127 "The item type '%s' does not have a variety of atomic or union",
15128 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015130 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015131 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015132 xmlSchemaTypeLinkPtr member;
15133
15134 member = itemType->memberTypes;
15135 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015136 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015137 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015138 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015139 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015140 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015141 "member type '%s' of this item type is not atomic",
15142 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015143 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015144 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15145 }
15146 member = member->next;
15147 }
15148 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015149
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015150 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015151 xmlSchemaFacetPtr facet;
15152 /*
15153 * This is the case if we have: <simpleType><list ..
15154 */
15155 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015156 * 2.3.1
15157 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015158 * contain list.
15159 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015160 if (xmlSchemaTypeFinalContains(itemType,
15161 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15162 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015163 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015164 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015165 "The final of its item type '%s' must not contain 'list'",
15166 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015167 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015168 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15169 }
15170 /*
15171 * 2.3.1.2 The {facets} must only contain the whiteSpace
15172 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015173 * OPTIMIZE TODO: the S4S already disallows any facet
15174 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015175 */
15176 if (type->facets != NULL) {
15177 facet = type->facets;
15178 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015179 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015181 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015182 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015183 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15184 }
15185 facet = facet->next;
15186 } while (facet != NULL);
15187 }
15188 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015189 * MAYBE TODO: (Hmm, not really) Datatypes states:
15190 * A ·list· datatype can be ·derived· from an ·atomic· datatype
15191 * whose ·lexical space· allows space (such as string or anyURI)or
15192 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000015193 * ·lexical space· allows space.
15194 */
15195 } else {
15196 /*
15197 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015198 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015199 */
15200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015201 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015202 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15203 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015204 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015205 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015206 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015207 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015208 "The base type '%s' must be a list type",
15209 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015210 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015211 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15212 }
15213 /*
15214 * 2.3.2.2 The {final} of the {base type definition} must not
15215 * contain restriction.
15216 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015217 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015218 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015219 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015220 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015221 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015222 "The 'final' of the base type '%s' must not contain 'restriction'",
15223 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015224 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015225 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15226 }
15227 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015228 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015229 * from the {base type definition}'s {item type definition} given
15230 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
15231 */
15232 {
15233 xmlSchemaTypePtr baseItemType;
15234
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015235 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015236 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015237 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15238 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015239 return (-1);
15240 }
15241 if ((itemType != baseItemType) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015242 (xmlSchemaCheckCOSSTDerivedOK(pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015243 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015244 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015245 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015246 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015247 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015248 "The item type '%s' is not validly derived from "
15249 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015250 xmlSchemaGetComponentQName(&str, itemType),
15251 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15252 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015253
15254 FREE_AND_NULL(str)
15255 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015256 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015257 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15258 }
15259 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015260
Daniel Veillard01fa6152004-06-29 17:04:39 +000015261 if (type->facets != NULL) {
15262 xmlSchemaFacetPtr facet;
15263 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015264 /*
15265 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015266 * and enumeration facet components are allowed among the {facets}.
15267 */
15268 facet = type->facets;
15269 do {
15270 switch (facet->type) {
15271 case XML_SCHEMA_FACET_LENGTH:
15272 case XML_SCHEMA_FACET_MINLENGTH:
15273 case XML_SCHEMA_FACET_MAXLENGTH:
15274 case XML_SCHEMA_FACET_WHITESPACE:
15275 /*
15276 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015277 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015278 */
15279 case XML_SCHEMA_FACET_PATTERN:
15280 case XML_SCHEMA_FACET_ENUMERATION:
15281 break;
15282 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015283 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015284 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015285 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015286 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015287 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015288 * invalid facets.
15289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015290 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015291 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015292 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015293 facet = facet->next;
15294 } while (facet != NULL);
15295 if (ok == 0)
15296 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15297 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015298 * SPEC (2.3.2.5) (same as 1.3.2)
15299 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015300 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015301 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015302 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015303 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015304 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015305 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015306 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015308 * atomic or list.
15309 */
15310 xmlSchemaTypeLinkPtr member;
15311
15312 member = type->memberTypes;
15313 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015314 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015315 xmlSchemaTypeFixup(member->type, pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015316
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015317 if ((! WXS_IS_ATOMIC(member->type)) &&
15318 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015319 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015320 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015321 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015322 "The member type '%s' is neither an atomic, nor a list type",
15323 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015324 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015325 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15326 }
15327 member = member->next;
15328 }
15329 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 * 3.3.1 If the {base type definition} is the ·simple ur-type
15331 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000015332 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015333 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015334 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015335 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015336 * {final} which does not contain union.
15337 */
15338 member = type->memberTypes;
15339 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015340 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015341 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015342 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015343 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015344 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015345 "The 'final' of member type '%s' contains 'union'",
15346 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015348 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15349 }
15350 member = member->next;
15351 }
15352 /*
15353 * 3.3.1.2 The {facets} must be empty.
15354 */
15355 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015356 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015357 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015358 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015359 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015360 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15361 }
15362 } else {
15363 /*
15364 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015365 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015366 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015367 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015368 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015369 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015370 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015371 "The base type '%s' is not a union type",
15372 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015373 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015374 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15375 }
15376 /*
15377 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15378 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015379 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015380 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015381 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015382 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015383 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015384 "The 'final' of its base type '%s' must not contain 'restriction'",
15385 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015387 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15388 }
15389 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015390 * 3.3.2.3 The {member type definitions}, in order, must be validly
15391 * derived from the corresponding type definitions in the {base
15392 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015393 * as defined in Type Derivation OK (Simple) (§3.14.6).
15394 */
15395 {
15396 xmlSchemaTypeLinkPtr baseMember;
15397
15398 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015399 * OPTIMIZE: if the type is restricting, it has no local defined
15400 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015401 * thus a check for equality can be skipped.
15402 */
15403 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015404 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015405 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015406 * types of it's base type. This check seems not necessary with
15407 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015408 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015409 */
15410 if (type->memberTypes != NULL) {
15411 member = type->memberTypes;
15412 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015413 if ((member == NULL) && (baseMember != NULL)) {
15414 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15415 "different number of member types in base");
15416 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015417 while (member != NULL) {
15418 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015419 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15420 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015421 }
15422 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015423 (xmlSchemaCheckCOSSTDerivedOK(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015424 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015425 xmlChar *strBMT = NULL, *strBT = NULL;
15426
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015427 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015428 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015429 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015430 "The member type %s is not validly "
15431 "derived from its corresponding member "
15432 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015433 xmlSchemaGetComponentQName(&str, member->type),
15434 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15435 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015436 FREE_AND_NULL(str)
15437 FREE_AND_NULL(strBMT)
15438 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015439 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015440 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015441 member = member->next;
15442 baseMember = baseMember->next;
15443 }
15444 }
15445 }
15446 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015447 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015448 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015449 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015450 if (type->facets != NULL) {
15451 xmlSchemaFacetPtr facet;
15452 int ok = 1;
15453
15454 facet = type->facets;
15455 do {
15456 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15457 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015458 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015459 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015460 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015461 ok = 0;
15462 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015463 facet = facet->next;
15464 } while (facet != NULL);
15465 if (ok == 0)
15466 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015467
Daniel Veillard01fa6152004-06-29 17:04:39 +000015468 }
15469 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015470 * SPEC (3.3.2.5) (same as 1.3.2)
15471 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015472 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015473 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015474 */
15475 }
15476 }
15477
15478 return (0);
15479}
15480
15481/**
15482 * xmlSchemaCheckSRCSimpleType:
15483 * @ctxt: the schema parser context
15484 * @type: the simple type definition
15485 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015486 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015487 *
15488 * Returns 0 if the constraints are satisfied,
15489 * if not a positive error code and -1 on internal
15490 * errors.
15491 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015492#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015493static int
15494xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15495 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015496{
15497 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015498 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015499 * must satisfy the conditions set out in Constraints on Simple Type
15500 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015501 */
15502 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015503 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015504 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015505 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015506 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015507 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015508 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015509 /*
15510 *
15511 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015512 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015513 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015514 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015515 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015516 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015517 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015518 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015519 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015520 /*
15521 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015522 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015523 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015524 return (0);
15525}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015526#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015527
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015528static int
15529xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15530{
15531 if (ctxt->vctxt == NULL) {
15532 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15533 if (ctxt->vctxt == NULL) {
15534 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015535 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015536 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015537 "failed to create a temp. validation context.\n",
15538 NULL, NULL);
15539 return (-1);
15540 }
15541 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015542 xmlSchemaSetValidErrors(ctxt->vctxt,
15543 ctxt->error, ctxt->warning, ctxt->userData);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015544 }
15545 return (0);
15546}
15547
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015548static int
15549xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15550 xmlNodePtr node,
15551 xmlSchemaTypePtr type,
15552 const xmlChar *value,
15553 xmlSchemaValPtr *retVal,
15554 int fireErrors,
15555 int normalize,
15556 int isNormalized);
15557
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015558/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015559 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015560 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015561 * @type: the simple type definition
15562 * @value: the default value
15563 * @node: an optional node (the holder of the value)
15564 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015565 * Schema Component Constraint: Element Default Valid (Immediate)
15566 * (cos-valid-default)
15567 * This will be used by the parser only. For the validator there's
15568 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015569 *
15570 * Returns 0 if the constraints are satisfied,
15571 * if not, a positive error code and -1 on internal
15572 * errors.
15573 */
15574static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015575xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15576 xmlNodePtr node,
15577 xmlSchemaTypePtr type,
15578 const xmlChar *value,
15579 xmlSchemaValPtr *val)
15580{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015581 int ret = 0;
15582
15583 /*
15584 * cos-valid-default:
15585 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015586 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015587 * definition the appropriate case among the following must be true:
15588 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015589 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015590 /*
15591 * Complex type.
15592 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015593 * SPEC (2.1) "its {content type} must be a simple type definition
15594 * or mixed."
15595 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015596 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015597 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015598 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015599 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15600 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015601 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015602 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015603 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015604 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015605 "For a string to be a valid default, the type definition "
15606 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015607 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015608 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015610 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015611 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015612 * 1 If the type definition is a simple type definition, then the string
15613 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015614 * Valid (§3.14.4).
15615 *
15616 * AND
15617 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015618 * 2.2.1 If the {content type} is a simple type definition, then the
15619 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015620 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015621 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015622 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015623 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015624 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015625 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015626 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015627 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015628 else
15629 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015631 if (ret < 0) {
15632 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15633 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015634 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015635
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015636 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015637}
15638
15639/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015640 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015641 * @ctxt: the schema parser context
15642 * @type: the complex type definition
15643 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015644 *.(4.6) Constraints on Complex Type Definition Schema Components
15645 * Schema Component Constraint:
15646 * Complex Type Definition Properties Correct (ct-props-correct)
15647 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015648 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015649 * Returns 0 if the constraints are satisfied, a positive
15650 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000015651 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015652static int
15653xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15654 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015655{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015656 /*
15657 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15658 *
15659 * SPEC (1) "The values of the properties of a complex type definition must
15660 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015661 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015662 * Sub-components (§5.3)."
15663 */
15664 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015665 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015666 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015667 /*
15668 * SPEC (2) "If the {base type definition} is a simple type definition,
15669 * the {derivation method} must be extension."
15670 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015671 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015672 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015673 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015674 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015675 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015676 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015678 /*
15679 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15680 * definition·. That is, it must be possible to reach the ·ur-type
15681 * definition by repeatedly following the {base type definition}."
15682 *
15683 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015684 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015685 /*
15686 * NOTE that (4) and (5) need the following:
15687 * - attribute uses need to be already inherited (apply attr. prohibitions)
15688 * - attribute group references need to be expanded already
15689 * - simple types need to be typefixed already
15690 */
15691 if (type->attrUses &&
15692 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15693 {
15694 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15695 xmlSchemaAttributeUsePtr use, tmp;
15696 int i, j, hasId = 0;
15697
15698 for (i = uses->nbItems -1; i >= 0; i--) {
15699 use = uses->items[i];
15700
15701 /*
15702 * SPEC ct-props-correct
15703 * (4) "Two distinct attribute declarations in the
15704 * {attribute uses} must not have identical {name}s and
15705 * {target namespace}s."
15706 */
15707 if (i > 0) {
15708 for (j = i -1; j >= 0; j--) {
15709 tmp = uses->items[j];
15710 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15711 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15712 (WXS_ATTRUSE_DECL_TNS(use) ==
15713 WXS_ATTRUSE_DECL_TNS(tmp)))
15714 {
15715 xmlChar *str = NULL;
15716
15717 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15718 XML_SCHEMAP_AG_PROPS_CORRECT,
15719 NULL, WXS_BASIC_CAST type,
15720 "Duplicate %s",
15721 xmlSchemaGetComponentDesignation(&str, use),
15722 NULL);
15723 FREE_AND_NULL(str);
15724 /*
15725 * Remove the duplicate.
15726 */
15727 if (xmlSchemaItemListRemove(uses, i) == -1)
15728 goto exit_failure;
15729 goto next_use;
15730 }
15731 }
15732 }
15733 /*
15734 * SPEC ct-props-correct
15735 * (5) "Two distinct attribute declarations in the
15736 * {attribute uses} must not have {type definition}s which
15737 * are or are derived from ID."
15738 */
15739 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15740 if (xmlSchemaIsDerivedFromBuiltInType(
15741 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15742 {
15743 if (hasId) {
15744 xmlChar *str = NULL;
15745
15746 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15747 XML_SCHEMAP_AG_PROPS_CORRECT,
15748 NULL, WXS_BASIC_CAST type,
15749 "There must not exist more than one attribute "
15750 "declaration of type 'xs:ID' "
15751 "(or derived from 'xs:ID'). The %s violates this "
15752 "constraint",
15753 xmlSchemaGetComponentDesignation(&str, use),
15754 NULL);
15755 FREE_AND_NULL(str);
15756 if (xmlSchemaItemListRemove(uses, i) == -1)
15757 goto exit_failure;
15758 }
15759
15760 hasId = 1;
15761 }
15762 }
15763next_use: {}
15764 }
15765 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015766 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015767exit_failure:
15768 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000015769}
15770
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015771static int
15772xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15773 xmlSchemaTypePtr typeB)
15774{
15775 /*
15776 * TODO: This should implement component-identity
15777 * in the future.
15778 */
15779 if ((typeA == NULL) || (typeB == NULL))
15780 return (0);
15781 return (typeA == typeB);
15782}
15783
15784/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015785 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015786 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015787 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015788 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015789 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015790 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015791 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015792 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15793 *
15794 * STATUS: completed
15795 *
15796 * Returns 0 if the constraints are satisfied, or 1
15797 * if not.
15798 */
15799static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015800xmlSchemaCheckCOSCTDerivedOK(xmlSchemaParserCtxtPtr ctxt,
15801 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015802 xmlSchemaTypePtr baseType,
15803 int set)
15804{
15805 int equal = xmlSchemaAreEqualTypes(type, baseType);
15806 /* TODO: Error codes. */
15807 /*
15808 * SPEC "For a complex type definition (call it D, for derived)
15809 * to be validly derived from a type definition (call this
15810 * B, for base) given a subset of {extension, restriction}
15811 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015812 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015813 if (! equal) {
15814 /*
15815 * SPEC (1) "If B and D are not the same type definition, then the
15816 * {derivation method} of D must not be in the subset."
15817 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015818 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15819 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015820 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015821 } else {
15822 /*
15823 * SPEC (2.1) "B and D must be the same type definition."
15824 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015825 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015826 }
15827 /*
15828 * SPEC (2.2) "B must be D's {base type definition}."
15829 */
15830 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015831 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015832 /*
15833 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15834 * definition·."
15835 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015836 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015837 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015838
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015839 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015840 /*
15841 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15842 * must be validly derived from B given the subset as defined by this
15843 * constraint."
15844 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015845 return (xmlSchemaCheckCOSCTDerivedOK(ctxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015846 baseType, set));
15847 } else {
15848 /*
15849 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15850 * must be validly derived from B given the subset as defined in Type
15851 * Derivation OK (Simple) (§3.14.6).
15852 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015853 return (xmlSchemaCheckCOSSTDerivedOK(ctxt, type->baseType,
15854 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015855 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015856}
15857
15858/**
15859 * xmlSchemaCheckCOSDerivedOK:
15860 * @type: the derived simple type definition
15861 * @baseType: the base type definition
15862 *
15863 * Calls:
15864 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015865 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015866 * Checks wheter @type can be validly derived from @baseType.
15867 *
15868 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015870static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015871xmlSchemaCheckCOSDerivedOK(xmlSchemaParserCtxtPtr ctxt,
15872 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015873 xmlSchemaTypePtr baseType,
15874 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015875{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015876 if (WXS_IS_SIMPLE(type))
15877 return (xmlSchemaCheckCOSSTDerivedOK(ctxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015878 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015879 return (xmlSchemaCheckCOSCTDerivedOK(ctxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015880}
15881
William M. Brack2f2a6632004-08-20 23:09:47 +000015882/**
15883 * xmlSchemaCheckCOSCTExtends:
15884 * @ctxt: the schema parser context
15885 * @type: the complex type definition
15886 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015887 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015888 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015889 * Derivation Valid (Extension) (cos-ct-extends)
15890 *
15891 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015892 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015893 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015894 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000015895 *
15896 * Returns 0 if the constraints are satisfied, a positive
15897 * error code if not and -1 if an internal error occured.
15898 */
15899static int
15900xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15901 xmlSchemaTypePtr type)
15902{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015903 xmlSchemaTypePtr base = type->baseType;
15904 /*
15905 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15906 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015907 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015908 /*
15909 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015910 * then all of the following must be true:"
15911 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015912 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015913 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015914 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015915 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015916 */
15917 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15918 xmlSchemaPCustomErr(ctxt,
15919 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015920 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015921 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015922 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015923 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15924 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015925
15926 /*
15927 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
15928 * since they are automatically satisfied through the
15929 * inheriting mechanism.
15930 * Note that even if redefining components, the inheriting mechanism
15931 * is used.
15932 */
15933#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000015934 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015935 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015936 * uses}
15937 * of the complex type definition itself, that is, for every attribute
15938 * use in the {attribute uses} of the {base type definition}, there
15939 * must be an attribute use in the {attribute uses} of the complex
15940 * type definition itself whose {attribute declaration} has the same
15941 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015942 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000015943 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015944 if (base->attrUses != NULL) {
15945 int i, j, found;
15946 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000015947
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015948 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
15949 buse = (WXS_LIST_CAST base->attrUses)->items[i];
15950 found = 0;
15951 if (type->attrUses != NULL) {
15952 use = (WXS_LIST_CAST type->attrUses)->items[j];
15953 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
15954 {
15955 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15956 WXS_ATTRUSE_DECL_NAME(buse)) &&
15957 (WXS_ATTRUSE_DECL_TNS(use) ==
15958 WXS_ATTRUSE_DECL_TNS(buse)) &&
15959 (WXS_ATTRUSE_TYPEDEF(use) ==
15960 WXS_ATTRUSE_TYPEDEF(buse))
15961 {
15962 found = 1;
15963 break;
15964 }
15965 }
15966 }
15967 if (! found) {
15968 xmlChar *str = NULL;
15969
15970 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15971 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
15972 NULL, WXS_BASIC_CAST type,
15973 /*
15974 * TODO: The report does not indicate that also the
15975 * type needs to be the same.
15976 */
15977 "This type is missing a matching correspondent "
15978 "for its {base type}'s %s in its {attribute uses}",
15979 xmlSchemaGetComponentDesignation(&str,
15980 buse->children),
15981 NULL);
15982 FREE_AND_NULL(str)
15983 }
15984 }
15985 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015986 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015987 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
15988 * definition must also have one, and the base type definition's
15989 * {attribute wildcard}'s {namespace constraint} must be a subset
15990 * of the complex type definition's {attribute wildcard}'s {namespace
15991 * constraint}, as defined by Wildcard Subset (§3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015992 */
15993
15994 /*
15995 * MAYBE TODO: Enable if ever needed. But this will be needed only
15996 * if created the type via a schema construction API.
15997 */
15998 if (base->attributeWildcard != NULL) {
15999 if (type->attributeWilcard == NULL) {
16000 xmlChar *str = NULL;
16001
16002 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16003 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16004 NULL, type,
16005 "The base %s has an attribute wildcard, "
16006 "but this type is missing an attribute wildcard",
16007 xmlSchemaGetComponentDesignation(&str, base));
16008 FREE_AND_NULL(str)
16009
16010 } else if (xmlSchemaCheckCOSNSSubset(
16011 base->attributeWildcard, type->attributeWildcard))
16012 {
16013 xmlChar *str = NULL;
16014
16015 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16016 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16017 NULL, type,
16018 "The attribute wildcard is not a valid "
16019 "superset of the one in the base %s",
16020 xmlSchemaGetComponentDesignation(&str, base));
16021 FREE_AND_NULL(str)
16022 }
16023 }
16024#endif
16025 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016026 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016027 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016028 if ((type->contentTypeDef != NULL) &&
16029 (type->contentTypeDef == base->contentTypeDef)) {
16030 /*
16031 * SPEC (1.4.1) "The {content type} of the {base type definition}
16032 * and the {content type} of the complex type definition itself
16033 * must be the same simple type definition"
16034 * PASS
16035 */
16036 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16037 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16038 /*
16039 * SPEC (1.4.2) "The {content type} of both the {base type
16040 * definition} and the complex type definition itself must
16041 * be empty."
16042 * PASS
16043 */
16044 } else {
16045 /*
16046 * SPEC (1.4.3) "All of the following must be true:"
16047 */
16048 if (type->subtypes == NULL) {
16049 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016050 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016051 * definition itself must specify a particle.
16052 */
16053 xmlSchemaPCustomErr(ctxt,
16054 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016055 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016056 "The content type must specify a particle", NULL);
16057 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16058 }
16059 /*
16060 * SPEC (1.4.3.2) "One of the following must be true:"
16061 */
16062 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16063 /*
16064 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16065 * definition} must be empty.
16066 * PASS
16067 */
16068 } else {
16069 /*
16070 * SPEC (1.4.3.2.2) "All of the following must be true:"
16071 */
16072 if ((type->contentType != base->contentType) ||
16073 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16074 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16075 /*
16076 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16077 * or both must be element-only."
16078 */
16079 xmlSchemaPCustomErr(ctxt,
16080 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016081 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016082 "The content type of both, the type and its base "
16083 "type, must either 'mixed' or 'element-only'", NULL);
16084 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016085 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016086 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016087 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016088 * complex type definition must be a ·valid extension·
16089 * of the {base type definition}'s particle, as defined
16090 * in Particle Valid (Extension) (§3.9.6)."
16091 *
16092 * NOTE that we won't check "Particle Valid (Extension)",
16093 * since it is ensured by the derivation process in
16094 * xmlSchemaTypeFixup(). We need to implement this when heading
16095 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016096 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016097 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016098 }
16099 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016100 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016101 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016102 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016103 } else {
16104 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016105 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016106 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016107 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016108 if (type->contentTypeDef != base) {
16109 /*
16110 * SPEC (2.1) "The {content type} must be the same simple type
16111 * definition."
16112 */
16113 xmlSchemaPCustomErr(ctxt,
16114 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016115 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116 "The content type must be the simple base type", NULL);
16117 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16118 }
16119 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16120 /*
16121 * SPEC (2.2) "The {final} of the {base type definition} must not
16122 * contain extension"
16123 * NOTE that this is the same as (1.1).
16124 */
16125 xmlSchemaPCustomErr(ctxt,
16126 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016127 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016128 "The 'final' of the base type definition "
16129 "contains 'extension'", NULL);
16130 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016131 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016132 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016133 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016134}
16135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016136/**
16137 * xmlSchemaCheckDerivationOKRestriction:
16138 * @ctxt: the schema parser context
16139 * @type: the complex type definition
16140 *
16141 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016142 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016143 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16144 *
16145 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016146 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016147 * (5.4.2) ???
16148 *
16149 * ATTENTION:
16150 * In XML Schema 1.1 this will be:
16151 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016152 *
16153 * Returns 0 if the constraints are satisfied, a positive
16154 * error code if not and -1 if an internal error occured.
16155 */
16156static int
16157xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16158 xmlSchemaTypePtr type)
16159{
16160 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016161
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016162 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016163 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016165 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016167 if (! WXS_IS_COMPLEX(base)) {
16168 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16169 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16170 type->node, WXS_BASIC_CAST type,
16171 "The base type must be a complex type", NULL, NULL);
16172 return(ctxt->err);
16173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16175 /*
16176 * SPEC (1) "The {base type definition} must be a complex type
16177 * definition whose {final} does not contain restriction."
16178 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016179 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16180 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16181 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016183 "contains 'restriction'", NULL, NULL);
16184 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016185 }
16186 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016187 * SPEC (2), (3) and (4)
16188 * Those are handled in a separate function, since the
16189 * same constraints are needed for redefinition of
16190 * attribute groups as well.
16191 */
16192 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16193 XML_SCHEMA_ACTION_DERIVE,
16194 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16195 type->attrUses, base->attrUses,
16196 type->attributeWildcard,
16197 base->attributeWildcard) == -1)
16198 {
16199 return(-1);
16200 }
16201 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016202 * SPEC (5) "One of the following must be true:"
16203 */
16204 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16205 /*
16206 * SPEC (5.1) "The {base type definition} must be the
16207 * ·ur-type definition·."
16208 * PASS
16209 */
16210 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16211 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16212 /*
16213 * SPEC (5.2.1) "The {content type} of the complex type definition
16214 * must be a simple type definition"
16215 *
16216 * SPEC (5.2.2) "One of the following must be true:"
16217 */
16218 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016219 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16220 {
16221 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016222 /*
16223 * SPEC (5.2.2.1) "The {content type} of the {base type
16224 * definition} must be a simple type definition from which
16225 * the {content type} is validly derived given the empty
16226 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016227 *
16228 * ATTENTION TODO: This seems not needed if the type implicitely
16229 * derived from the base type.
16230 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016231 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016232 err = xmlSchemaCheckCOSSTDerivedOK(ctxt, type->contentTypeDef,
16233 base->contentTypeDef, 0);
16234 if (err != 0) {
16235 xmlChar *strA = NULL, *strB = NULL;
16236
16237 if (err == -1)
16238 return(-1);
16239 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16240 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16241 NULL, WXS_BASIC_CAST type,
16242 "The {content type} %s is not validly derived from the "
16243 "base type's {content type} %s",
16244 xmlSchemaGetComponentDesignation(&strA,
16245 type->contentTypeDef),
16246 xmlSchemaGetComponentDesignation(&strB,
16247 base->contentTypeDef));
16248 FREE_AND_NULL(strA);
16249 FREE_AND_NULL(strB);
16250 return(ctxt->err);
16251 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16253 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016254 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016255 /*
16256 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16257 * and have a particle which is ·emptiable· as defined in
16258 * Particle Emptiable (§3.9.6)."
16259 * PASS
16260 */
16261 } else {
16262 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016263 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16264 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016265 "The content type of the base type must be either "
16266 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016267 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016268 }
16269 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16270 /*
16271 * SPEC (5.3.1) "The {content type} of the complex type itself must
16272 * be empty"
16273 */
16274 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16275 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016276 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016277 * definition} must also be empty."
16278 * PASS
16279 */
16280 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16281 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16282 xmlSchemaIsParticleEmptiable(
16283 (xmlSchemaParticlePtr) base->subtypes)) {
16284 /*
16285 * SPEC (5.3.2.2) "The {content type} of the {base type
16286 * definition} must be elementOnly or mixed and have a particle
16287 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
16288 * PASS
16289 */
16290 } else {
16291 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016292 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16293 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016294 "The content type of the base type must be either "
16295 "empty or 'mixed' (or 'elements-only') and an emptiable "
16296 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016297 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016298 }
16299 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016300 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016301 /*
16302 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16303 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016304 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016305 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016306 /*
16307 * SPEC (5.4.1.2) "The {content type} of the complex type
16308 * definition itself and of the {base type definition} must be
16309 * mixed"
16310 */
16311 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016312 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16313 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016314 "If the content type is 'mixed', then the content type of the "
16315 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016316 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016317 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016318 /*
16319 * SPEC (5.4.2) "The particle of the complex type definition itself
16320 * must be a ·valid restriction· of the particle of the {content
16321 * type} of the {base type definition} as defined in Particle Valid
16322 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016323 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016324 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016325 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016326 } else {
16327 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016328 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16329 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016331 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016332 }
16333 return (0);
16334}
16335
16336/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016337 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 * @ctxt: the schema parser context
16339 * @type: the complex type definition
16340 *
16341 * (3.4.6) Constraints on Complex Type Definition Schema Components
16342 *
16343 * Returns 0 if the constraints are satisfied, a positive
16344 * error code if not and -1 if an internal error occured.
16345 */
16346static int
16347xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16348 xmlSchemaTypePtr type)
16349{
16350 int ret;
16351 /*
16352 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016353 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016354 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16355 if (ret != 0)
16356 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016357 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16359 else
16360 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16361 return (ret);
16362}
16363
16364/**
16365 * xmlSchemaCheckSRCCT:
16366 * @ctxt: the schema parser context
16367 * @type: the complex type definition
16368 *
16369 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016370 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 * Complex Type Definition Representation OK (src-ct)
16372 *
16373 * Returns 0 if the constraints are satisfied, a positive
16374 * error code if not and -1 if an internal error occured.
16375 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016376static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016377xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016378 xmlSchemaTypePtr type)
16379{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 xmlSchemaTypePtr base;
16381 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016382
16383 /*
16384 * TODO: Adjust the error codes here, as I used
16385 * XML_SCHEMAP_SRC_CT_1 only yet.
16386 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016387 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016388 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016389 /*
16390 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016391 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 * must be a complex type definition;
16393 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016394 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016395 xmlChar *str = NULL;
16396 xmlSchemaPCustomErr(ctxt,
16397 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016398 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016399 "If using <complexContent>, the base type is expected to be "
16400 "a complex type. The base type '%s' is a simple type",
16401 xmlSchemaFormatQName(&str, base->targetNamespace,
16402 base->name));
16403 FREE_AND_NULL(str)
16404 return (XML_SCHEMAP_SRC_CT_1);
16405 }
16406 } else {
16407 /*
16408 * SPEC
16409 * 2 If the <simpleContent> alternative is chosen, all of the
16410 * following must be true:
16411 * 2.1 The type definition ·resolved· to by the ·actual value· of the
16412 * base [attribute] must be one of the following:
16413 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016414 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016415 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016416 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016417 /*
16418 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016419 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016420 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016422 xmlSchemaPCustomErr(ctxt,
16423 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016424 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016425 "If using <simpleContent> and <restriction>, the base "
16426 "type must be a complex type. The base type '%s' is "
16427 "a simple type",
16428 xmlSchemaFormatQName(&str, base->targetNamespace,
16429 base->name));
16430 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016431 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016432 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 } else {
16434 /* Base type is a complex type. */
16435 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16436 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16437 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016438 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016439 * simple type definition;
16440 * PASS
16441 */
16442 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016444 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016445 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016446 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016447 type->name);
16448 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016449 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016450 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016451 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016452
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016454 * 2.1.2 only if the <restriction> alternative is also
16455 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016456 * is mixed and a particle emptiable.
16457 */
16458 if (! xmlSchemaIsParticleEmptiable(
16459 (xmlSchemaParticlePtr) base->subtypes)) {
16460 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016461 } else
16462 /*
16463 * Attention: at this point the <simpleType> child is in
16464 * ->contentTypeDef (put there during parsing).
16465 */
16466 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016467 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016468 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016469 * 2.2 If clause 2.1.2 above is satisfied, then there
16470 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016471 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016472 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016473 /* TODO: Change error code to ..._SRC_CT_2_2. */
16474 xmlSchemaPCustomErr(ctxt,
16475 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016476 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016477 "A <simpleType> is expected among the children "
16478 "of <restriction>, if <simpleContent> is used and "
16479 "the base type '%s' is a complex type",
16480 xmlSchemaFormatQName(&str, base->targetNamespace,
16481 base->name));
16482 FREE_AND_NULL(str)
16483 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016484 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016485 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016486 ret = XML_SCHEMAP_SRC_CT_1;
16487 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016488 }
16489 if (ret > 0) {
16490 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016491 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016492 xmlSchemaPCustomErr(ctxt,
16493 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016494 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016495 "If <simpleContent> and <restriction> is used, the "
16496 "base type must be a simple type or a complex type with "
16497 "mixed content and particle emptiable. The base type "
16498 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016500 base->name));
16501 } else {
16502 xmlSchemaPCustomErr(ctxt,
16503 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016504 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016505 "If <simpleContent> and <extension> is used, the "
16506 "base type must be a simple type. The base type '%s' "
16507 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016508 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016509 base->name));
16510 }
16511 FREE_AND_NULL(str)
16512 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016513 }
16514 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016515 * SPEC (3) "The corresponding complex type definition component must
16516 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016517 * Definition Schema Components (§3.4.6);"
16518 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016519 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016520 /*
16521 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 * above for {attribute wildcard} is satisfied, the intensional
16523 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016524 * Intersection (§3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016525 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016526 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016527 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016528}
William M. Brack2f2a6632004-08-20 23:09:47 +000016529
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016530#ifdef ENABLE_PARTICLE_RESTRICTION
16531/**
16532 * xmlSchemaCheckParticleRangeOK:
16533 * @ctxt: the schema parser context
16534 * @type: the complex type definition
16535 *
16536 * (3.9.6) Constraints on Particle Schema Components
16537 * Schema Component Constraint:
16538 * Occurrence Range OK (range-ok)
16539 *
16540 * STATUS: complete
16541 *
16542 * Returns 0 if the constraints are satisfied, a positive
16543 * error code if not and -1 if an internal error occured.
16544 */
16545static int
16546xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16547 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016549 if (rmin < bmin)
16550 return (1);
16551 if ((bmax != UNBOUNDED) &&
16552 (rmax > bmax))
16553 return (1);
16554 return (0);
16555}
16556
16557/**
16558 * xmlSchemaCheckRCaseNameAndTypeOK:
16559 * @ctxt: the schema parser context
16560 * @r: the restricting element declaration particle
16561 * @b: the base element declaration particle
16562 *
16563 * (3.9.6) Constraints on Particle Schema Components
16564 * Schema Component Constraint:
16565 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16566 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016567 *
16568 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016569 * MISSING (3.2.3)
16570 * CLARIFY: (3.2.2)
16571 *
16572 * Returns 0 if the constraints are satisfied, a positive
16573 * error code if not and -1 if an internal error occured.
16574 */
16575static int
16576xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16577 xmlSchemaParticlePtr r,
16578 xmlSchemaParticlePtr b)
16579{
16580 xmlSchemaElementPtr elemR, elemB;
16581
16582 /* TODO: Error codes (rcase-NameAndTypeOK). */
16583 elemR = (xmlSchemaElementPtr) r->children;
16584 elemB = (xmlSchemaElementPtr) b->children;
16585 /*
16586 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16587 * the same."
16588 */
16589 if ((elemR != elemB) &&
16590 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16591 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16592 return (1);
16593 /*
16594 * SPEC (2) "R's occurrence range is a valid restriction of B's
16595 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16596 */
16597 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16598 b->minOccurs, b->maxOccurs) != 0)
16599 return (1);
16600 /*
16601 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16602 * {scope} are global."
16603 */
16604 if (elemR == elemB)
16605 return (0);
16606 /*
16607 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16608 */
16609 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16610 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16611 return (1);
16612 /*
16613 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16614 * or is not fixed, or R's declaration's {value constraint} is fixed
16615 * with the same value."
16616 */
16617 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16618 ((elemR->value == NULL) ||
16619 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16620 /* TODO: Equality of the initial value or normalized or canonical? */
16621 (! xmlStrEqual(elemR->value, elemB->value))))
16622 return (1);
16623 /*
16624 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16625 * definitions} is a subset of B's declaration's {identity-constraint
16626 * definitions}, if any."
16627 */
16628 if (elemB->idcs != NULL) {
16629 /* TODO */
16630 }
16631 /*
16632 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16633 * superset of B's declaration's {disallowed substitutions}."
16634 */
16635 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16636 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16637 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16638 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16639 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16640 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16641 return (1);
16642 /*
16643 * SPEC (3.2.5) "R's {type definition} is validly derived given
16644 * {extension, list, union} from B's {type definition}"
16645 *
16646 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16647 * set, if the corresponding constraints handle "restriction" and
16648 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016649 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016650 */
16651 {
16652 int set = 0;
16653
16654 set |= SUBSET_EXTENSION;
16655 set |= SUBSET_LIST;
16656 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016657 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016658 elemB->subtypes, set) != 0)
16659 return (1);
16660 }
16661 return (0);
16662}
16663
16664/**
16665 * xmlSchemaCheckRCaseNSCompat:
16666 * @ctxt: the schema parser context
16667 * @r: the restricting element declaration particle
16668 * @b: the base wildcard particle
16669 *
16670 * (3.9.6) Constraints on Particle Schema Components
16671 * Schema Component Constraint:
16672 * Particle Derivation OK (Elt:Any -- NSCompat)
16673 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016674 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016675 * STATUS: complete
16676 *
16677 * Returns 0 if the constraints are satisfied, a positive
16678 * error code if not and -1 if an internal error occured.
16679 */
16680static int
16681xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16682 xmlSchemaParticlePtr r,
16683 xmlSchemaParticlePtr b)
16684{
16685 /* TODO:Error codes (rcase-NSCompat). */
16686 /*
16687 * SPEC "For an element declaration particle to be a ·valid restriction·
16688 * of a wildcard particle all of the following must be true:"
16689 *
16690 * SPEC (1) "The element declaration's {target namespace} is ·valid·
16691 * with respect to the wildcard's {namespace constraint} as defined by
16692 * Wildcard allows Namespace Name (§3.10.4)."
16693 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016694 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016695 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16696 return (1);
16697 /*
16698 * SPEC (2) "R's occurrence range is a valid restriction of B's
16699 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16700 */
16701 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16702 b->minOccurs, b->maxOccurs) != 0)
16703 return (1);
16704
16705 return (0);
16706}
16707
16708/**
16709 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16710 * @ctxt: the schema parser context
16711 * @r: the restricting element declaration particle
16712 * @b: the base model group particle
16713 *
16714 * (3.9.6) Constraints on Particle Schema Components
16715 * Schema Component Constraint:
16716 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16717 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016718 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016719 * STATUS: TODO
16720 *
16721 * Returns 0 if the constraints are satisfied, a positive
16722 * error code if not and -1 if an internal error occured.
16723 */
16724static int
16725xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16726 xmlSchemaParticlePtr r,
16727 xmlSchemaParticlePtr b)
16728{
16729 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16730 TODO
16731 return (0);
16732}
16733
16734/**
16735 * xmlSchemaCheckRCaseNSSubset:
16736 * @ctxt: the schema parser context
16737 * @r: the restricting wildcard particle
16738 * @b: the base wildcard particle
16739 *
16740 * (3.9.6) Constraints on Particle Schema Components
16741 * Schema Component Constraint:
16742 * Particle Derivation OK (Any:Any -- NSSubset)
16743 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016744 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016745 * STATUS: complete
16746 *
16747 * Returns 0 if the constraints are satisfied, a positive
16748 * error code if not and -1 if an internal error occured.
16749 */
16750static int
16751xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16752 xmlSchemaParticlePtr r,
16753 xmlSchemaParticlePtr b,
16754 int isAnyTypeBase)
16755{
16756 /* TODO: Error codes (rcase-NSSubset). */
16757 /*
16758 * SPEC (1) "R's occurrence range is a valid restriction of B's
16759 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16760 */
16761 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16762 b->minOccurs, b->maxOccurs))
16763 return (1);
16764 /*
16765 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16766 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
16767 */
16768 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16769 (xmlSchemaWildcardPtr) b->children))
16770 return (1);
16771 /*
16772 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
16773 * definition·, R's {process contents} must be identical to or stronger
16774 * than B's {process contents}, where strict is stronger than lax is
16775 * stronger than skip."
16776 */
16777 if (! isAnyTypeBase) {
16778 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16779 ((xmlSchemaWildcardPtr) b->children)->processContents)
16780 return (1);
16781 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016782
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016783 return (0);
16784}
16785
16786/**
16787 * xmlSchemaCheckCOSParticleRestrict:
16788 * @ctxt: the schema parser context
16789 * @type: the complex type definition
16790 *
16791 * (3.9.6) Constraints on Particle Schema Components
16792 * Schema Component Constraint:
16793 * Particle Valid (Restriction) (cos-particle-restrict)
16794 *
16795 * STATUS: TODO
16796 *
16797 * Returns 0 if the constraints are satisfied, a positive
16798 * error code if not and -1 if an internal error occured.
16799 */
16800static int
16801xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16802 xmlSchemaParticlePtr r,
16803 xmlSchemaParticlePtr b)
16804{
16805 int ret = 0;
16806
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016807 /*part = WXS_TYPE_PARTICLE(type);
16808 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016809 */
16810
16811 TODO
16812
16813 /*
16814 * SPEC (1) "They are the same particle."
16815 */
16816 if (r == b)
16817 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016818
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016819
16820 return (0);
16821}
16822
16823/**
16824 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16825 * @ctxt: the schema parser context
16826 * @r: the model group particle
16827 * @b: the base wildcard particle
16828 *
16829 * (3.9.6) Constraints on Particle Schema Components
16830 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016831 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016832 * NSRecurseCheckCardinality)
16833 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016835 * STATUS: TODO: subst-groups
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
16841xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16842 xmlSchemaParticlePtr r,
16843 xmlSchemaParticlePtr b)
16844{
16845 xmlSchemaParticlePtr part;
16846 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16847 if ((r->children == NULL) || (r->children->children == NULL))
16848 return (-1);
16849 /*
16850 * SPEC "For a group particle to be a ·valid restriction· of a
16851 * wildcard particle..."
16852 *
16853 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016854 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016855 * Particle Valid (Restriction) (§3.9.6)."
16856 */
16857 part = (xmlSchemaParticlePtr) r->children->children;
16858 do {
16859 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16860 return (1);
16861 part = (xmlSchemaParticlePtr) part->next;
16862 } while (part != NULL);
16863 /*
16864 * SPEC (2) "The effective total range of the group [...] is a
16865 * valid restriction of B's occurrence range as defined by
16866 * Occurrence Range OK (§3.9.6)."
16867 */
16868 if (xmlSchemaCheckParticleRangeOK(
16869 xmlSchemaGetParticleTotalRangeMin(r),
16870 xmlSchemaGetParticleTotalRangeMax(r),
16871 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016873 return (0);
16874}
16875
16876/**
16877 * xmlSchemaCheckRCaseRecurse:
16878 * @ctxt: the schema parser context
16879 * @r: the <all> or <sequence> model group particle
16880 * @b: the base <all> or <sequence> model group particle
16881 *
16882 * (3.9.6) Constraints on Particle Schema Components
16883 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016884 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016885 Recurse)
16886 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016888 * STATUS: ?
16889 * TODO: subst-groups
16890 *
16891 * Returns 0 if the constraints are satisfied, a positive
16892 * error code if not and -1 if an internal error occured.
16893 */
16894static int
16895xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16896 xmlSchemaParticlePtr r,
16897 xmlSchemaParticlePtr b)
16898{
16899 /* xmlSchemaParticlePtr part; */
16900 /* TODO: Error codes (rcase-Recurse). */
16901 if ((r->children == NULL) || (b->children == NULL) ||
16902 (r->children->type != b->children->type))
16903 return (-1);
16904 /*
16905 * SPEC "For an all or sequence group particle to be a ·valid
16906 * restriction· of another group particle with the same {compositor}..."
16907 *
16908 * SPEC (1) "R's occurrence range is a valid restriction of B's
16909 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16910 */
16911 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16912 b->minOccurs, b->maxOccurs))
16913 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016914
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016915
16916 return (0);
16917}
16918
16919#endif
16920
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016921#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
16922 xmlSchemaPCustomErrExt(pctxt, \
16923 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016924 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016925 "It is an error for both '%s' and '%s' to be specified on the "\
16926 "same type definition", \
16927 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
16928 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
16929
16930#define FACET_RESTR_ERR(fac1, msg) \
16931 xmlSchemaPCustomErr(pctxt, \
16932 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016933 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016935
16936#define FACET_RESTR_FIXED_ERR(fac) \
16937 xmlSchemaPCustomErr(pctxt, \
16938 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016939 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016940 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016941 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016942
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016943static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016944xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
16945 xmlSchemaFacetPtr facet1,
16946 xmlSchemaFacetPtr facet2,
16947 int lessGreater,
16948 int orEqual,
16949 int ofBase)
16950{
16951 xmlChar *msg = NULL;
16952
16953 msg = xmlStrdup(BAD_CAST "'");
16954 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
16955 msg = xmlStrcat(msg, BAD_CAST "' has to be");
16956 if (lessGreater == 0)
16957 msg = xmlStrcat(msg, BAD_CAST " equal to");
16958 if (lessGreater == 1)
16959 msg = xmlStrcat(msg, BAD_CAST " greater than");
16960 else
16961 msg = xmlStrcat(msg, BAD_CAST " less than");
16962
16963 if (orEqual)
16964 msg = xmlStrcat(msg, BAD_CAST " or equal to");
16965 msg = xmlStrcat(msg, BAD_CAST " '");
16966 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
16967 if (ofBase)
16968 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
16969 else
16970 msg = xmlStrcat(msg, BAD_CAST "'");
16971
16972 xmlSchemaPCustomErr(pctxt,
16973 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016974 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016975 (const char *) msg, NULL);
16976
16977 if (msg != NULL)
16978 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016979}
16980
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016981/*
16982* xmlSchemaDeriveAndValidateFacets:
16983*
16984* Schema Component Constraint: Simple Type Restriction (Facets)
16985* (st-restrict-facets)
16986*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016987static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016988xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
16989 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016990{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016991 xmlSchemaTypePtr base = type->baseType;
16992 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016993 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016994 flength = NULL, ftotdig = NULL, ffracdig = NULL,
16995 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
16996 fmininc = NULL, fmaxinc = NULL,
16997 fminexc = NULL, fmaxexc = NULL,
16998 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
16999 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17000 bfmininc = NULL, bfmaxinc = NULL,
17001 bfminexc = NULL, bfmaxexc = NULL;
17002 int res, err = 0, fixedErr;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017003
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017004 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017005 * SPEC st-restrict-facets 1:
17006 * "The {variety} of R is the same as that of B."
17007 */
17008 /*
17009 * SPEC st-restrict-facets 2:
17010 * "If {variety} is atomic, the {primitive type definition}
17011 * of R is the same as that of B."
17012 *
17013 * NOTE: we leave 1 & 2 out for now, since this will be
17014 * satisfied by the derivation process.
17015 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17016 */
17017 /*
17018 * SPEC st-restrict-facets 3:
17019 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017020 * of B, eliminating duplicates. To eliminate duplicates,
17021 * when a facet of the same kind occurs in both S and the
17022 * {facets} of B, the one in the {facets} of B is not
17023 * included, with the exception of enumeration and pattern
17024 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017025 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017026 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017027
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017028 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17029 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017030
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017031 last = type->facetSet;
17032 if (last != NULL)
17033 while (last->next != NULL)
17034 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017035
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017036 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17037 facet = cur->facet;
17038 switch (facet->type) {
17039 case XML_SCHEMA_FACET_LENGTH:
17040 flength = facet; break;
17041 case XML_SCHEMA_FACET_MINLENGTH:
17042 fminlen = facet; break;
17043 case XML_SCHEMA_FACET_MININCLUSIVE:
17044 fmininc = facet; break;
17045 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17046 fminexc = facet; break;
17047 case XML_SCHEMA_FACET_MAXLENGTH:
17048 fmaxlen = facet; break;
17049 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17050 fmaxinc = facet; break;
17051 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17052 fmaxexc = facet; break;
17053 case XML_SCHEMA_FACET_TOTALDIGITS:
17054 ftotdig = facet; break;
17055 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17056 ffracdig = facet; break;
17057 default:
17058 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017059 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017060 }
17061 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17062 facet = cur->facet;
17063 switch (facet->type) {
17064 case XML_SCHEMA_FACET_LENGTH:
17065 bflength = facet; break;
17066 case XML_SCHEMA_FACET_MINLENGTH:
17067 bfminlen = facet; break;
17068 case XML_SCHEMA_FACET_MININCLUSIVE:
17069 bfmininc = facet; break;
17070 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17071 bfminexc = facet; break;
17072 case XML_SCHEMA_FACET_MAXLENGTH:
17073 bfmaxlen = facet; break;
17074 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17075 bfmaxinc = facet; break;
17076 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17077 bfmaxexc = facet; break;
17078 case XML_SCHEMA_FACET_TOTALDIGITS:
17079 bftotdig = facet; break;
17080 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17081 bffracdig = facet; break;
17082 default:
17083 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017084 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017085 }
17086 err = 0;
17087 /*
17088 * length and minLength or maxLength (2.2) + (3.2)
17089 */
17090 if (flength && (fminlen || fmaxlen)) {
17091 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17092 "either of 'minLength' or 'maxLength' to be specified on "
17093 "the same type definition")
17094 }
17095 /*
17096 * Mutual exclusions in the same derivation step.
17097 */
17098 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017099 /*
17100 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017101 */
17102 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17103 }
17104 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017105 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017106 * SCC "minInclusive and minExclusive"
17107 */
17108 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017109 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017111 if (flength && bflength) {
17112 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017113 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017114 * The values have to be equal.
17115 */
17116 res = xmlSchemaCompareValues(flength->val, bflength->val);
17117 if (res == -2)
17118 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017119 if (res != 0)
17120 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17121 if ((res != 0) && (bflength->fixed)) {
17122 FACET_RESTR_FIXED_ERR(flength)
17123 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017124
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017125 }
17126 if (fminlen && bfminlen) {
17127 /*
17128 * SCC "minLength valid restriction"
17129 * minLength >= BASE minLength
17130 */
17131 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17132 if (res == -2)
17133 goto internal_error;
17134 if (res == -1)
17135 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17136 if ((res != 0) && (bfminlen->fixed)) {
17137 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017138 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017139 }
17140 if (fmaxlen && bfmaxlen) {
17141 /*
17142 * SCC "maxLength valid restriction"
17143 * maxLength <= BASE minLength
17144 */
17145 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17146 if (res == -2)
17147 goto internal_error;
17148 if (res == 1)
17149 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17150 if ((res != 0) && (bfmaxlen->fixed)) {
17151 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017152 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017153 }
17154 /*
17155 * SCC "length and minLength or maxLength"
17156 */
17157 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017158 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017159 if (flength) {
17160 if (! fminlen)
17161 flength = bflength;
17162 if (fminlen) {
17163 /* (1.1) length >= minLength */
17164 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17165 if (res == -2)
17166 goto internal_error;
17167 if (res == -1)
17168 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17169 }
17170 if (! fmaxlen)
17171 fmaxlen = bfmaxlen;
17172 if (fmaxlen) {
17173 /* (2.1) length <= maxLength */
17174 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17175 if (res == -2)
17176 goto internal_error;
17177 if (res == 1)
17178 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17179 }
17180 }
17181 if (fmaxinc) {
17182 /*
17183 * "maxInclusive"
17184 */
17185 if (fmininc) {
17186 /* SCC "maxInclusive >= minInclusive" */
17187 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17188 if (res == -2)
17189 goto internal_error;
17190 if (res == -1) {
17191 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17192 }
17193 }
17194 /*
17195 * SCC "maxInclusive valid restriction"
17196 */
17197 if (bfmaxinc) {
17198 /* maxInclusive <= BASE maxInclusive */
17199 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17200 if (res == -2)
17201 goto internal_error;
17202 if (res == 1)
17203 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17204 if ((res != 0) && (bfmaxinc->fixed)) {
17205 FACET_RESTR_FIXED_ERR(fmaxinc)
17206 }
17207 }
17208 if (bfmaxexc) {
17209 /* maxInclusive < BASE maxExclusive */
17210 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17211 if (res == -2)
17212 goto internal_error;
17213 if (res != -1) {
17214 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17215 }
17216 }
17217 if (bfmininc) {
17218 /* maxInclusive >= BASE minInclusive */
17219 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17220 if (res == -2)
17221 goto internal_error;
17222 if (res == -1) {
17223 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17224 }
17225 }
17226 if (bfminexc) {
17227 /* maxInclusive > BASE minExclusive */
17228 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17229 if (res == -2)
17230 goto internal_error;
17231 if (res != 1) {
17232 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17233 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017234 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017235 }
17236 if (fmaxexc) {
17237 /*
17238 * "maxExclusive >= minExclusive"
17239 */
17240 if (fminexc) {
17241 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17242 if (res == -2)
17243 goto internal_error;
17244 if (res == -1) {
17245 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17246 }
17247 }
17248 /*
17249 * "maxExclusive valid restriction"
17250 */
17251 if (bfmaxexc) {
17252 /* maxExclusive <= BASE maxExclusive */
17253 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17254 if (res == -2)
17255 goto internal_error;
17256 if (res == 1) {
17257 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17258 }
17259 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017260 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017261 }
17262 }
17263 if (bfmaxinc) {
17264 /* maxExclusive <= BASE maxInclusive */
17265 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17266 if (res == -2)
17267 goto internal_error;
17268 if (res == 1) {
17269 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17270 }
17271 }
17272 if (bfmininc) {
17273 /* maxExclusive > BASE minInclusive */
17274 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17275 if (res == -2)
17276 goto internal_error;
17277 if (res != 1) {
17278 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17279 }
17280 }
17281 if (bfminexc) {
17282 /* maxExclusive > BASE minExclusive */
17283 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17284 if (res == -2)
17285 goto internal_error;
17286 if (res != 1) {
17287 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17288 }
17289 }
17290 }
17291 if (fminexc) {
17292 /*
17293 * "minExclusive < maxInclusive"
17294 */
17295 if (fmaxinc) {
17296 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17297 if (res == -2)
17298 goto internal_error;
17299 if (res != -1) {
17300 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17301 }
17302 }
17303 /*
17304 * "minExclusive valid restriction"
17305 */
17306 if (bfminexc) {
17307 /* minExclusive >= BASE minExclusive */
17308 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17309 if (res == -2)
17310 goto internal_error;
17311 if (res == -1) {
17312 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17313 }
17314 if ((res != 0) && (bfminexc->fixed)) {
17315 FACET_RESTR_FIXED_ERR(fminexc)
17316 }
17317 }
17318 if (bfmaxinc) {
17319 /* minExclusive <= BASE maxInclusive */
17320 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17321 if (res == -2)
17322 goto internal_error;
17323 if (res == 1) {
17324 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17325 }
17326 }
17327 if (bfmininc) {
17328 /* minExclusive >= BASE minInclusive */
17329 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17330 if (res == -2)
17331 goto internal_error;
17332 if (res == -1) {
17333 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17334 }
17335 }
17336 if (bfmaxexc) {
17337 /* minExclusive < BASE maxExclusive */
17338 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17339 if (res == -2)
17340 goto internal_error;
17341 if (res != -1) {
17342 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17343 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017344 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017345 }
17346 if (fmininc) {
17347 /*
17348 * "minInclusive < maxExclusive"
17349 */
17350 if (fmaxexc) {
17351 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17352 if (res == -2)
17353 goto internal_error;
17354 if (res != -1) {
17355 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17356 }
17357 }
17358 /*
17359 * "minExclusive valid restriction"
17360 */
17361 if (bfmininc) {
17362 /* minInclusive >= BASE minInclusive */
17363 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17364 if (res == -2)
17365 goto internal_error;
17366 if (res == -1) {
17367 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17368 }
17369 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017370 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017371 }
17372 }
17373 if (bfmaxinc) {
17374 /* minInclusive <= BASE maxInclusive */
17375 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17376 if (res == -2)
17377 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017378 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017379 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17380 }
17381 }
17382 if (bfminexc) {
17383 /* minInclusive > BASE minExclusive */
17384 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17385 if (res == -2)
17386 goto internal_error;
17387 if (res != 1)
17388 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17389 }
17390 if (bfmaxexc) {
17391 /* minInclusive < BASE maxExclusive */
17392 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17393 if (res == -2)
17394 goto internal_error;
17395 if (res != -1)
17396 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17397 }
17398 }
17399 if (ftotdig && bftotdig) {
17400 /*
17401 * SCC " totalDigits valid restriction"
17402 * totalDigits <= BASE totalDigits
17403 */
17404 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17405 if (res == -2)
17406 goto internal_error;
17407 if (res == 1)
17408 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17409 -1, 1, 1);
17410 if ((res != 0) && (bftotdig->fixed)) {
17411 FACET_RESTR_FIXED_ERR(ftotdig)
17412 }
17413 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017414 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017415 /*
17416 * SCC "fractionDigits valid restriction"
17417 * fractionDigits <= BASE fractionDigits
17418 */
17419 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17420 if (res == -2)
17421 goto internal_error;
17422 if (res == 1)
17423 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17424 -1, 1, 1);
17425 if ((res != 0) && (bffracdig->fixed)) {
17426 FACET_RESTR_FIXED_ERR(ffracdig)
17427 }
17428 }
17429 /*
17430 * SCC "fractionDigits less than or equal to totalDigits"
17431 */
17432 if (! ftotdig)
17433 ftotdig = bftotdig;
17434 if (! ffracdig)
17435 ffracdig = bffracdig;
17436 if (ftotdig && ffracdig) {
17437 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17438 if (res == -2)
17439 goto internal_error;
17440 if (res == 1)
17441 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17442 -1, 1, 0);
17443 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017444 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017445 * *Enumerations* won' be added here, since only the first set
17446 * of enumerations in the ancestor-or-self axis is used
17447 * for validation, plus we need to use the base type of those
17448 * enumerations for whitespace.
17449 *
17450 * *Patterns*: won't be add here, since they are ORed at
17451 * type level and ANDed at ancestor level. This will
17452 * happed during validation by walking the base axis
17453 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017454 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017455 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17456 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017457 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017458 * Special handling of enumerations and patterns.
17459 * TODO: hmm, they should not appear in the set, so remove this.
17460 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017461 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017462 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017463 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017464 /*
17465 * Search for a duplicate facet in the current type.
17466 */
17467 link = type->facetSet;
17468 err = 0;
17469 fixedErr = 0;
17470 while (link != NULL) {
17471 facet = link->facet;
17472 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017473 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017474 case XML_SCHEMA_FACET_WHITESPACE:
17475 /*
17476 * The whitespace must be stronger.
17477 */
17478 if (facet->whitespace < bfacet->whitespace) {
17479 FACET_RESTR_ERR(flength,
17480 "The 'whitespace' value has to be equal to "
17481 "or stronger than the 'whitespace' value of "
17482 "the base type")
17483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017484 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017485 (facet->whitespace != bfacet->whitespace)) {
17486 FACET_RESTR_FIXED_ERR(facet)
17487 }
17488 break;
17489 default:
17490 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017491 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017492 /* Duplicate found. */
17493 break;
17494 }
17495 link = link->next;
17496 }
17497 /*
17498 * If no duplicate was found: add the base types's facet
17499 * to the set.
17500 */
17501 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017502 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017503 xmlMalloc(sizeof(xmlSchemaFacetLink));
17504 if (link == NULL) {
17505 xmlSchemaPErrMemory(pctxt,
17506 "deriving facets, creating a facet link", NULL);
17507 return (-1);
17508 }
17509 link->facet = cur->facet;
17510 link->next = NULL;
17511 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017512 type->facetSet = link;
17513 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017514 last->next = link;
17515 last = link;
17516 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017517
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017518 }
17519
17520 return (0);
17521internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017522 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17523 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017524 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017525}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017526
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017527static int
17528xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17529 xmlSchemaTypePtr type)
17530{
17531 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17532 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 * The actual value is then formed by replacing any union type
17534 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017535 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017536 *
17537 * TODO: There's a bug entry at
17538 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17539 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017540 */
17541 link = type->memberTypes;
17542 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017543
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017544 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017545 xmlSchemaTypeFixup(link->type, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017546
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017547 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017548 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017549 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017550 link->type = subLink->type;
17551 if (subLink->next != NULL) {
17552 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017553 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017554 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017555 while (subLink != NULL) {
17556 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017557 xmlMalloc(sizeof(xmlSchemaTypeLink));
17558 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017559 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017560 NULL);
17561 return (-1);
17562 }
17563 newLink->type = subLink->type;
17564 prevLink->next = newLink;
17565 prevLink = newLink;
17566 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017567
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017568 subLink = subLink->next;
17569 }
17570 }
17571 }
17572 }
17573 link = link->next;
17574 }
17575 return (0);
17576}
17577
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017578static void
17579xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17580{
17581 int has = 0, needVal = 0, normVal = 0;
17582
17583 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17584 if (has) {
17585 needVal = (type->baseType->flags &
17586 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17587 normVal = (type->baseType->flags &
17588 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17589 }
17590 if (type->facets != NULL) {
17591 xmlSchemaFacetPtr fac;
17592
17593 for (fac = type->facets; fac != NULL; fac = fac->next) {
17594 switch (fac->type) {
17595 case XML_SCHEMA_FACET_WHITESPACE:
17596 break;
17597 case XML_SCHEMA_FACET_PATTERN:
17598 normVal = 1;
17599 has = 1;
17600 break;
17601 case XML_SCHEMA_FACET_ENUMERATION:
17602 needVal = 1;
17603 normVal = 1;
17604 has = 1;
17605 break;
17606 default:
17607 has = 1;
17608 break;
17609 }
17610 }
17611 }
17612 if (normVal)
17613 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17614 if (needVal)
17615 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17616 if (has)
17617 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17618
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017619 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17621 /*
17622 * OPTIMIZE VAL TODO: Some facets need a computed value.
17623 */
17624 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17625 (prim->builtInType != XML_SCHEMAS_STRING)) {
17626 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17627 }
17628 }
17629}
17630
17631static int
17632xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17633{
17634
17635
17636 /*
17637 * Evaluate the whitespace-facet value.
17638 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017639 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017640 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17641 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017642 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017643 return (0);
17644
17645 if (type->facetSet != NULL) {
17646 xmlSchemaFacetLinkPtr lin;
17647
17648 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17649 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17650 switch (lin->facet->whitespace) {
17651 case XML_SCHEMAS_FACET_PRESERVE:
17652 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17653 break;
17654 case XML_SCHEMAS_FACET_REPLACE:
17655 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17656 break;
17657 case XML_SCHEMAS_FACET_COLLAPSE:
17658 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17659 break;
17660 default:
17661 return (-1);
17662 }
17663 return (0);
17664 }
17665 }
17666 }
17667 /*
17668 * For all ·atomic· datatypes other than string (and types ·derived·
17669 * by ·restriction· from it) the value of whiteSpace is fixed to
17670 * collapse
17671 */
17672 {
17673 xmlSchemaTypePtr anc;
17674
17675 for (anc = type->baseType; anc != NULL &&
17676 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17677 anc = anc->baseType) {
17678
17679 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17680 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17681 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17682
17683 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17684 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17685 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17686
17687 } else
17688 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17689 break;
17690 }
17691 }
17692 return (0);
17693 }
17694 return (0);
17695}
17696
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017697static int
17698xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17699 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017700{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017701 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17702 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017703 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017704 return(0);
17705 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017706
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017707 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017708 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017709 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017710 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017711 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017712 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017713 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017714 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017715 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017716 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017717 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017718 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017719 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017720 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017721 * Corresponds to <simpleType><union>...
17722 */
17723 if (type->memberTypes == NULL) {
17724 /*
17725 * This one is really needed, so get out.
17726 */
17727 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17728 "union type has no member-types assigned");
17729 return(-1);
17730 }
17731 } else {
17732 /*
17733 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017734 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017735 if (type->baseType == NULL) {
17736 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17737 "type has no base-type assigned");
17738 return(-1);
17739 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017740 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017741 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17742 return(-1);
17743 /*
17744 * Variety
17745 * If the <restriction> alternative is chosen, then the
17746 * {variety} of the {base type definition}.
17747 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017748 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017749 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017750 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017751 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017752 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017753 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017754 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017755 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017756 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017757 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017758 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017759 * NOTE that we won't assign the memberTypes of the base,
17760 * since this will make trouble when freeing them; we will
17761 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017762 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017763 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017764 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017765 return(0);
17766}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017767
Daniel Veillard8651f532002-04-17 09:06:27 +000017768#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017769xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17770 xmlSchemaTypePtr type)
17771{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017772 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017773 xmlGenericError(xmlGenericErrorContext,
17774 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017775 type->node->doc->URL,
17776 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017777 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017778 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000017779 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017780 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017781 switch (type->contentType) {
17782 case XML_SCHEMA_CONTENT_SIMPLE:
17783 xmlGenericError(xmlGenericErrorContext, "simple\n");
17784 break;
17785 case XML_SCHEMA_CONTENT_ELEMENTS:
17786 xmlGenericError(xmlGenericErrorContext, "elements\n");
17787 break;
17788 case XML_SCHEMA_CONTENT_UNKNOWN:
17789 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17790 break;
17791 case XML_SCHEMA_CONTENT_EMPTY:
17792 xmlGenericError(xmlGenericErrorContext, "empty\n");
17793 break;
17794 case XML_SCHEMA_CONTENT_MIXED:
17795 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017796 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017797 xmlGenericError(xmlGenericErrorContext,
17798 "mixed as emptiable particle\n");
17799 else
17800 xmlGenericError(xmlGenericErrorContext, "mixed\n");
17801 break;
17802 /* Removed, since not used. */
17803 /*
17804 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17805 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17806 break;
17807 */
17808 case XML_SCHEMA_CONTENT_BASIC:
17809 xmlGenericError(xmlGenericErrorContext, "basic\n");
17810 break;
17811 default:
17812 xmlGenericError(xmlGenericErrorContext,
17813 "not registered !!!\n");
17814 break;
17815 }
Daniel Veillard8651f532002-04-17 09:06:27 +000017816 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017817}
Daniel Veillard8651f532002-04-17 09:06:27 +000017818#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017819
17820/*
17821* 3.14.6 Constraints on Simple Type Definition Schema Components
17822*/
17823static int
17824xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17825 xmlSchemaTypePtr type)
17826{
17827 int res, olderrs = pctxt->nberrors;
17828
17829 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17830 return(-1);
17831
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017832 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017833 return(0);
17834
17835 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17836 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17837
17838 if (type->baseType == NULL) {
17839 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17840 "missing baseType");
17841 goto exit_failure;
17842 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017843 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017844 xmlSchemaTypeFixup(type->baseType, pctxt);
17845 /*
17846 * If a member type of a union is a union itself, we need to substitute
17847 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017848 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17849 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017850 */
17851 if ((type->memberTypes != NULL) &&
17852 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17853 return(-1);
17854 /*
17855 * SPEC src-simple-type 1
17856 * "The corresponding simple type definition, if any, must satisfy
17857 * the conditions set out in Constraints on Simple Type Definition
17858 * Schema Components (§3.14.6)."
17859 */
17860 /*
17861 * Schema Component Constraint: Simple Type Definition Properties Correct
17862 * (st-props-correct)
17863 */
17864 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17865 HFAILURE HERROR
17866 /*
17867 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17868 * (cos-st-restricts)
17869 */
17870 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17871 HFAILURE HERROR
17872 /*
17873 * TODO: Removed the error report, since it got annoying to get an
17874 * extra error report, if anything failed until now.
17875 * Enable this if needed.
17876 *
17877 * xmlSchemaPErr(ctxt, type->node,
17878 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17879 * "Simple type '%s' does not satisfy the constraints "
17880 * "on simple type definitions.\n",
17881 * type->name, NULL);
17882 */
17883 /*
17884 * Schema Component Constraint: Simple Type Restriction (Facets)
17885 * (st-restrict-facets)
17886 */
17887 res = xmlSchemaCheckFacetValues(type, pctxt);
17888 HFAILURE HERROR
17889 if ((type->facetSet != NULL) ||
17890 (type->baseType->facetSet != NULL)) {
17891 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17892 HFAILURE HERROR
17893 }
17894 /*
17895 * Whitespace value.
17896 */
17897 res = xmlSchemaTypeFixupWhitespace(type);
17898 HFAILURE HERROR
17899 xmlSchemaTypeFixupOptimFacets(type);
17900
17901exit_error:
17902#ifdef DEBUG_TYPE
17903 xmlSchemaDebugFixedType(pctxt, type);
17904#endif
17905 if (olderrs != pctxt->nberrors)
17906 return(pctxt->err);
17907 return(0);
17908
17909exit_failure:
17910#ifdef DEBUG_TYPE
17911 xmlSchemaDebugFixedType(pctxt, type);
17912#endif
17913 return(-1);
17914}
17915
17916static int
17917xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17918 xmlSchemaTypePtr type)
17919{
17920 int res = 0, olderrs = pctxt->nberrors;
17921 xmlSchemaTypePtr baseType = type->baseType;
17922
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017923 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017924 return(0);
17925 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17926 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017927 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017928 "missing baseType");
17929 goto exit_failure;
17930 }
17931 /*
17932 * Fixup the base type.
17933 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017934 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017935 xmlSchemaTypeFixup(baseType, pctxt);
17936 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
17937 /*
17938 * Skip fixup if the base type is invalid.
17939 * TODO: Generate a warning!
17940 */
17941 return(0);
17942 }
17943 /*
17944 * This basically checks if the base type can be derived.
17945 */
17946 res = xmlSchemaCheckSRCCT(pctxt, type);
17947 HFAILURE HERROR
17948 /*
17949 * Fixup the content type.
17950 */
17951 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
17952 /*
17953 * Corresponds to <complexType><simpleContent>...
17954 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017955 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017956 (baseType->contentTypeDef != NULL) &&
17957 (WXS_IS_RESTRICTION(type))) {
17958 xmlSchemaTypePtr contentBase, content;
17959#ifdef ENABLE_NAMED_LOCALS
17960 char buf[30];
17961 const xmlChar *tmpname;
17962#endif
17963 /*
17964 * SPEC (1) If <restriction> + base type is <complexType>,
17965 * "whose own {content type} is a simple type..."
17966 */
17967 if (type->contentTypeDef != NULL) {
17968 /*
17969 * SPEC (1.1) "the simple type definition corresponding to the
17970 * <simpleType> among the [children] of <restriction> if there
17971 * is one;"
17972 * Note that this "<simpleType> among the [children]" was put
17973 * into ->contentTypeDef during parsing.
17974 */
17975 contentBase = type->contentTypeDef;
17976 type->contentTypeDef = NULL;
17977 } else {
17978 /*
17979 * (1.2) "...otherwise (<restriction> has no <simpleType>
17980 * among its [children]), the simple type definition which
17981 * is the {content type} of the ... base type."
17982 */
17983 contentBase = baseType->contentTypeDef;
17984 }
17985 /*
17986 * SPEC
17987 * "... a simple type definition which restricts the simple
17988 * type definition identified in clause 1.1 or clause 1.2
17989 * with a set of facet components"
17990 *
17991 * Create the anonymous simple type, which will be the content
17992 * type of the complex type.
17993 */
17994#ifdef ENABLE_NAMED_LOCALS
17995 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
17996 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017997 content = xmlSchemaAddType(pctxt, pctxt->schema,
17998 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017999 type->node, 0);
18000#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018001 content = xmlSchemaAddType(pctxt, pctxt->schema,
18002 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018003 type->node, 0);
18004#endif
18005 if (content == NULL)
18006 goto exit_failure;
18007 /*
18008 * We will use the same node as for the <complexType>
18009 * to have it somehow anchored in the schema doc.
18010 */
18011 content->type = XML_SCHEMA_TYPE_SIMPLE;
18012 content->baseType = contentBase;
18013 /*
18014 * Move the facets, previously anchored on the
18015 * complexType during parsing.
18016 */
18017 content->facets = type->facets;
18018 type->facets = NULL;
18019 content->facetSet = type->facetSet;
18020 type->facetSet = NULL;
18021
18022 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018023 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018024 xmlSchemaTypeFixup(contentBase, pctxt);
18025 /*
18026 * Fixup the newly created type. We don't need to check
18027 * for circularity here.
18028 */
18029 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18030 HFAILURE HERROR
18031 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18032 HFAILURE HERROR
18033
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018034 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018035 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18036 (WXS_IS_RESTRICTION(type))) {
18037 /*
18038 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18039 * an emptiable particle, then a simple type definition which
18040 * restricts the <restriction>'s <simpleType> child.
18041 */
18042 if ((type->contentTypeDef == NULL) ||
18043 (type->contentTypeDef->baseType == NULL)) {
18044 /*
18045 * TODO: Check if this ever happens.
18046 */
18047 xmlSchemaPCustomErr(pctxt,
18048 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018049 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018050 "Internal error: xmlSchemaTypeFixup, "
18051 "complex type '%s': the <simpleContent><restriction> "
18052 "is missing a <simpleType> child, but was not catched "
18053 "by xmlSchemaCheckSRCCT()", type->name);
18054 goto exit_failure;
18055 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018056 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018057 /*
18058 * SPEC (3) If <extension> + base is <complexType> with
18059 * <simpleType> content, "...then the {content type} of that
18060 * complex type definition"
18061 */
18062 if (baseType->contentTypeDef == NULL) {
18063 /*
18064 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18065 * should have catched this already.
18066 */
18067 xmlSchemaPCustomErr(pctxt,
18068 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018069 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018070 "Internal error: xmlSchemaTypeFixup, "
18071 "complex type '%s': the <extension>ed base type is "
18072 "a complex type with no simple content type",
18073 type->name);
18074 goto exit_failure;
18075 }
18076 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018077 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018078 /*
18079 * SPEC (4) <extension> + base is <simpleType>
18080 * "... then that simple type definition"
18081 */
18082 type->contentTypeDef = baseType;
18083 } else {
18084 /*
18085 * TODO: Check if this ever happens.
18086 */
18087 xmlSchemaPCustomErr(pctxt,
18088 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018089 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018090 "Internal error: xmlSchemaTypeFixup, "
18091 "complex type '%s' with <simpleContent>: unhandled "
18092 "derivation case", type->name);
18093 goto exit_failure;
18094 }
18095 } else {
18096 int dummySequence = 0;
18097 xmlSchemaParticlePtr particle =
18098 (xmlSchemaParticlePtr) type->subtypes;
18099 /*
18100 * Corresponds to <complexType><complexContent>...
18101 *
18102 * NOTE that the effective mixed was already set during parsing of
18103 * <complexType> and <complexContent>; its flag value is
18104 * XML_SCHEMAS_TYPE_MIXED.
18105 *
18106 * Compute the "effective content":
18107 * (2.1.1) + (2.1.2) + (2.1.3)
18108 */
18109 if ((particle == NULL) ||
18110 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18111 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18112 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18113 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18114 (particle->minOccurs == 0))) &&
18115 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18116 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18117 /*
18118 * SPEC (2.1.4) "If the ·effective mixed· is true, then
18119 * a particle whose properties are as follows:..."
18120 *
18121 * Empty sequence model group with
18122 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18123 * NOTE that we sill assign it the <complexType> node to
18124 * somehow anchor it in the doc.
18125 */
18126 if ((particle == NULL) ||
18127 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18128 /*
18129 * Create the particle.
18130 */
18131 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18132 type->node, 1, 1);
18133 if (particle == NULL)
18134 goto exit_failure;
18135 /*
18136 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018137 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018138 particle->children = (xmlSchemaTreeItemPtr)
18139 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18140 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18141 if (particle->children == NULL)
18142 goto exit_failure;
18143
18144 type->subtypes = (xmlSchemaTypePtr) particle;
18145 }
18146 dummySequence = 1;
18147 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18148 } else {
18149 /*
18150 * SPEC (2.1.5) "otherwise empty"
18151 */
18152 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18153 }
18154 } else {
18155 /*
18156 * SPEC (2.2) "otherwise the particle corresponding to the
18157 * <all>, <choice>, <group> or <sequence> among the
18158 * [children]."
18159 */
18160 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18161 }
18162 /*
18163 * Compute the "content type".
18164 */
18165 if (WXS_IS_RESTRICTION(type)) {
18166 /*
18167 * SPEC (3.1) "If <restriction>..."
18168 * (3.1.1) + (3.1.2) */
18169 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18170 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18171 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18172 }
18173 } else {
18174 /*
18175 * SPEC (3.2) "If <extension>..."
18176 */
18177 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18178 /*
18179 * SPEC (3.2.1)
18180 */
18181 type->contentType = baseType->contentType;
18182 type->subtypes = baseType->subtypes;
18183 /*
18184 * NOTE that the effective mixed is ignored here.
18185 */
18186 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18187 /*
18188 * SPEC (3.2.2)
18189 */
18190 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18191 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18192 } else {
18193 /*
18194 * SPEC (3.2.3)
18195 */
18196 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18197 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18198 /*
18199 * "A model group whose {compositor} is sequence and whose
18200 * {particles} are..."
18201 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018202 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18203 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18204 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18205 XML_SCHEMA_TYPE_ALL))
18206 {
18207 /*
18208 * SPEC cos-all-limited (1)
18209 */
18210 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18211 /* TODO: error code */
18212 XML_SCHEMAP_COS_ALL_LIMITED,
18213 WXS_ITEM_NODE(type), NULL,
18214 "The type has an 'all' model group in its "
18215 "{content type} and thus cannot be derived from "
18216 "a non-empty type, since this would produce a "
18217 "'sequence' model group containing the 'all' "
18218 "model group; 'all' model groups are not "
18219 "allowed to appear inside other model groups",
18220 NULL, NULL);
18221
18222 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18223 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18224 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18225 XML_SCHEMA_TYPE_ALL))
18226 {
18227 /*
18228 * SPEC cos-all-limited (1)
18229 */
18230 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18231 /* TODO: error code */
18232 XML_SCHEMAP_COS_ALL_LIMITED,
18233 WXS_ITEM_NODE(type), NULL,
18234 "A type cannot be derived by extension from a type "
18235 "which has an 'all' model group in its "
18236 "{content type}, since this would produce a "
18237 "'sequence' model group containing the 'all' "
18238 "model group; 'all' model groups are not "
18239 "allowed to appear inside other model groups",
18240 NULL, NULL);
18241
18242 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018243 xmlSchemaTreeItemPtr effectiveContent =
18244 (xmlSchemaTreeItemPtr) type->subtypes;
18245 /*
18246 * Create the particle.
18247 */
18248 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
18249 type->node, 1, 1);
18250 if (particle == NULL)
18251 goto exit_failure;
18252 /*
18253 * Create the "sequence" model group.
18254 */
18255 particle->children = (xmlSchemaTreeItemPtr)
18256 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18257 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18258 if (particle->children == NULL)
18259 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018260 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018261 /*
18262 * SPEC "the particle of the {content type} of
18263 * the ... base ..."
18264 * Create a duplicate of the base type's particle
18265 * and assign its "term" to it.
18266 */
18267 particle->children->children =
18268 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18269 pctxt->schema, type->node,
18270 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18271 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18272 if (particle->children->children == NULL)
18273 goto exit_failure;
18274 particle = (xmlSchemaParticlePtr)
18275 particle->children->children;
18276 particle->children =
18277 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18278 /*
18279 * SPEC "followed by the ·effective content·."
18280 */
18281 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018282 /*
18283 * This all will result in:
18284 * new-particle
18285 * --> new-sequence(
18286 * new-particle
18287 * --> base-model,
18288 * this-particle
18289 * --> this-model
18290 * )
18291 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018292 } else {
18293 /*
18294 * This is the case when there is already an empty
18295 * <sequence> with minOccurs==maxOccurs==1.
18296 * Just add the base types's content type.
18297 * NOTE that, although we miss to add an intermediate
18298 * <sequence>, this should produce no difference to
18299 * neither the regex compilation of the content model,
18300 * nor to the complex type contraints.
18301 */
18302 particle->children->children =
18303 (xmlSchemaTreeItemPtr) baseType->subtypes;
18304 }
18305 }
18306 }
18307 }
18308 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018309 * Now fixup attribute uses:
18310 * - expand attr. group references
18311 * - intersect attribute wildcards
18312 * - inherit attribute uses of the base type
18313 * - inherit or union attr. wildcards if extending
18314 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018315 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018316 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018317 HFAILURE HERROR
18318 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018319 * Apply the complex type component constraints; this will not
18320 * check attributes, since this is done in
18321 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018322 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018323 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018324 HFAILURE HERROR
18325
18326#ifdef DEBUG_TYPE
18327 xmlSchemaDebugFixedType(pctxt, type);
18328#endif
18329 if (olderrs != pctxt->nberrors)
18330 return(pctxt->err);
18331 else
18332 return(0);
18333
18334exit_error:
18335 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18336#ifdef DEBUG_TYPE
18337 xmlSchemaDebugFixedType(pctxt, type);
18338#endif
18339 return(pctxt->err);
18340
18341exit_failure:
18342 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18343#ifdef DEBUG_TYPE
18344 xmlSchemaDebugFixedType(pctxt, type);
18345#endif
18346 return(-1);
18347}
18348
18349
18350/**
18351 * xmlSchemaTypeFixup:
18352 * @typeDecl: the schema type definition
18353 * @ctxt: the schema parser context
18354 *
18355 * Fixes the content model of the type.
18356 * URGENT TODO: We need an int result!
18357 */
18358static int
18359xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18360 xmlSchemaParserCtxtPtr pctxt)
18361{
18362 if (type == NULL)
18363 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018364 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018365 return(0);
18366 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18367 return(xmlSchemaFixupComplexType(pctxt, type));
18368 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18369 return(xmlSchemaFixupSimpleTypeStageTwo(pctxt, type));
18370 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018371}
18372
18373/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018374 * xmlSchemaCheckFacet:
18375 * @facet: the facet
18376 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018377 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018378 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018379 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018380 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018381 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018382 * Returns 0 if valid, a positive error code if not valid and
18383 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018384 */
18385int
18386xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018387 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018388 xmlSchemaParserCtxtPtr pctxt,
18389 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018390{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018391 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018392
Daniel Veillardce682bc2004-11-05 17:22:25 +000018393 if ((facet == NULL) || (typeDecl == NULL))
18394 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018395 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018396 * TODO: will the parser context be given if used from
18397 * the relaxNG module?
18398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018399 if (pctxt == NULL)
18400 ctxtGiven = 0;
18401 else
18402 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018403
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018404 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018405 case XML_SCHEMA_FACET_MININCLUSIVE:
18406 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18407 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018408 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18409 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018410 /*
18411 * Okay we need to validate the value
18412 * at that point.
18413 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018414 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018415
18416 /* 4.3.5.5 Constraints on enumeration Schema Components
18417 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018418 * It is an ·error· if any member of {value} is not in the
18419 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018420 *
18421 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018422 * The value ·must· be in the
18423 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018424 */
18425 /*
18426 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018427 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018428 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018429 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018430 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018431 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018432 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018433 */
18434 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18435 base = typeDecl->baseType;
18436 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018437 PERROR_INT("xmlSchemaCheckFacet",
18438 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018439 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018440 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018441 } else
18442 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018443
18444 if (! ctxtGiven) {
18445 /*
18446 * A context is needed if called from RelaxNG.
18447 */
18448 pctxt = xmlSchemaNewParserCtxt("*");
18449 if (pctxt == NULL)
18450 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018451 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018452 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018453 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018454 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018455 * facet->node is just the node holding the facet
18456 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018457 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018458 */
18459 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018460 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018461 facet->value, &(facet->val), 1, 1, 0);
18462 if (ret != 0) {
18463 if (ret < 0) {
18464 /* No error message for RelaxNG. */
18465 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018466 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018467 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18468 "Internal error: xmlSchemaCheckFacet, "
18469 "failed to validate the value '%s' of the "
18470 "facet '%s' against the base type",
18471 facet->value, xmlSchemaFacetTypeToString(facet->type));
18472 }
18473 goto internal_error;
18474 }
18475 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18476 /* No error message for RelaxNG. */
18477 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018478 xmlChar *str = NULL;
18479
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018480 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018481 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018482 "The value '%s' of the facet does not validate "
18483 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 facet->value,
18485 xmlSchemaFormatQName(&str,
18486 base->targetNamespace, base->name));
18487 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018488 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 goto exit;
18490 } else if (facet->val == NULL) {
18491 if (ctxtGiven) {
18492 PERROR_INT("xmlSchemaCheckFacet",
18493 "value was not computed");
18494 }
18495 TODO
18496 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018497 break;
18498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018499 case XML_SCHEMA_FACET_PATTERN:
18500 facet->regexp = xmlRegexpCompile(facet->value);
18501 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018502 ret = XML_SCHEMAP_REGEXP_INVALID;
18503 /* No error message for RelaxNG. */
18504 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018505 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018506 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018507 "The value '%s' of the facet 'pattern' is not a "
18508 "valid regular expression",
18509 facet->value, NULL);
18510 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018511 }
18512 break;
18513 case XML_SCHEMA_FACET_TOTALDIGITS:
18514 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18515 case XML_SCHEMA_FACET_LENGTH:
18516 case XML_SCHEMA_FACET_MAXLENGTH:
18517 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018518 ret = xmlSchemaValidatePredefinedType(
18519 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18520 facet->value, &(facet->val));
18521 if (ret != 0) {
18522 if (ret < 0) {
18523 /* No error message for RelaxNG. */
18524 if (ctxtGiven) {
18525 PERROR_INT("xmlSchemaCheckFacet",
18526 "validating facet value");
18527 }
18528 goto internal_error;
18529 }
18530 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18531 /* No error message for RelaxNG. */
18532 if (ctxtGiven) {
18533 /* error code */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018534 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018535 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 "The value '%s' of the facet '%s' is not a valid "
18537 "'nonNegativeInteger'",
18538 facet->value,
18539 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018540 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018541 }
18542 break;
18543 }
18544 case XML_SCHEMA_FACET_WHITESPACE:{
18545 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18546 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18547 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18548 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18549 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18550 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18551 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018552 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18553 /* No error message for RelaxNG. */
18554 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018555 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018556 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018557 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018558 "The value '%s' of the facet 'whitespace' is not "
18559 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018560 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018561 }
18562 }
18563 default:
18564 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018565 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566exit:
18567 if ((! ctxtGiven) && (pctxt != NULL))
18568 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018569 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018570internal_error:
18571 if ((! ctxtGiven) && (pctxt != NULL))
18572 xmlSchemaFreeParserCtxt(pctxt);
18573 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018574}
18575
18576/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018577 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018578 * @typeDecl: the schema type definition
18579 * @ctxt: the schema parser context
18580 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018581 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018582 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018583static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018584xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018585 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018586{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018587 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018588 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018589 /*
18590 * NOTE: It is intended to use the facets list, instead
18591 * of facetSet.
18592 */
18593 if (typeDecl->facets != NULL) {
18594 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018595
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018596 /*
18597 * Temporarily assign the "schema" to the validation context
18598 * of the parser context. This is needed for NOTATION validation.
18599 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018600 if (pctxt->vctxt == NULL) {
18601 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18602 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018603 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018604 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018605 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018606 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18607 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018608 facet = facet->next;
18609 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018610 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018612 if (olderrs != pctxt->nberrors)
18613 return(pctxt->err);
18614 return(0);
18615exit_failure:
18616 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018617}
18618
18619/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018620 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018621 * @ctxtMGroup: the searched model group
18622 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018623 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018624 *
18625 * This one is intended to be used by
18626 * xmlSchemaCheckGroupDefCircular only.
18627 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018628 * Returns the particle with the circular model group definition reference,
18629 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018630 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018631static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018632xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018633 xmlSchemaTreeItemPtr particle)
18634{
18635 xmlSchemaTreeItemPtr circ = NULL;
18636 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018637 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018638
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018639 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018640 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018641 if (term == NULL)
18642 continue;
18643 switch (term->type) {
18644 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018646 if (gdef == groupDef)
18647 return (particle);
18648 /*
18649 * Mark this model group definition to avoid infinite
18650 * recursion on circular references not yet examined.
18651 */
18652 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18653 continue;
18654 if (gdef->children != NULL) {
18655 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18656 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18657 gdef->children->children);
18658 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18659 if (circ != NULL)
18660 return (circ);
18661 }
18662 break;
18663 case XML_SCHEMA_TYPE_SEQUENCE:
18664 case XML_SCHEMA_TYPE_CHOICE:
18665 case XML_SCHEMA_TYPE_ALL:
18666 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18667 if (circ != NULL)
18668 return (circ);
18669 break;
18670 default:
18671 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018672 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018673 }
18674 return (NULL);
18675}
18676
18677/**
18678 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018679 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018680 * @ctxt: the parser context
18681 * @name: the name
18682 *
18683 * Checks for circular references to model group definitions.
18684 */
18685static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018686xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018687 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018688{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018689 /*
18690 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018691 * 2 Circular groups are disallowed. That is, within the {particles}
18692 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018693 * is the group itself.
18694 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018695 if ((item == NULL) ||
18696 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18697 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018698 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018699 {
18700 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018701
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018702 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018703 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018704 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018705 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018706 * TODO: The error report is not adequate: this constraint
18707 * is defined for model groups but not definitions, but since
18708 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018710 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018711 */
18712 xmlSchemaPCustomErr(ctxt,
18713 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018714 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018715 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018716 "defined", xmlSchemaFormatQName(&str,
18717 item->targetNamespace, item->name));
18718 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018719 /*
18720 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018721 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018722 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018723 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018724 }
18725 }
18726}
18727
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018728/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018729 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018730 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018731 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018732 *
18733 * Assigns the model group of model group definitions to the "term"
18734 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018735 * In xmlSchemaResolveModelGroupParticleReferences the model group
18736 * definitions were assigned to the "term", since needed for the
18737 * circularity check.
18738 *
18739 * Schema Component Constraint:
18740 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018741 */
18742static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018743xmlSchemaModelGroupToModelGroupDefFixup(
18744 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18745 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018746{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018747 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18748
18749 while (particle != NULL) {
18750 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18751 ((WXS_PARTICLE_TERM(particle))->type !=
18752 XML_SCHEMA_TYPE_GROUP))
18753 {
18754 particle = WXS_PTC_CAST particle->next;
18755 continue;
18756 }
18757 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18758 /*
18759 * TODO: Remove the particle.
18760 */
18761 WXS_PARTICLE_TERM(particle) = NULL;
18762 particle = WXS_PTC_CAST particle->next;
18763 continue;
18764 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018765 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018766 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018767 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018768 WXS_PARTICLE_TERM(particle) =
18769 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18770
18771 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018772 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018773}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018774
18775/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018776 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018777 * @ctxtGr: the searched attribute group
18778 * @attr: the current attribute list to be processed
18779 *
18780 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018781 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018782 *
18783 * Returns the circular attribute grou reference, otherwise NULL.
18784 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018785static xmlSchemaQNameRefPtr
18786xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18787 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018788{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018789 xmlSchemaAttributeGroupPtr gr;
18790 xmlSchemaQNameRefPtr ref, circ;
18791 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018792 /*
18793 * We will search for an attribute group reference which
18794 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018795 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018796 for (i = 0; i < list->nbItems; i++) {
18797 ref = list->items[i];
18798 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18799 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18800 (ref->item != NULL))
18801 {
18802 gr = WXS_ATTR_GROUP_CAST ref->item;
18803 if (gr == ctxtGr)
18804 return(ref);
18805 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18806 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018807 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018808 * Mark as visited to avoid infinite recursion on
18809 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018810 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018811 if ((gr->attrUses) &&
18812 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18813 {
18814 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18815 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18816 (xmlSchemaItemListPtr) gr->attrUses);
18817 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18818 if (circ != NULL)
18819 return (circ);
18820 }
18821
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018822 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018823 }
18824 return (NULL);
18825}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018826
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018827/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018828 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018829 * attrGr: the attribute group definition
18830 * @ctxt: the parser context
18831 * @name: the name
18832 *
18833 * Checks for circular references of attribute groups.
18834 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018835static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018836xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018837 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018838{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018839 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018840 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018841 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018842 * 3 Circular group reference is disallowed outside <redefine>.
18843 * That is, unless this element information item's parent is
18844 * <redefine>, then among the [children], if any, there must
18845 * not be an <attributeGroup> with ref [attribute] which resolves
18846 * to the component corresponding to this <attributeGroup>. Indirect
18847 * circularity is also ruled out. That is, when QName resolution
18848 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
18849 * any <attributeGroup>s with a ref [attribute] among the [children],
18850 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018851 * which resolves to the component corresponding to this <attributeGroup>.
18852 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018853 if (attrGr->attrUses == NULL)
18854 return(0);
18855 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18856 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018857 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018858 xmlSchemaQNameRefPtr circ;
18859
18860 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18861 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018862 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018863 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018864 /*
18865 * TODO: Report the referenced attr group as QName.
18866 */
18867 xmlSchemaPCustomErr(ctxt,
18868 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018869 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018870 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018871 "defined", xmlSchemaGetComponentQName(&str, attrGr));
18872 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018873 /*
18874 * NOTE: We will cut the reference to avoid further
18875 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018876 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018877 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018878 circ->item = NULL;
18879 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018880 }
18881 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018882 return(0);
18883}
18884
18885static int
18886xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
18887 xmlSchemaAttributeGroupPtr attrGr);
18888
18889/**
18890 * xmlSchemaExpandAttributeGroupRefs:
18891 * @pctxt: the parser context
18892 * @node: the node of the component holding the attribute uses
18893 * @completeWild: the intersected wildcard to be returned
18894 * @list: the attribute uses
18895 *
18896 * Substitutes contained attribute group references
18897 * for their attribute uses. Wilcards are intersected.
18898 * Attribute use prohibitions are removed from the list
18899 * and returned via the @prohibs list.
18900 * Pointlessness of attr. prohibs, if a matching attr. decl
18901 * is existent a well, are checked.
18902 */
18903static int
18904xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
18905 xmlSchemaBasicItemPtr item,
18906 xmlSchemaWildcardPtr *completeWild,
18907 xmlSchemaItemListPtr list,
18908 xmlSchemaItemListPtr prohibs)
18909{
18910 xmlSchemaAttributeGroupPtr gr;
18911 xmlSchemaAttributeUsePtr use;
18912 xmlSchemaItemListPtr sublist;
18913 int i, j;
18914 int created = (*completeWild == NULL) ? 0 : 1;
18915
18916 if (prohibs)
18917 prohibs->nbItems = 0;
18918
18919 for (i = 0; i < list->nbItems; i++) {
18920 use = list->items[i];
18921
18922 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
18923 if (prohibs == NULL) {
18924 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
18925 "unexpected attr prohibition found");
18926 return(-1);
18927 }
18928 /*
18929 * Remove from attribute uses.
18930 */
18931 if (xmlSchemaItemListRemove(list, i) == -1)
18932 return(-1);
18933 i--;
18934 /*
18935 * Note that duplicate prohibitions were already
18936 * handled at parsing time.
18937 */
18938 /*
18939 * Add to list of prohibitions.
18940 */
18941 xmlSchemaItemListAddSize(prohibs, 2, use);
18942 continue;
18943 }
18944 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18945 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
18946 {
18947 if ((WXS_QNAME_CAST use)->item == NULL)
18948 return(-1);
18949 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
18950 /*
18951 * Expand the referenced attr. group.
18952 * TODO: remove this, this is done in a previous step, so
18953 * already done here.
18954 */
18955 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
18956 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
18957 return(-1);
18958 }
18959 /*
18960 * Build the 'complete' wildcard; i.e. intersect multiple
18961 * wildcards.
18962 */
18963 if (gr->attributeWildcard != NULL) {
18964 if (*completeWild == NULL) {
18965 *completeWild = gr->attributeWildcard;
18966 } else {
18967 if (! created) {
18968 xmlSchemaWildcardPtr tmpWild;
18969
18970 /*
18971 * Copy the first encountered wildcard as context,
18972 * except for the annotation.
18973 *
18974 * Although the complete wildcard might not correspond
18975 * to any node in the schema, we will anchor it on
18976 * the node of the owner component.
18977 */
18978 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
18979 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
18980 WXS_ITEM_NODE(item));
18981 if (tmpWild == NULL)
18982 return(-1);
18983 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
18984 tmpWild, *completeWild) == -1)
18985 return (-1);
18986 tmpWild->processContents = (*completeWild)->processContents;
18987 *completeWild = tmpWild;
18988 created = 1;
18989 }
18990
18991 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
18992 gr->attributeWildcard) == -1)
18993 return(-1);
18994 }
18995 }
18996 /*
18997 * Just remove the reference if the referenced group does not
18998 * contain any attribute uses.
18999 */
19000 if (gr->attrUses == NULL) {
19001 if (xmlSchemaItemListRemove(list, i) == -1)
19002 return(-1);
19003 i--;
19004 continue;
19005 }
19006 /*
19007 * Add the attribute uses.
19008 */
19009 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19010 if (sublist->nbItems != 0) {
19011 list->items[i] = sublist->items[0];
19012 if (sublist->nbItems != 1) {
19013 for (j = 1; j < sublist->nbItems; j++) {
19014 i++;
19015 if (xmlSchemaItemListInsert(list,
19016 sublist->items[j], i) == -1)
19017 return(-1);
19018 }
19019 }
19020 }
19021 }
19022
19023 }
19024 /*
19025 * Handle pointless prohibitions of declared attributes.
19026 */
19027 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19028 xmlSchemaAttributeUseProhibPtr prohib;
19029
19030 for (i = prohibs->nbItems -1; i >= 0; i--) {
19031 prohib = prohibs->items[i];
19032 for (j = 0; j < list->nbItems; j++) {
19033 use = list->items[j];
19034
19035 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19036 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19037 {
19038 xmlChar *str = NULL;
19039
19040 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19041 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19042 prohib->node, NULL,
19043 "Skipping pointless attribute use prohibition "
19044 "'%s', since a corresponding attribute use "
19045 "exists already in the type definition",
19046 xmlSchemaFormatQName(&str,
19047 prohib->targetNamespace, prohib->name),
19048 NULL, NULL);
19049 FREE_AND_NULL(str);
19050 /*
19051 * Remove the prohibition.
19052 */
19053 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19054 return(-1);
19055 break;
19056 }
19057 }
19058 }
19059 }
19060 return(0);
19061}
19062
19063/**
19064 * xmlSchemaAttributeGroupExpandRefs:
19065 * @pctxt: the parser context
19066 * @attrGr: the attribute group definition
19067 *
19068 * Computation of:
19069 * {attribute uses} property
19070 * {attribute wildcard} property
19071 *
19072 * Substitutes contained attribute group references
19073 * for their attribute uses. Wilcards are intersected.
19074 */
19075static int
19076xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19077 xmlSchemaAttributeGroupPtr attrGr)
19078{
19079 if ((attrGr->attrUses == NULL) ||
19080 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19081 return(0);
19082
19083 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19084 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19085 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19086 return(-1);
19087 return(0);
19088}
19089
19090/**
19091 * xmlSchemaAttributeGroupExpandRefs:
19092 * @pctxt: the parser context
19093 * @attrGr: the attribute group definition
19094 *
19095 * Substitutes contained attribute group references
19096 * for their attribute uses. Wilcards are intersected.
19097 *
19098 * Schema Component Constraint:
19099 * Attribute Group Definition Properties Correct (ag-props-correct)
19100 */
19101static int
19102xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19103 xmlSchemaAttributeGroupPtr attrGr)
19104{
19105 /*
19106 * SPEC ag-props-correct
19107 * (1) "The values of the properties of an attribute group definition
19108 * must be as described in the property tableau in The Attribute
19109 * Group Definition Schema Component (§3.6.1), modulo the impact of
19110 * Missing Sub-components (§5.3);"
19111 */
19112
19113 if ((attrGr->attrUses != NULL) &&
19114 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19115 {
19116 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19117 xmlSchemaAttributeUsePtr use, tmp;
19118 int i, j, hasId = 0;
19119
19120 for (i = uses->nbItems -1; i >= 0; i--) {
19121 use = uses->items[i];
19122 /*
19123 * SPEC ag-props-correct
19124 * (2) "Two distinct members of the {attribute uses} must not have
19125 * {attribute declaration}s both of whose {name}s match and whose
19126 * {target namespace}s are identical."
19127 */
19128 if (i > 0) {
19129 for (j = i -1; j >= 0; j--) {
19130 tmp = uses->items[j];
19131 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19132 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19133 (WXS_ATTRUSE_DECL_TNS(use) ==
19134 WXS_ATTRUSE_DECL_TNS(tmp)))
19135 {
19136 xmlChar *str = NULL;
19137
19138 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19139 XML_SCHEMAP_AG_PROPS_CORRECT,
19140 attrGr->node, WXS_BASIC_CAST attrGr,
19141 "Duplicate %s",
19142 xmlSchemaGetComponentDesignation(&str, use),
19143 NULL);
19144 FREE_AND_NULL(str);
19145 /*
19146 * Remove the duplicate.
19147 */
19148 if (xmlSchemaItemListRemove(uses, i) == -1)
19149 return(-1);
19150 goto next_use;
19151 }
19152 }
19153 }
19154 /*
19155 * SPEC ag-props-correct
19156 * (3) "Two distinct members of the {attribute uses} must not have
19157 * {attribute declaration}s both of whose {type definition}s are or
19158 * are derived from ID."
19159 * TODO: Does 'derived' include member-types of unions?
19160 */
19161 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19162 if (xmlSchemaIsDerivedFromBuiltInType(
19163 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19164 {
19165 if (hasId) {
19166 xmlChar *str = NULL;
19167
19168 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19169 XML_SCHEMAP_AG_PROPS_CORRECT,
19170 attrGr->node, WXS_BASIC_CAST attrGr,
19171 "There must not exist more than one attribute "
19172 "declaration of type 'xs:ID' "
19173 "(or derived from 'xs:ID'). The %s violates this "
19174 "constraint",
19175 xmlSchemaGetComponentDesignation(&str, use),
19176 NULL);
19177 FREE_AND_NULL(str);
19178 if (xmlSchemaItemListRemove(uses, i) == -1)
19179 return(-1);
19180 }
19181 hasId = 1;
19182 }
19183 }
19184next_use: {}
19185 }
19186 }
19187 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019188}
19189
19190/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019191 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019192 * @attrgrpDecl: the schema attribute definition
19193 * @ctxt: the schema parser context
19194 * @name: the attribute name
19195 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019196 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019197 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019198static int
19199xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19200 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019201{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019202 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019203
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019204 if (ref->item != NULL)
19205 return(0);
19206 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19207 ref->name,
19208 ref->targetNamespace);
19209 if (group == NULL) {
19210 xmlSchemaPResCompAttrErr(ctxt,
19211 XML_SCHEMAP_SRC_RESOLVE,
19212 NULL, ref->node,
19213 "ref", ref->name, ref->targetNamespace,
19214 ref->itemType, NULL);
19215 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019216 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019217 ref->item = WXS_BASIC_CAST group;
19218 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019219}
19220
19221/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019222 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019223 * @item: an schema attribute declaration/use
19224 * @ctxt: a schema parser context
19225 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019226 *
19227 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019228 * Schema Component Constraint:
19229 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019230 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019231 * Validates the value constraints of an attribute declaration/use.
19232 * NOTE that this needs the simle type definitions to be already
19233 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019234 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019235static int
19236xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19237 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019238{
19239
19240 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019241 * SPEC a-props-correct (1)
19242 * "The values of the properties of an attribute declaration must
19243 * be as described in the property tableau in The Attribute
19244 * Declaration Schema Component (§3.2.1), modulo the impact of
19245 * Missing Sub-components (§5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019246 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019247
19248 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19249 return(0);
19250
19251 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019252 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019253
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019254 /*
19255 * SPEC a-props-correct (3)
19256 * "If the {type definition} is or is derived from ID then there
19257 * must not be a {value constraint}."
19258 */
19259 if (xmlSchemaIsDerivedFromBuiltInType(
19260 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19261 {
19262 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19263 XML_SCHEMAP_A_PROPS_CORRECT_3,
19264 NULL, WXS_BASIC_CAST attr,
19265 "Value constraints are not allowed if the type definition "
19266 "is or is derived from xs:ID",
19267 NULL, NULL);
19268 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019269 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019270 /*
19271 * SPEC a-props-correct (2)
19272 * "if there is a {value constraint}, the canonical lexical
19273 * representation of its value must be ·valid· with respect
19274 * to the {type definition} as defined in String Valid (§3.14.4)."
19275 * TODO: Don't care about the *cononical* stuff here, this requirement
19276 * will be removed in WXS 1.1 anyway.
19277 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019278 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019279 attr->node, WXS_ATTR_TYPEDEF(attr),
19280 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019281 1, 1, 0);
19282 if (ret != 0) {
19283 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019284 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019285 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019286 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019287 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019288 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019289 XML_SCHEMAP_A_PROPS_CORRECT_2,
19290 NULL, WXS_BASIC_CAST attr,
19291 "The value of the value constraint is not valid",
19292 NULL, NULL);
19293 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019295 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019296
19297 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019298}
19299
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019300static xmlSchemaElementPtr
19301xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19302 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019303{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019304 xmlSchemaElementPtr ret;
19305
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019306 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019307 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019308 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019309 return (ancestor);
19310
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019311 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019312 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019313 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019314 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019315 WXS_SUBST_HEAD(ancestor));
19316 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019317
19318 return (ret);
19319}
19320
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019321/**
19322 * xmlSchemaCheckElemPropsCorrect:
19323 * @ctxt: a schema parser context
19324 * @decl: the element declaration
19325 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019326 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019327 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019328 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019329 *
19330 * STATUS:
19331 * missing: (6)
19332 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019333static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019334xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19335 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019336{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019337 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019338 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019339 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019340 * SPEC (1) "The values of the properties of an element declaration
19341 * must be as described in the property tableau in The Element
19342 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
19343 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019344 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019345 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19346 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019347
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019348 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019349 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019350 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019351 * affiliation}, then {scope} must be global."
19352 */
19353 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19354 xmlSchemaPCustomErr(pctxt,
19355 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019356 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019357 "Only global element declarations can have a "
19358 "substitution group affiliation", NULL);
19359 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019360 }
19361 /*
19362 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19363 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019364 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019365 * property."
19366 */
19367 if (head == elemDecl)
19368 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019369 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019370 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19371 else
19372 circ = NULL;
19373 if (circ != NULL) {
19374 xmlChar *strA = NULL, *strB = NULL;
19375
19376 xmlSchemaPCustomErrExt(pctxt,
19377 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019378 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019379 "The element declaration '%s' defines a circular "
19380 "substitution group to element declaration '%s'",
19381 xmlSchemaGetComponentQName(&strA, circ),
19382 xmlSchemaGetComponentQName(&strB, head),
19383 NULL);
19384 FREE_AND_NULL(strA)
19385 FREE_AND_NULL(strB)
19386 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19387 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019388 /*
19389 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019390 * the {type definition}
19391 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019392 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019393 * of the {substitution group exclusions} of the {substitution group
19394 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
19395 * (if the {type definition} is complex) or as defined in
19396 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019397 * simple)."
19398 *
19399 * NOTE: {substitution group exclusions} means the values of the
19400 * attribute "final".
19401 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019402
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019403 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019404 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019405
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019406 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19407 set |= SUBSET_EXTENSION;
19408 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19409 set |= SUBSET_RESTRICTION;
19410
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019411 if (xmlSchemaCheckCOSDerivedOK(pctxt, typeDef,
19412 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019413 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19414
19415 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019416 xmlSchemaPCustomErrExt(pctxt,
19417 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019418 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019419 "The type definition '%s' was "
19420 "either rejected by the substitution group "
19421 "affiliation '%s', or not validly derived from its type "
19422 "definition '%s'",
19423 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019424 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019425 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019426 FREE_AND_NULL(strA)
19427 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019428 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019429 }
19430 }
19431 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019432 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019433 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019434 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019435 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019436 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019437 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019438 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019439 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019440 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019441 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019442 (WXS_IS_COMPLEX(typeDef) &&
19443 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019444 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19445 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019446
19447 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19448 xmlSchemaPCustomErr(pctxt,
19449 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019450 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019451 "The type definition (or type definition's content type) is or "
19452 "is derived from ID; value constraints are not allowed in "
19453 "conjunction with such a type definition", NULL);
19454 } else if (elemDecl->value != NULL) {
19455 int vcret;
19456 xmlNodePtr node = NULL;
19457
19458 /*
19459 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19460 * representation of its value must be ·valid· with respect to the
19461 * {type definition} as defined in Element Default Valid (Immediate)
19462 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019463 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019464 if (typeDef == NULL) {
19465 xmlSchemaPErr(pctxt, elemDecl->node,
19466 XML_SCHEMAP_INTERNAL,
19467 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19468 "type is missing... skipping validation of "
19469 "the value constraint", NULL, NULL);
19470 return (-1);
19471 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019472 if (elemDecl->node != NULL) {
19473 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19474 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19475 BAD_CAST "fixed");
19476 else
19477 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19478 BAD_CAST "default");
19479 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019480 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19481 typeDef, elemDecl->value, &(elemDecl->defVal));
19482 if (vcret != 0) {
19483 if (vcret < 0) {
19484 PERROR_INT("xmlSchemaElemCheckValConstr",
19485 "failed to validate the value constraint of an "
19486 "element declaration");
19487 return (-1);
19488 }
19489 return (vcret);
19490 }
19491 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019492
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019493 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019494}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019495
19496/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019497 * xmlSchemaCheckElemSubstGroup:
19498 * @ctxt: a schema parser context
19499 * @decl: the element declaration
19500 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019501 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019502 * Schema Component Constraint:
19503 * Substitution Group (cos-equiv-class)
19504 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019505 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019506 * a list will be built for each subst. group head, holding all direct
19507 * referents to this head.
19508 * NOTE that this function needs:
19509 * 1. circular subst. groups to be checked beforehand
19510 * 2. the declaration's type to be derived from the head's type
19511 *
19512 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019513 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019514 */
19515static void
19516xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19517 xmlSchemaElementPtr elemDecl)
19518{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019519 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019520 /* SPEC (1) "Its {abstract} is false." */
19521 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19522 return;
19523 {
19524 xmlSchemaElementPtr head;
19525 xmlSchemaTypePtr headType, type;
19526 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019527 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019528 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19529 * {disallowed substitutions} as the blocking constraint, as defined in
19530 * Substitution Group OK (Transitive) (§3.3.6)."
19531 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019532 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19533 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019534 set = 0;
19535 methSet = 0;
19536 /*
19537 * The blocking constraints.
19538 */
19539 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19540 continue;
19541 headType = head->subtypes;
19542 type = elemDecl->subtypes;
19543 if (headType == type)
19544 goto add_member;
19545 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19546 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19547 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19548 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19549 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019550 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019551 * "The set of all {derivation method}s involved in the
19552 * derivation of D's {type definition} from C's {type definition}
19553 * does not intersect with the union of the blocking constraint,
19554 * C's {prohibited substitutions} (if C is complex, otherwise the
19555 * empty set) and the {prohibited substitutions} (respectively the
19556 * empty set) of any intermediate {type definition}s in the
19557 * derivation of D's {type definition} from C's {type definition}."
19558 */
19559 /*
19560 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19561 * subst.head axis, the methSet does not need to be computed for
19562 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019563 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019564 /*
19565 * The set of all {derivation method}s involved in the derivation
19566 */
19567 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019568 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019569 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19570 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019571
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019572 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019573 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19574 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19575
19576 type = type->baseType;
19577 }
19578 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019579 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019580 * the head's type.
19581 */
19582 type = elemDecl->subtypes->baseType;
19583 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019584 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019585 if ((type->flags &
19586 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19587 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19588 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19589 if ((type->flags &
19590 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19591 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19592 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19593 } else
19594 break;
19595 if (type == headType)
19596 break;
19597 type = type->baseType;
19598 }
19599 if ((set != 0) &&
19600 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19601 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19602 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19603 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19604 continue;
19605 }
19606add_member:
19607 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19608 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19609 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19610 }
19611 }
19612}
19613
19614/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019615 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019616 * @item: an schema element declaration/particle
19617 * @ctxt: a schema parser context
19618 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019619 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019620 * Validates the value constraints of an element declaration.
19621 *
19622 * Fixes finish doing the computations on the element declarations.
19623 */
19624static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019625xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019626 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019627{
19628 if (elemDecl == NULL)
19629 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019630 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19631 return;
19632 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019633 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19634 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019635}
19636
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019637/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019638 * xmlSchemaResolveModelGroupParticleReferences:
19639 * @particle: a particle component
19640 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019641 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019642 * Resolves references of a model group's {particles} to
19643 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019644 */
19645static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019646xmlSchemaResolveModelGroupParticleReferences(
19647 xmlSchemaParserCtxtPtr ctxt,
19648 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019649{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019650 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19651 xmlSchemaQNameRefPtr ref;
19652 xmlSchemaBasicItemPtr refItem;
19653
19654 /*
19655 * URGENT TODO: Test this.
19656 */
19657 while (particle != NULL) {
19658 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19659 ((WXS_PARTICLE_TERM(particle))->type !=
19660 XML_SCHEMA_EXTRA_QNAMEREF))
19661 {
19662 goto next_particle;
19663 }
19664 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019665 /*
19666 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019667 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019668 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019669 particle->children = NULL;
19670
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019671 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19672 ref->itemType, ref->name, ref->targetNamespace);
19673 if (refItem == NULL) {
19674 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019675 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019676 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019677 /* TODO: remove the particle. */
19678 goto next_particle;
19679 }
19680 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19681 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19682 /* TODO: remove the particle. */
19683 goto next_particle;
19684 /*
19685 * NOTE that we will assign the model group definition
19686 * itself to the "term" of the particle. This will ease
19687 * the check for circular model group definitions. After
19688 * that the "term" will be assigned the model group of the
19689 * model group definition.
19690 */
19691 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19692 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019693 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019694 * SPEC cos-all-limited (1)
19695 * SPEC cos-all-limited (1.2)
19696 * "It appears only as the value of one or both of the
19697 * following properties:"
19698 * (1.1) "the {model group} property of a model group
19699 * definition."
19700 * (1.2) "the {term} property of a particle [... of] the "
19701 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019702 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019703 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19704 /* TODO: error code */
19705 XML_SCHEMAP_COS_ALL_LIMITED,
19706 WXS_ITEM_NODE(particle), NULL,
19707 "A model group definition is referenced, but "
19708 "it contains an 'all' model group, which "
19709 "cannot be contained by model groups",
19710 NULL, NULL);
19711 /* TODO: remove the particle. */
19712 goto next_particle;
19713 }
19714 particle->children = (xmlSchemaTreeItemPtr) refItem;
19715 } else {
19716 /*
19717 * TODO: Are referenced element declarations the only
19718 * other components we expect here?
19719 */
19720 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019721 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019722next_particle:
19723 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019724 }
19725}
19726
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019727static int
19728xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19729 xmlSchemaValPtr y)
19730{
19731 xmlSchemaTypePtr tx, ty, ptx, pty;
19732 int ret;
19733
19734 while (x != NULL) {
19735 /* Same types. */
19736 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19737 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19738 ptx = xmlSchemaGetPrimitiveType(tx);
19739 pty = xmlSchemaGetPrimitiveType(ty);
19740 /*
19741 * (1) if a datatype T' is ·derived· by ·restriction· from an
19742 * atomic datatype T then the ·value space· of T' is a subset of
19743 * the ·value space· of T. */
19744 /*
19745 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
19746 * from a common atomic ancestor T then the ·value space·s of T'
19747 * and T'' may overlap.
19748 */
19749 if (ptx != pty)
19750 return(0);
19751 /*
19752 * We assume computed values to be normalized, so do a fast
19753 * string comparison for string based types.
19754 */
19755 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019756 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019757 if (! xmlStrEqual(
19758 xmlSchemaValueGetAsString(x),
19759 xmlSchemaValueGetAsString(y)))
19760 return (0);
19761 } else {
19762 ret = xmlSchemaCompareValuesWhtsp(
19763 x, XML_SCHEMA_WHITESPACE_PRESERVE,
19764 y, XML_SCHEMA_WHITESPACE_PRESERVE);
19765 if (ret == -2)
19766 return(-1);
19767 if (ret != 0)
19768 return(0);
19769 }
19770 /*
19771 * Lists.
19772 */
19773 x = xmlSchemaValueGetNext(x);
19774 if (x != NULL) {
19775 y = xmlSchemaValueGetNext(y);
19776 if (y == NULL)
19777 return (0);
19778 } else if (xmlSchemaValueGetNext(y) != NULL)
19779 return (0);
19780 else
19781 return (1);
19782 }
19783 return (0);
19784}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019785
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019786/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019787 * xmlSchemaResolveAttrUseReferences:
19788 * @item: an attribute use
19789 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019790 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019791 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019792 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019793static int
19794xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19795 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000019796{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019797 if ((ctxt == NULL) || (ause == NULL))
19798 return(-1);
19799 if ((ause->attrDecl == NULL) ||
19800 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19801 return(0);
19802
19803 {
19804 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19805
19806 /*
19807 * TODO: Evaluate, what errors could occur if the declaration is not
19808 * found.
19809 */
19810 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19811 ref->name, ref->targetNamespace);
19812 if (ause->attrDecl == NULL) {
19813 xmlSchemaPResCompAttrErr(ctxt,
19814 XML_SCHEMAP_SRC_RESOLVE,
19815 WXS_BASIC_CAST ause, ause->node,
19816 "ref", ref->name, ref->targetNamespace,
19817 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19818 return(ctxt->err);;
19819 }
19820 }
19821 return(0);
19822}
19823
19824/**
19825 * xmlSchemaCheckAttrUsePropsCorrect:
19826 * @ctxt: a parser context
19827 * @use: an attribute use
19828 *
19829 * Schema Component Constraint:
19830 * Attribute Use Correct (au-props-correct)
19831 *
19832 */
19833static int
19834xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19835 xmlSchemaAttributeUsePtr use)
19836{
19837 if ((ctxt == NULL) || (use == NULL))
19838 return(-1);
19839 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19840 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19841 return(0);
19842
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019843 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019844 * SPEC au-props-correct (1)
19845 * "The values of the properties of an attribute use must be as
19846 * described in the property tableau in The Attribute Use Schema
19847 * Component (§3.5.1), modulo the impact of Missing
19848 * Sub-components (§5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000019849 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019850
19851 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19852 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19853 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19854 {
19855 xmlSchemaPCustomErr(ctxt,
19856 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19857 WXS_BASIC_CAST use, NULL,
19858 "The attribute declaration has a 'fixed' value constraint "
19859 ", thus the attribute use must also have a 'fixed' value "
19860 "constraint",
19861 NULL);
19862 return(ctxt->err);
19863 }
19864 /*
19865 * Compute and check the value constraint's value.
19866 */
19867 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19868 int ret;
19869 /*
19870 * TODO: The spec seems to be missing a check of the
19871 * value constraint of the attribute use. We will do it here.
19872 */
19873 /*
19874 * SPEC a-props-correct (3)
19875 */
19876 if (xmlSchemaIsDerivedFromBuiltInType(
19877 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19878 {
19879 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19880 XML_SCHEMAP_AU_PROPS_CORRECT,
19881 NULL, WXS_BASIC_CAST use,
19882 "Value constraints are not allowed if the type definition "
19883 "is or is derived from xs:ID",
19884 NULL, NULL);
19885 return(ctxt->err);
19886 }
19887
19888 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
19889 use->node, WXS_ATTRUSE_TYPEDEF(use),
19890 use->defValue, &(use->defVal),
19891 1, 1, 0);
19892 if (ret != 0) {
19893 if (ret < 0) {
19894 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
19895 "calling xmlSchemaVCheckCVCSimpleType()");
19896 return(-1);
19897 }
19898 xmlSchemaCustomErr(ACTXT_CAST ctxt,
19899 XML_SCHEMAP_AU_PROPS_CORRECT,
19900 NULL, WXS_BASIC_CAST use,
19901 "The value of the value constraint is not valid",
19902 NULL, NULL);
19903 return(ctxt->err);
19904 }
19905 }
19906 /*
19907 * SPEC au-props-correct (2)
19908 * "If the {attribute declaration} has a fixed
19909 * {value constraint}, then if the attribute use itself has a
19910 * {value constraint}, it must also be fixed and its value must match
19911 * that of the {attribute declaration}'s {value constraint}."
19912 */
19913 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
19914 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19915 {
19916 if (! xmlSchemaAreValuesEqual(use->defVal,
19917 (WXS_ATTRUSE_DECL(use))->defVal))
19918 {
19919 xmlSchemaPCustomErr(ctxt,
19920 XML_SCHEMAP_AU_PROPS_CORRECT_2,
19921 WXS_BASIC_CAST use, NULL,
19922 "The 'fixed' value constraint of the attribute use "
19923 "must match the attribute declaration's value "
19924 "constraint '%s'",
19925 (WXS_ATTRUSE_DECL(use))->defValue);
19926 }
19927 return(ctxt->err);
19928 }
19929 return(0);
19930}
19931
19932
19933
19934
19935/**
19936 * xmlSchemaResolveAttrTypeReferences:
19937 * @item: an attribute declaration
19938 * @ctxt: a parser context
19939 *
19940 * Resolves the referenced type definition component.
19941 */
19942static int
19943xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
19944 xmlSchemaParserCtxtPtr ctxt)
19945{
Daniel Veillard01fa6152004-06-29 17:04:39 +000019946 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019947 * The simple type definition corresponding to the <simpleType> element
19948 * information item in the [children], if present, otherwise the simple
19949 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019950 * [attribute], if present, otherwise the ·simple ur-type definition·.
19951 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019952 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019953 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019954 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
19955 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019956 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019957 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019958 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000019959
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019960 type = xmlSchemaGetType(ctxt->schema, item->typeName,
19961 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019962 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019963 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019964 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019965 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019966 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019967 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019968 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019969 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019970 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019971
Daniel Veillard3646d642004-06-02 19:19:14 +000019972 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019973 /*
19974 * The type defaults to the xs:anySimpleType.
19975 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019976 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
19977 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019978 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000019979}
19980
19981/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019982 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019983 * @idc: the identity-constraint definition
19984 * @ctxt: the schema parser context
19985 * @name: the attribute name
19986 *
19987 * Resolve keyRef references to key/unique IDCs.
19988 */
19989static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019990xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019991 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019992{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019993 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
19994 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019995 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019996 idc->ref->item = (xmlSchemaBasicItemPtr)
19997 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
19998 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019999 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020000 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020001 * TODO: It is actually not an error to fail to resolve
20002 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020003 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020004 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020005 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020006 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020007 "refer", idc->ref->name,
20008 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020009 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020010 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020011 } else {
20012 if (idc->nbFields !=
20013 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20014 xmlChar *str = NULL;
20015 xmlSchemaIDCPtr refer;
20016
20017 refer = (xmlSchemaIDCPtr) idc->ref->item;
20018 /*
20019 * SPEC c-props-correct(2)
20020 * "If the {identity-constraint category} is keyref,
20021 * the cardinality of the {fields} must equal that of
20022 * the {fields} of the {referenced key}.
20023 */
20024 xmlSchemaPCustomErr(pctxt,
20025 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020026 WXS_BASIC_CAST idc, NULL,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020027 "The cardinality of the keyref differs from the "
20028 "cardinality of the referenced key '%s'",
20029 xmlSchemaFormatQName(&str, refer->targetNamespace,
20030 refer->name)
20031 );
20032 FREE_AND_NULL(str)
20033 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020034 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020035 }
20036}
20037
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020038static int
20039xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20040 xmlSchemaParserCtxtPtr pctxt)
20041{
20042 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20043 prohib->targetNamespace) == NULL) {
20044
20045 xmlSchemaPResCompAttrErr(pctxt,
20046 XML_SCHEMAP_SRC_RESOLVE,
20047 NULL, prohib->node,
20048 "ref", prohib->name, prohib->targetNamespace,
20049 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20050 return(XML_SCHEMAP_SRC_RESOLVE);
20051 }
20052 return(0);
20053}
20054
20055#define WXS_REDEFINED_TYPE(c) \
20056(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20057
20058#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20059(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20060
20061#define WXS_REDEFINED_ATTR_GROUP(c) \
20062(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20063
20064static int
20065xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20066{
20067 int err = 0;
20068 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20069 xmlSchemaBasicItemPtr prev, item;
20070 int wasRedefined;
20071
20072 if (redef == NULL)
20073 return(0);
20074
20075 do {
20076 item = redef->item;
20077 /*
20078 * First try to locate the redefined component in the
20079 * schema graph starting with the redefined schema.
20080 */
20081 prev = xmlSchemaFindRedefCompInGraph(
20082 redef->targetBucket, item->type,
20083 redef->refName, redef->refTargetNs);
20084 if (prev == NULL) {
20085 xmlChar *str = NULL;
20086 xmlNodePtr node;
20087
20088 /*
20089 * SPEC src-redefine:
20090 * (6.2.1) "The ·actual value· of its own name attribute plus
20091 * target namespace must successfully ·resolve· to a model
20092 * group definition in I."
20093 * (7.2.1) "The ·actual value· of its own name attribute plus
20094 * target namespace must successfully ·resolve· to an attribute
20095 * group definition in I."
20096
20097 *
20098 * Note that, if we are redefining with the use of references
20099 * to components, the spec assumes the src-resolve to be used;
20100 * but this won't assure that we search only *inside* the
20101 * redefined schema.
20102 */
20103 if (redef->reference)
20104 node = WXS_ITEM_NODE(redef->reference);
20105 else
20106 node = WXS_ITEM_NODE(item);
20107 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20108 /*
20109 * TODO: error code.
20110 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20111 * reference kind.
20112 */
20113 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20114 "The %s to be redefined could not be found in "
20115 "the redefined schema",
20116 WXS_ITEM_TYPE_NAME(item),
20117 xmlSchemaFormatQName(&str, redef->refTargetNs,
20118 redef->refName));
20119 FREE_AND_NULL(str);
20120 err = pctxt->err;
20121 redef = redef->next;
20122 continue;
20123 }
20124 /*
20125 * TODO: Obtaining and setting the redefinition state is really
20126 * clumsy.
20127 */
20128 wasRedefined = 0;
20129 switch (item->type) {
20130 case XML_SCHEMA_TYPE_COMPLEX:
20131 case XML_SCHEMA_TYPE_SIMPLE:
20132 if ((WXS_TYPE_CAST prev)->flags &
20133 XML_SCHEMAS_TYPE_REDEFINED)
20134 {
20135 wasRedefined = 1;
20136 break;
20137 }
20138 /* Mark it as redefined. */
20139 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20140 /*
20141 * Assign the redefined type to the
20142 * base type of the redefining type.
20143 * TODO: How
20144 */
20145 ((xmlSchemaTypePtr) item)->baseType =
20146 (xmlSchemaTypePtr) prev;
20147 break;
20148 case XML_SCHEMA_TYPE_GROUP:
20149 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20150 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20151 {
20152 wasRedefined = 1;
20153 break;
20154 }
20155 /* Mark it as redefined. */
20156 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20157 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20158 if (redef->reference != NULL) {
20159 /*
20160 * Overwrite the QName-reference with the
20161 * referenced model group def.
20162 */
20163 (WXS_PTC_CAST redef->reference)->children =
20164 WXS_TREE_CAST prev;
20165 }
20166 redef->target = prev;
20167 break;
20168 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20169 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20170 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20171 {
20172 wasRedefined = 1;
20173 break;
20174 }
20175 (WXS_ATTR_GROUP_CAST prev)->flags |=
20176 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20177 if (redef->reference != NULL) {
20178 /*
20179 * Assign the redefined attribute group to the
20180 * QName-reference component.
20181 * This is the easy case, since we will just
20182 * expand the redefined group.
20183 */
20184 (WXS_QNAME_CAST redef->reference)->item = prev;
20185 redef->target = NULL;
20186 } else {
20187 /*
20188 * This is the complicated case: we need
20189 * to apply src-redefine (7.2.2) at a later
20190 * stage, i.e. when attribute group references
20191 * have beed expanded and simple types have
20192 * beed fixed.
20193 */
20194 redef->target = prev;
20195 }
20196 break;
20197 default:
20198 PERROR_INT("xmlSchemaResolveRedefReferences",
20199 "Unexpected redefined component type");
20200 return(-1);
20201 }
20202 if (wasRedefined) {
20203 xmlChar *str = NULL;
20204 xmlNodePtr node;
20205
20206 if (redef->reference)
20207 node = WXS_ITEM_NODE(redef->reference);
20208 else
20209 node = WXS_ITEM_NODE(redef->item);
20210
20211 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20212 /* TODO: error code. */
20213 XML_SCHEMAP_SRC_REDEFINE,
20214 node, NULL,
20215 "The referenced %s was already redefined. Multiple "
20216 "redefinition of the same component is not supported",
20217 xmlSchemaGetComponentDesignation(&str, prev),
20218 NULL);
20219 FREE_AND_NULL(str)
20220 err = pctxt->err;
20221 redef = redef->next;
20222 continue;
20223 }
20224 redef = redef->next;
20225 } while (redef != NULL);
20226
20227 return(err);
20228}
20229
20230static int
20231xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20232{
20233 int err = 0;
20234 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20235 xmlSchemaBasicItemPtr item;
20236
20237 if (redef == NULL)
20238 return(0);
20239
20240 do {
20241 if (redef->target == NULL) {
20242 redef = redef->next;
20243 continue;
20244 }
20245 item = redef->item;
20246
20247 switch (item->type) {
20248 case XML_SCHEMA_TYPE_SIMPLE:
20249 case XML_SCHEMA_TYPE_COMPLEX:
20250 /*
20251 * Since the spec wants the {name} of the redefined
20252 * type to be 'absent', we'll NULL it.
20253 */
20254 (WXS_TYPE_CAST redef->target)->name = NULL;
20255
20256 /*
20257 * TODO: Seems like there's nothing more to do. The normal
20258 * inheritance mechanism is used. But not 100% sure.
20259 */
20260 break;
20261 case XML_SCHEMA_TYPE_GROUP:
20262 /*
20263 * URGENT TODO:
20264 * SPEC src-redefine:
20265 * (6.2.2) "The {model group} of the model group definition
20266 * which corresponds to it per XML Representation of Model
20267 * Group Definition Schema Components (§3.7.2) must be a
20268 * ·valid restriction· of the {model group} of that model
20269 * group definition in I, as defined in Particle Valid
20270 * (Restriction) (§3.9.6)."
20271 */
20272 break;
20273 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20274 /*
20275 * SPEC src-redefine:
20276 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20277 * the attribute group definition which corresponds to it
20278 * per XML Representation of Attribute Group Definition Schema
20279 * Components (§3.6.2) must be ·valid restrictions· of the
20280 * {attribute uses} and {attribute wildcard} of that attribute
20281 * group definition in I, as defined in clause 2, clause 3 and
20282 * clause 4 of Derivation Valid (Restriction, Complex)
20283 * (§3.4.6) (where references to the base type definition are
20284 * understood as references to the attribute group definition
20285 * in I)."
20286 */
20287 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20288 XML_SCHEMA_ACTION_REDEFINE,
20289 item, redef->target,
20290 (WXS_ATTR_GROUP_CAST item)->attrUses,
20291 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20292 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20293 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20294 if (err == -1)
20295 return(-1);
20296 break;
20297 default:
20298 break;
20299 }
20300 redef = redef->next;
20301 } while (redef != NULL);
20302 return(0);
20303}
20304
20305
20306static int
20307xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20308 xmlSchemaBucketPtr bucket)
20309{
20310 xmlSchemaBasicItemPtr item;
20311 int err;
20312 xmlHashTablePtr *table;
20313 const xmlChar *name;
20314 int i;
20315
20316#define WXS_GET_GLOBAL_HASH(c, s, slot) { \
20317 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20318 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20319 else \
20320 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20321
20322 /*
20323 * Add global components to the schema's hash tables.
20324 * This is the place where duplicate components will be
20325 * detected.
20326 */
20327 if (bucket == NULL)
20328 return(-1);
20329 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20330 return(0);
20331 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20332
20333 for (i = 0; i < bucket->globals->nbItems; i++) {
20334 item = bucket->globals->items[i];
20335 table = NULL;
20336 switch (item->type) {
20337 case XML_SCHEMA_TYPE_COMPLEX:
20338 case XML_SCHEMA_TYPE_SIMPLE:
20339 if (WXS_REDEFINED_TYPE(item))
20340 continue;
20341 name = (WXS_TYPE_CAST item)->name;
20342 WXS_GET_GLOBAL_HASH(bucket, schema, typeDecl)
20343 break;
20344 case XML_SCHEMA_TYPE_ELEMENT:
20345 name = (WXS_ELEM_CAST item)->name;
20346 WXS_GET_GLOBAL_HASH(bucket, schema, elemDecl)
20347 break;
20348 case XML_SCHEMA_TYPE_ATTRIBUTE:
20349 name = (WXS_ATTR_CAST item)->name;
20350 WXS_GET_GLOBAL_HASH(bucket, schema, attrDecl)
20351 break;
20352 case XML_SCHEMA_TYPE_GROUP:
20353 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20354 continue;
20355 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20356 WXS_GET_GLOBAL_HASH(bucket, schema, groupDecl)
20357 break;
20358 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20359 if (WXS_REDEFINED_ATTR_GROUP(item))
20360 continue;
20361 name = (WXS_ATTR_GROUP_CAST item)->name;
20362 WXS_GET_GLOBAL_HASH(bucket, schema, attrgrpDecl)
20363 break;
20364 case XML_SCHEMA_TYPE_IDC_KEY:
20365 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20366 case XML_SCHEMA_TYPE_IDC_KEYREF:
20367 name = (WXS_IDC_CAST item)->name;
20368 WXS_GET_GLOBAL_HASH(bucket, schema, idcDef)
20369 break;
20370 case XML_SCHEMA_TYPE_NOTATION:
20371 name = ((xmlSchemaNotationPtr) item)->name;
20372 WXS_GET_GLOBAL_HASH(bucket, schema, notaDecl)
20373 break;
20374 default:
20375 PERROR_INT("xmlSchemaAddComponents",
20376 "Unexpected global component type");
20377 continue;
20378 }
20379 if (*table == NULL) {
20380 *table = xmlHashCreateDict(10, pctxt->dict);
20381 if (*table == NULL) {
20382 PERROR_INT("xmlSchemaAddComponents",
20383 "failed to create a component hash table");
20384 return(-1);
20385 }
20386 }
20387 err = xmlHashAddEntry(*table, name, item);
20388 if (err != 0) {
20389 xmlChar *str = NULL;
20390
20391 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20392 XML_SCHEMAP_REDEFINED_TYPE,
20393 WXS_ITEM_NODE(item),
20394 WXS_BASIC_CAST item,
20395 "A global %s '%s' does already exist",
20396 WXS_ITEM_TYPE_NAME(item),
20397 xmlSchemaGetComponentQName(&str, item));
20398 FREE_AND_NULL(str);
20399 }
20400 }
20401 /*
20402 * Process imported/included schemas.
20403 */
20404 if (bucket->relations != NULL) {
20405 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20406 do {
20407 if ((rel->bucket != NULL) &&
20408 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20409 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20410 return(-1);
20411 }
20412 rel = rel->next;
20413 } while (rel != NULL);
20414 }
20415 return(0);
20416}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020417
20418static int
20419xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
20420{
20421 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20422 xmlSchemaTreeItemPtr item, *items;
20423 int nbItems, i;
20424
20425#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20426
20427 if ((con->pending == NULL) ||
20428 (con->pending->nbItems == 0))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020429 return(0);
20430
20431 /* TODO:
20432 * SPEC (src-redefine):
20433 * (6.2) "If it has no such self-reference, then all of the
20434 * following must be true:"
20435
20436 * (6.2.2) The {model group} of the model group definition which
20437 * corresponds to it per XML Representation of Model Group
20438 * Definition Schema Components (§3.7.2) must be a ·valid
20439 * restriction· of the {model group} of that model group definition
20440 * in I, as defined in Particle Valid (Restriction) (§3.9.6)."
20441 */
20442 xmlSchemaCheckSRCRedefineFirst(pctxt);
20443
20444 /*
20445 * Add global components to the schemata's hash tables.
20446 */
20447 xmlSchemaAddComponents(pctxt, WXS_CONSTRUCTOR(pctxt)->mainBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020448
20449 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020450 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20451 nbItems = con->pending->nbItems;
20452 /*
20453 * Now that we have parsed *all* the schema document(s) and converted
20454 * them to schema components, we can resolve references, apply component
20455 * constraints, create the FSA from the content model, etc.
20456 */
20457 /*
20458 * Resolve references of..
20459 *
20460 * 1. element declarations:
20461 * - the type definition
20462 * - the substitution group affiliation
20463 * 2. simple/complex types:
20464 * - the base type definition
20465 * - the memberTypes of union types
20466 * - the itemType of list types
20467 * 3. attributes declarations and attribute uses:
20468 * - the type definition
20469 * - if an attribute use, then the attribute declaration
20470 * 4. attribute group references:
20471 * - the attribute group definition
20472 * 5. particles:
20473 * - the term of the particle (e.g. a model group)
20474 * 6. IDC key-references:
20475 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020476 * 7. Attribute prohibitions which had a "ref" attribute.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020477 */
20478 for (i = 0; i < nbItems; i++) {
20479 item = items[i];
20480 switch (item->type) {
20481 case XML_SCHEMA_TYPE_ELEMENT:
20482 xmlSchemaResolveElementReferences(
20483 (xmlSchemaElementPtr) item, pctxt);
20484 FIXHFAILURE;
20485 break;
20486 case XML_SCHEMA_TYPE_COMPLEX:
20487 case XML_SCHEMA_TYPE_SIMPLE:
20488 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020489 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020490 FIXHFAILURE;
20491 break;
20492 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020493 xmlSchemaResolveAttrTypeReferences(
20494 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020495 FIXHFAILURE;
20496 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020497 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20498 xmlSchemaResolveAttrUseReferences(
20499 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020500 FIXHFAILURE;
20501 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020502 case XML_SCHEMA_EXTRA_QNAMEREF:
20503 if ((WXS_QNAME_CAST item)->itemType ==
20504 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20505 {
20506 xmlSchemaResolveAttrGroupReferences(
20507 WXS_QNAME_CAST item, pctxt);
20508 }
20509 FIXHFAILURE;
20510 break;
20511 case XML_SCHEMA_TYPE_SEQUENCE:
20512 case XML_SCHEMA_TYPE_CHOICE:
20513 case XML_SCHEMA_TYPE_ALL:
20514 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20515 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020516 FIXHFAILURE;
20517 break;
20518 case XML_SCHEMA_TYPE_IDC_KEY:
20519 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20520 case XML_SCHEMA_TYPE_IDC_KEYREF:
20521 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020522 (xmlSchemaIDCPtr) item, pctxt);
20523 FIXHFAILURE;
20524 break;
20525 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20526 /*
20527 * Handle attribue prohibition which had a
20528 * "ref" attribute.
20529 */
20530 xmlSchemaResolveAttrUseProhibReferences(
20531 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020532 FIXHFAILURE;
20533 break;
20534 default:
20535 break;
20536 }
20537 }
20538 if (pctxt->nberrors != 0)
20539 goto exit_error;
20540
20541 /*
20542 * Now that all references are resolved we
20543 * can check for circularity of...
20544 * 1. the base axis of type definitions
20545 * 2. nested model group definitions
20546 * 3. nested attribute group definitions
20547 * TODO: check for circual substitution groups.
20548 */
20549 for (i = 0; i < nbItems; i++) {
20550 item = items[i];
20551 /*
20552 * Let's better stop on the first error here.
20553 */
20554 switch (item->type) {
20555 case XML_SCHEMA_TYPE_COMPLEX:
20556 case XML_SCHEMA_TYPE_SIMPLE:
20557 xmlSchemaCheckTypeDefCircular(
20558 (xmlSchemaTypePtr) item, pctxt);
20559 FIXHFAILURE;
20560 if (pctxt->nberrors != 0)
20561 goto exit_error;
20562 break;
20563 case XML_SCHEMA_TYPE_GROUP:
20564 xmlSchemaCheckGroupDefCircular(
20565 (xmlSchemaModelGroupDefPtr) item, pctxt);
20566 FIXHFAILURE;
20567 if (pctxt->nberrors != 0)
20568 goto exit_error;
20569 break;
20570 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20571 xmlSchemaCheckAttrGroupCircular(
20572 (xmlSchemaAttributeGroupPtr) item, pctxt);
20573 FIXHFAILURE;
20574 if (pctxt->nberrors != 0)
20575 goto exit_error;
20576 break;
20577 default:
20578 break;
20579 }
20580 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020581 if (pctxt->nberrors != 0)
20582 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020583 /*
20584 * Model group definition references:
20585 * Such a reference is reflected by a particle at the component
20586 * level. Until now the 'term' of such particles pointed
20587 * to the model group definition; this was done, in order to
20588 * ease circularity checks. Now we need to set the 'term' of
20589 * such particles to the model group of the model group definition.
20590 */
20591 for (i = 0; i < nbItems; i++) {
20592 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020593 switch (item->type) {
20594 case XML_SCHEMA_TYPE_SEQUENCE:
20595 case XML_SCHEMA_TYPE_CHOICE:
20596 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20597 WXS_MODEL_GROUP_CAST item);
20598 break;
20599 default:
20600 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020601 }
20602 }
20603 if (pctxt->nberrors != 0)
20604 goto exit_error;
20605 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020606 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020607 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020608 for (i = 0; i < nbItems; i++) {
20609 item = items[i];
20610 switch (item->type) {
20611 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20612 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20613 WXS_ATTR_GROUP_HAS_REFS(item))
20614 {
20615 xmlSchemaAttributeGroupExpandRefs(pctxt,
20616 WXS_ATTR_GROUP_CAST item);
20617 FIXHFAILURE;
20618 }
20619 break;
20620 default:
20621 break;
20622 }
20623 }
20624 if (pctxt->nberrors != 0)
20625 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020626 /*
20627 * First compute the variety of simple types. This is needed as
20628 * a seperate step, since otherwise we won't be able to detect
20629 * circular union types in all cases.
20630 */
20631 for (i = 0; i < nbItems; i++) {
20632 item = items[i];
20633 switch (item->type) {
20634 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020635 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020636 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20637 (xmlSchemaTypePtr) item);
20638 FIXHFAILURE;
20639 }
20640 break;
20641 default:
20642 break;
20643 }
20644 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020645 if (pctxt->nberrors != 0)
20646 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020647 /*
20648 * Detect circular union types. Note that this needs the variety to
20649 * be already computed.
20650 */
20651 for (i = 0; i < nbItems; i++) {
20652 item = items[i];
20653 switch (item->type) {
20654 case XML_SCHEMA_TYPE_SIMPLE:
20655 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20656 xmlSchemaCheckUnionTypeDefCircular(pctxt,
20657 (xmlSchemaTypePtr) item);
20658 FIXHFAILURE;
20659 }
20660 break;
20661 default:
20662 break;
20663 }
20664 }
20665 if (pctxt->nberrors != 0)
20666 goto exit_error;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020667
20668 /*
20669 * Do the complete type fixup for simple types.
20670 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020671 for (i = 0; i < nbItems; i++) {
20672 item = items[i];
20673 switch (item->type) {
20674 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020675 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20676 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20677 FIXHFAILURE;
20678 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020679 break;
20680 default:
20681 break;
20682 }
20683 }
20684 if (pctxt->nberrors != 0)
20685 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020686 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020687 * At this point we need all simple types to be builded and checked.
20688 */
20689 /*
20690 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020691 */
20692 for (i = 0; i < nbItems; i++) {
20693 item = items[i];
20694 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020695 case XML_SCHEMA_TYPE_ATTRIBUTE:
20696 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20697 FIXHFAILURE;
20698 break;
20699 default:
20700 break;
20701 }
20702 }
20703 if (pctxt->nberrors != 0)
20704 goto exit_error;
20705 /*
20706 * Apply constraints for attribute uses.
20707 */
20708 for (i = 0; i < nbItems; i++) {
20709 item = items[i];
20710 switch (item->type) {
20711 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20712 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20713 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20714 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020715 FIXHFAILURE;
20716 }
20717 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020718 default:
20719 break;
20720 }
20721 }
20722 if (pctxt->nberrors != 0)
20723 goto exit_error;
20724
20725 /*
20726 * Apply constraints for attribute group definitions.
20727 */
20728 for (i = 0; i < nbItems; i++) {
20729 item = items[i];
20730 switch (item->type) {
20731 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20732 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20733 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20734 {
20735 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20736 FIXHFAILURE;
20737 }
20738 break;
20739 default:
20740 break;
20741 }
20742 }
20743 if (pctxt->nberrors != 0)
20744 goto exit_error;
20745
20746 /*
20747 * Apply constraints for redefinitions.
20748 */
20749 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20750 xmlSchemaCheckSRCRedefineSecond(pctxt);
20751 if (pctxt->nberrors != 0)
20752 goto exit_error;
20753
20754 /*
20755 * Fixup complex types.
20756 */
20757 for (i = 0; i < nbItems; i++) {
20758 item = con->pending->items[i];
20759 switch (item->type) {
20760 case XML_SCHEMA_TYPE_COMPLEX:
20761 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20762 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20763 FIXHFAILURE;
20764 }
20765 break;
20766 default:
20767 break;
20768 }
20769 }
20770 if (pctxt->nberrors != 0)
20771 goto exit_error;
20772
20773 /*
20774 * The list could have changed, since xmlSchemaFixupComplexType()
20775 * will create particles and model groups in some cases.
20776 */
20777 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20778 nbItems = con->pending->nbItems;
20779
20780 /*
20781 * At this point all complex types need to be builded and checked.
20782 */
20783 /*
20784 * Apply some constraints for element declarations.
20785 */
20786 for (i = 0; i < nbItems; i++) {
20787 item = items[i];
20788 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020789 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020790
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020791 if ((((xmlSchemaElementPtr) item)->flags &
20792 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20793 xmlSchemaCheckElementDeclComponent(
20794 (xmlSchemaElementPtr) item, pctxt);
20795 FIXHFAILURE;
20796 }
20797 break;
20798 default:
20799 break;
20800 }
20801 }
20802 if (pctxt->nberrors != 0)
20803 goto exit_error;
20804 /*
20805 * Finally we can build the automaton from the content model of
20806 * complex types.
20807 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020808
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020809 for (i = 0; i < nbItems; i++) {
20810 item = items[i];
20811 switch (item->type) {
20812 case XML_SCHEMA_TYPE_COMPLEX:
20813 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020814 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020815 break;
20816 default:
20817 break;
20818 }
20819 }
20820 if (pctxt->nberrors != 0)
20821 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020822 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020823 * URGENT TODO: cos-element-consistent
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020824 */
20825 con->pending->nbItems = 0;
20826 return(0);
20827exit_error:
20828 con->pending->nbItems = 0;
20829 return(pctxt->err);
20830exit_failure:
20831 con->pending->nbItems = 0;
20832 return(-1);
20833}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020834/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020835 * xmlSchemaParse:
20836 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020837 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020838 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000020839 * XML Shema struture which can be used to validate instances.
20840 * *WARNING* this interface is highly subject to change
20841 *
20842 * Returns the internal XML Schema structure built from the resource or
20843 * NULL in case of error
20844 */
20845xmlSchemaPtr
20846xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
20847{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020848 xmlSchemaPtr schema = NULL;
20849 xmlSchemaBucketPtr bucket = NULL;
20850 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000020851
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020852 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020853 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020854 * the API; i.e. not automatically by the validated instance document.
20855 */
20856
Daniel Veillard4255d502002-04-16 15:50:10 +000020857 xmlSchemaInitTypes();
20858
Daniel Veillard6045c902002-10-09 21:13:59 +000020859 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000020860 return (NULL);
20861
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020862 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020863 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020864 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020865 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020866
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020867 /* Create the *main* schema. */
20868 schema = xmlSchemaNewSchema(ctxt);
20869 if (schema == NULL)
20870 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000020871 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020872 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020873 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020874 if (ctxt->constructor == NULL) {
20875 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
20876 if (ctxt->constructor == NULL)
20877 return(NULL);
20878 /* Take ownership of the constructor to be able to free it. */
20879 ctxt->ownsConstructor = 1;
20880 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020881 ctxt->constructor->mainSchema = schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020882 /*
20883 * Locate and add the schema document.
20884 */
20885 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
20886 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
20887 NULL, NULL, &bucket);
20888 if (res == -1)
20889 goto exit_failure;
20890 if (res != 0)
20891 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020892
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020893 if (bucket == NULL) {
20894 /* TODO: Error code, actually we failed to *locate* the schema. */
20895 if (ctxt->URL)
20896 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
20897 NULL, NULL,
20898 "Failed to locate the main schema resource at '%s'",
20899 ctxt->URL, NULL);
20900 else
20901 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
20902 NULL, NULL,
20903 "Failed to locate the main schema resource",
20904 NULL, NULL);
20905 goto exit;
20906 }
20907 /* Set the main schema bucket. */
20908 ctxt->constructor->bucket = bucket;
20909 ctxt->targetNamespace = bucket->targetNamespace;
20910 schema->targetNamespace = bucket->targetNamespace;
20911
20912 /* Then do the parsing for good. */
20913 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
20914 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020915 if (ctxt->nberrors != 0)
20916 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020917
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020918 schema->doc = bucket->doc;
20919 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020920
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020921 ctxt->schema = schema;
20922
20923 if (xmlSchemaFixupComponents(ctxt) == -1)
20924 goto exit_failure;
20925
20926 /*
20927 * TODO: This is not nice, since we cannot distinguish from the
20928 * result if there was an internal error or not.
20929 */
20930exit:
20931 if (ctxt->nberrors != 0) {
20932 if (schema) {
20933 xmlSchemaFree(schema);
20934 schema = NULL;
20935 }
20936 if (ctxt->constructor) {
20937 xmlSchemaConstructionCtxtFree(ctxt->constructor);
20938 ctxt->constructor = NULL;
20939 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020940 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020941 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020942 ctxt->schema = NULL;
20943 return(schema);
20944exit_failure:
20945 /*
20946 * Quite verbose, but should catch internal errors, which were
20947 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020948 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020949 if (schema) {
20950 xmlSchemaFree(schema);
20951 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020952 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020953 if (ctxt->constructor) {
20954 xmlSchemaConstructionCtxtFree(ctxt->constructor);
20955 ctxt->constructor = NULL;
20956 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000020957 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020958 PERROR_INT2("xmlSchemaParse",
20959 "An internal error occured");
20960 ctxt->schema = NULL;
20961 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020962}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020963
Daniel Veillard4255d502002-04-16 15:50:10 +000020964/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000020965 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000020966 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000020967 * @err: the error callback
20968 * @warn: the warning callback
20969 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000020970 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000020971 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020972 */
20973void
20974xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020975 xmlSchemaValidityErrorFunc err,
20976 xmlSchemaValidityWarningFunc warn, void *ctx)
20977{
Daniel Veillard4255d502002-04-16 15:50:10 +000020978 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020979 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020980 ctxt->error = err;
20981 ctxt->warning = warn;
20982 ctxt->userData = ctx;
20983}
20984
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000020985/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020986 * xmlSchemaGetParserErrors:
20987 * @ctxt: a XMl-Schema parser context
20988 * @err: the error callback result
20989 * @warn: the warning callback result
20990 * @ctx: contextual data for the callbacks result
20991 *
20992 * Get the callback information used to handle errors for a parser context
20993 *
20994 * Returns -1 in case of failure, 0 otherwise
20995 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020996int
Daniel Veillard259f0df2004-08-18 09:13:18 +000020997xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
20998 xmlSchemaValidityErrorFunc * err,
20999 xmlSchemaValidityWarningFunc * warn, void **ctx)
21000{
21001 if (ctxt == NULL)
21002 return(-1);
21003 if (err != NULL)
21004 *err = ctxt->error;
21005 if (warn != NULL)
21006 *warn = ctxt->warning;
21007 if (ctx != NULL)
21008 *ctx = ctxt->userData;
21009 return(0);
21010}
21011
21012/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021013 * xmlSchemaFacetTypeToString:
21014 * @type: the facet type
21015 *
21016 * Convert the xmlSchemaTypeType to a char string.
21017 *
21018 * Returns the char string representation of the facet type if the
21019 * type is a facet and an "Internal Error" string otherwise.
21020 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021021static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021022xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21023{
21024 switch (type) {
21025 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021026 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021027 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021028 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021029 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021030 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021031 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021032 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021033 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021034 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021035 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021036 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021037 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021038 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021039 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021040 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021041 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021042 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021043 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021044 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021045 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021046 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021047 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021048 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021049 default:
21050 break;
21051 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021052 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021053}
21054
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021055static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021056xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21057{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021058 /*
21059 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021060 * from xsd:string.
21061 */
21062 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021063 /*
21064 * Note that we assume a whitespace of preserve for anySimpleType.
21065 */
21066 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21067 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21068 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021069 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021070 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021071 else {
21072 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021073 * For all ·atomic· datatypes other than string (and types ·derived·
21074 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021075 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021076 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021077 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021078 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021079 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021080 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021081 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021082 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021083 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021084 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021085 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021086 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021087 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021088 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21089 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21090 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21091 return (XML_SCHEMA_WHITESPACE_REPLACE);
21092 else
21093 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021094 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021095 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021096}
21097
Daniel Veillard4255d502002-04-16 15:50:10 +000021098/************************************************************************
21099 * *
21100 * Simple type validation *
21101 * *
21102 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021103
Daniel Veillard4255d502002-04-16 15:50:10 +000021104
21105/************************************************************************
21106 * *
21107 * DOM Validation code *
21108 * *
21109 ************************************************************************/
21110
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021111/**
21112 * xmlSchemaAssembleByLocation:
21113 * @pctxt: a schema parser context
21114 * @vctxt: a schema validation context
21115 * @schema: the existing schema
21116 * @node: the node that fired the assembling
21117 * @nsName: the namespace name of the new schema
21118 * @location: the location of the schema
21119 *
21120 * Expands an existing schema by an additional schema.
21121 *
21122 * Returns 0 if the new schema is correct, a positive error code
21123 * number otherwise and -1 in case of an internal or API error.
21124 */
21125static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021126xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021127 xmlSchemaPtr schema,
21128 xmlNodePtr node,
21129 const xmlChar *nsName,
21130 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021131{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021132 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021133 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021134 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021135
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021136 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021137 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021138
21139 if (vctxt->pctxt == NULL) {
21140 VERROR_INT("xmlSchemaAssembleByLocation",
21141 "no parser context available");
21142 return(-1);
21143 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021144 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021145 if (pctxt->constructor == NULL) {
21146 PERROR_INT("xmlSchemaAssembleByLocation",
21147 "no constructor");
21148 return(-1);
21149 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021150 /*
21151 * Acquire the schema document.
21152 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021153 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21154 location, node);
21155 /*
21156 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21157 * the process will automatically change this to
21158 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21159 */
21160 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21161 location, NULL, NULL, 0, node, NULL, nsName,
21162 &bucket);
21163 if (ret != 0)
21164 return(ret);
21165 if (bucket == NULL) {
21166 PERROR_INT("xmlSchemaAssembleByLocation",
21167 "no schema bucket aquired");
21168 return(-1);
21169 }
21170 /*
21171 * The first located schema will be handled as if all other
21172 * schemas imported by XSI were imported by this first schema.
21173 */
21174 if ((bucket != NULL) &&
21175 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21176 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21177 /*
21178 * TODO: Is this handled like an import? I.e. is it not an error
21179 * if the schema cannot be located?
21180 */
21181 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21182 return(0);
21183 /*
21184 * We will reuse the parser context for every schema imported
21185 * directly via XSI. So reset the context.
21186 */
21187 pctxt->nberrors = 0;
21188 pctxt->err = 0;
21189 pctxt->doc = bucket->doc;
21190
21191 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21192 if (ret == -1) {
21193 pctxt->doc = NULL;
21194 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021195 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021196 /* Paranoid error channelling. */
21197 if ((ret == 0) && (pctxt->nberrors != 0))
21198 ret = pctxt->err;
21199 if (pctxt->nberrors == 0) {
21200 /*
21201 * Only bother to fixup pending components, if there was
21202 * no error yet.
21203 */
21204 xmlSchemaFixupComponents(pctxt);
21205 vctxt->nberrors += pctxt->nberrors;
21206 } else {
21207 /* Add to validation error sum. */
21208 vctxt->nberrors += pctxt->nberrors;
21209 }
21210 pctxt->doc = NULL;
21211 return(ret);
21212exit_failure:
21213 pctxt->doc = NULL;
21214 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021215}
21216
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021217static xmlSchemaAttrInfoPtr
21218xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21219 int metaType)
21220{
21221 if (vctxt->nbAttrInfos == 0)
21222 return (NULL);
21223 {
21224 int i;
21225 xmlSchemaAttrInfoPtr iattr;
21226
21227 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21228 iattr = vctxt->attrInfos[i];
21229 if (iattr->metaType == metaType)
21230 return (iattr);
21231 }
21232
21233 }
21234 return (NULL);
21235}
21236
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021237/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021238 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021239 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021240 *
21241 * Expands an existing schema by an additional schema using
21242 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21243 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21244 * must be set to 1.
21245 *
21246 * Returns 0 if the new schema is correct, a positive error code
21247 * number otherwise and -1 in case of an internal or API error.
21248 */
21249static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021250xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021251{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021252 const xmlChar *cur, *end;
21253 const xmlChar *nsname = NULL, *location;
21254 int count = 0;
21255 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021256 xmlSchemaAttrInfoPtr iattr;
21257
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021258 /*
21259 * Parse the value; we will assume an even number of values
21260 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021261 *
21262 * URGENT TODO: !! This needs to work also for multiple
21263 * schemaLocation attributes !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021265 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21266 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21267 if (iattr == NULL)
21268 xmlSchemaGetMetaAttrInfo(vctxt,
21269 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21270 if (iattr == NULL)
21271 return (0);
21272 cur = iattr->value;
21273 do {
21274 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021275 /*
21276 * Get the namespace name.
21277 */
21278 while (IS_BLANK_CH(*cur))
21279 cur++;
21280 end = cur;
21281 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21282 end++;
21283 if (end == cur)
21284 break;
21285 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021286 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021287 cur = end;
21288 }
21289 /*
21290 * Get the URI.
21291 */
21292 while (IS_BLANK_CH(*cur))
21293 cur++;
21294 end = cur;
21295 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21296 end++;
21297 if (end == cur)
21298 break;
21299 count++;
21300 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021301 cur = end;
21302 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21303 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021304 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021305 VERROR_INT("xmlSchemaAssembleByXSI",
21306 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021307 return (-1);
21308 }
21309 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021310 return (ret);
21311}
21312
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021313static const xmlChar *
21314xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21315 const xmlChar *prefix)
21316{
21317 if (vctxt->sax != NULL) {
21318 int i, j;
21319 xmlSchemaNodeInfoPtr inode;
21320
21321 for (i = vctxt->depth; i >= 0; i--) {
21322 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21323 inode = vctxt->elemInfos[i];
21324 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21325 if (((prefix == NULL) &&
21326 (inode->nsBindings[j] == NULL)) ||
21327 ((prefix != NULL) && xmlStrEqual(prefix,
21328 inode->nsBindings[j]))) {
21329
21330 /*
21331 * Note that the namespace bindings are already
21332 * in a string dict.
21333 */
21334 return (inode->nsBindings[j+1]);
21335 }
21336 }
21337 }
21338 }
21339 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021340#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021341 } else if (vctxt->reader != NULL) {
21342 xmlChar *nsName;
21343
21344 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21345 if (nsName != NULL) {
21346 const xmlChar *ret;
21347
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021348 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21349 xmlFree(nsName);
21350 return (ret);
21351 } else
21352 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021353#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021354 } else {
21355 xmlNsPtr ns;
21356
21357 if ((vctxt->inode->node == NULL) ||
21358 (vctxt->inode->node->doc == NULL)) {
21359 VERROR_INT("xmlSchemaLookupNamespace",
21360 "no node or node's doc avaliable");
21361 return (NULL);
21362 }
21363 ns = xmlSearchNs(vctxt->inode->node->doc,
21364 vctxt->inode->node, prefix);
21365 if (ns != NULL)
21366 return (ns->href);
21367 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021368 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021369}
21370
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021371/*
21372* This one works on the schema of the validation context.
21373*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021374static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021375xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21376 xmlSchemaPtr schema,
21377 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021378 const xmlChar *value,
21379 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021380 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021381{
21382 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021383
21384 if (vctxt && (vctxt->schema == NULL)) {
21385 VERROR_INT("xmlSchemaValidateNotation",
21386 "a schema is needed on the validation context");
21387 return (-1);
21388 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021389 ret = xmlValidateQName(value, 1);
21390 if (ret != 0)
21391 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021392 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021393 xmlChar *localName = NULL;
21394 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021395
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021396 localName = xmlSplitQName2(value, &prefix);
21397 if (prefix != NULL) {
21398 const xmlChar *nsName = NULL;
21399
21400 if (vctxt != NULL)
21401 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21402 else if (node != NULL) {
21403 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21404 if (ns != NULL)
21405 nsName = ns->href;
21406 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021407 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021408 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021409 return (1);
21410 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021411 if (nsName == NULL) {
21412 xmlFree(prefix);
21413 xmlFree(localName);
21414 return (1);
21415 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021416 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021417 if (valNeeded && (val != NULL)) {
21418 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21419 BAD_CAST xmlStrdup(nsName));
21420 if (*val == NULL)
21421 ret = -1;
21422 }
21423 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021424 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021425 xmlFree(prefix);
21426 xmlFree(localName);
21427 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021428 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021429 if (valNeeded && (val != NULL)) {
21430 (*val) = xmlSchemaNewNOTATIONValue(
21431 BAD_CAST xmlStrdup(value), NULL);
21432 if (*val == NULL)
21433 ret = -1;
21434 }
21435 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021436 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021437 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021438 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021439 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021440}
21441
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021442static int
21443xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21444 const xmlChar* lname,
21445 const xmlChar* nsname)
21446{
21447 int i;
21448
21449 lname = xmlDictLookup(vctxt->dict, lname, -1);
21450 if (lname == NULL)
21451 return(-1);
21452 if (nsname != NULL) {
21453 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21454 if (nsname == NULL)
21455 return(-1);
21456 }
21457 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21458 if ((vctxt->nodeQNames->items [i] == lname) &&
21459 (vctxt->nodeQNames->items[i +1] == nsname))
21460 /* Already there */
21461 return(i);
21462 }
21463 /* Add new entry. */
21464 i = vctxt->nodeQNames->nbItems;
21465 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21466 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21467 return(i);
21468}
21469
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021470/************************************************************************
21471 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021472 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021473 * *
21474 ************************************************************************/
21475
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021476/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021477 * xmlSchemaAugmentIDC:
21478 * @idcDef: the IDC definition
21479 *
21480 * Creates an augmented IDC definition item.
21481 *
21482 * Returns the item, or NULL on internal errors.
21483 */
21484static void
21485xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21486 xmlSchemaValidCtxtPtr vctxt)
21487{
21488 xmlSchemaIDCAugPtr aidc;
21489
21490 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21491 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021492 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021493 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21494 NULL);
21495 return;
21496 }
21497 aidc->bubbleDepth = -1;
21498 aidc->def = idcDef;
21499 aidc->next = NULL;
21500 if (vctxt->aidcs == NULL)
21501 vctxt->aidcs = aidc;
21502 else {
21503 aidc->next = vctxt->aidcs;
21504 vctxt->aidcs = aidc;
21505 }
21506}
21507
21508/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021509 * xmlSchemaIDCNewBinding:
21510 * @idcDef: the IDC definition of this binding
21511 *
21512 * Creates a new IDC binding.
21513 *
21514 * Returns the new binding in case of succeeded, NULL on internal errors.
21515 */
21516static xmlSchemaPSVIIDCBindingPtr
21517xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21518{
21519 xmlSchemaPSVIIDCBindingPtr ret;
21520
21521 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21522 sizeof(xmlSchemaPSVIIDCBinding));
21523 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021524 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021525 "allocating a PSVI IDC binding item", NULL);
21526 return (NULL);
21527 }
21528 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21529 ret->definition = idcDef;
21530 return (ret);
21531}
21532
21533/**
21534 * xmlSchemaIDCStoreNodeTableItem:
21535 * @vctxt: the WXS validation context
21536 * @item: the IDC node table item
21537 *
21538 * The validation context is used to store an IDC node table items.
21539 * They are stored to avoid copying them if IDC node-tables are merged
21540 * with corresponding parent IDC node-tables (bubbling).
21541 *
21542 * Returns 0 if succeeded, -1 on internal errors.
21543 */
21544static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021545xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021546 xmlSchemaPSVIIDCNodePtr item)
21547{
21548 /*
21549 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021550 */
21551 if (vctxt->idcNodes == NULL) {
21552 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021553 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21554 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021555 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021556 "allocating the IDC node table item list", NULL);
21557 return (-1);
21558 }
21559 vctxt->sizeIdcNodes = 20;
21560 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21561 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021562 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21563 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021564 sizeof(xmlSchemaPSVIIDCNodePtr));
21565 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021566 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021567 "re-allocating the IDC node table item list", NULL);
21568 return (-1);
21569 }
21570 }
21571 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021572
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021573 return (0);
21574}
21575
21576/**
21577 * xmlSchemaIDCStoreKey:
21578 * @vctxt: the WXS validation context
21579 * @item: the IDC key
21580 *
21581 * The validation context is used to store an IDC key.
21582 *
21583 * Returns 0 if succeeded, -1 on internal errors.
21584 */
21585static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021586xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021587 xmlSchemaPSVIIDCKeyPtr key)
21588{
21589 /*
21590 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021591 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021592 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021593 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021594 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21595 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021596 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021597 "allocating the IDC key storage list", NULL);
21598 return (-1);
21599 }
21600 vctxt->sizeIdcKeys = 40;
21601 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21602 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021603 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21604 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021605 sizeof(xmlSchemaPSVIIDCKeyPtr));
21606 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021607 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021608 "re-allocating the IDC key storage list", NULL);
21609 return (-1);
21610 }
21611 }
21612 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021613
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021614 return (0);
21615}
21616
21617/**
21618 * xmlSchemaIDCAppendNodeTableItem:
21619 * @bind: the IDC binding
21620 * @ntItem: the node-table item
21621 *
21622 * Appends the IDC node-table item to the binding.
21623 *
21624 * Returns 0 on success and -1 on internal errors.
21625 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021626static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021627xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21628 xmlSchemaPSVIIDCNodePtr ntItem)
21629{
21630 if (bind->nodeTable == NULL) {
21631 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021632 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021633 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21634 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021635 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021636 "allocating an array of IDC node-table items", NULL);
21637 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021638 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021639 } else if (bind->sizeNodes <= bind->nbNodes) {
21640 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021641 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21642 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021643 sizeof(xmlSchemaPSVIIDCNodePtr));
21644 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021645 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021646 "re-allocating an array of IDC node-table items", NULL);
21647 return(-1);
21648 }
21649 }
21650 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021651 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021652}
21653
21654/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021655 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021656 * @vctxt: the WXS validation context
21657 * @matcher: the IDC matcher
21658 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021659 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021660 * of the given matcher. If none found, a new one is created
21661 * and added to the IDC table.
21662 *
21663 * Returns an IDC binding or NULL on internal errors.
21664 */
21665static xmlSchemaPSVIIDCBindingPtr
21666xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
21667 xmlSchemaIDCMatcherPtr matcher)
21668{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021669 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021670
21671 info = vctxt->elemInfos[matcher->depth];
21672
21673 if (info->idcTable == NULL) {
21674 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21675 if (info->idcTable == NULL)
21676 return (NULL);
21677 return(info->idcTable);
21678 } else {
21679 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021680
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021681 bind = info->idcTable;
21682 do {
21683 if (bind->definition == matcher->aidc->def)
21684 return(bind);
21685 if (bind->next == NULL) {
21686 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21687 if (bind->next == NULL)
21688 return (NULL);
21689 return(bind->next);
21690 }
21691 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021692 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021693 }
21694 return (NULL);
21695}
21696
21697/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021698 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021699 * @key: the IDC key
21700 *
21701 * Frees an IDC key together with its compiled value.
21702 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021703static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021704xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021706 if (key->val != NULL)
21707 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021708 xmlFree(key);
21709}
21710
21711/**
21712 * xmlSchemaIDCFreeBinding:
21713 *
21714 * Frees an IDC binding. Note that the node table-items
21715 * are not freed.
21716 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021717static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021718xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21719{
21720 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021721 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
21722 int i;
21723 /*
21724 * Node-table items for keyrefs are not stored globally
21725 * to the validation context, since they are not bubbled.
21726 * We need to free them here.
21727 */
21728 for (i = 0; i < bind->nbNodes; i++) {
21729 xmlFree(bind->nodeTable[i]->keys);
21730 xmlFree(bind->nodeTable[i]);
21731 }
21732 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021733 xmlFree(bind->nodeTable);
21734 }
21735 xmlFree(bind);
21736}
21737
21738/**
21739 * xmlSchemaIDCFreeIDCTable:
21740 * @bind: the first IDC binding in the list
21741 *
21742 * Frees an IDC table, i.e. all the IDC bindings in the list.
21743 */
21744static void
21745xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21746{
21747 xmlSchemaPSVIIDCBindingPtr prev;
21748
21749 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021750 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021751 bind = bind->next;
21752 xmlSchemaIDCFreeBinding(prev);
21753 }
21754}
21755
21756/**
21757 * xmlSchemaIDCFreeMatcherList:
21758 * @matcher: the first IDC matcher in the list
21759 *
21760 * Frees a list of IDC matchers.
21761 */
21762static void
21763xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
21764{
21765 xmlSchemaIDCMatcherPtr next;
21766
21767 while (matcher != NULL) {
21768 next = matcher->next;
21769 if (matcher->keySeqs != NULL) {
21770 int i;
21771 for (i = 0; i < matcher->sizeKeySeqs; i++)
21772 if (matcher->keySeqs[i] != NULL)
21773 xmlFree(matcher->keySeqs[i]);
21774 xmlFree(matcher->keySeqs);
21775 }
21776 xmlFree(matcher);
21777 matcher = next;
21778 }
21779}
21780
21781/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021782 * xmlSchemaIDCAddStateObject:
21783 * @vctxt: the WXS validation context
21784 * @matcher: the IDC matcher
21785 * @sel: the XPath information
21786 * @parent: the parent "selector" state object if any
21787 * @type: "selector" or "field"
21788 *
21789 * Creates/reuses and activates state objects for the given
21790 * XPath information; if the XPath expression consists of unions,
21791 * multiple state objects are created for every unioned expression.
21792 *
21793 * Returns 0 on success and -1 on internal errors.
21794 */
21795static int
21796xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
21797 xmlSchemaIDCMatcherPtr matcher,
21798 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021799 int type)
21800{
21801 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021802
21803 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021804 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021805 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021806 if (vctxt->xpathStatePool != NULL) {
21807 sto = vctxt->xpathStatePool;
21808 vctxt->xpathStatePool = sto->next;
21809 sto->next = NULL;
21810 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021811 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021812 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021813 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021814 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
21815 if (sto == NULL) {
21816 xmlSchemaVErrMemory(NULL,
21817 "allocating an IDC state object", NULL);
21818 return (-1);
21819 }
21820 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
21821 }
21822 /*
21823 * Add to global list.
21824 */
21825 if (vctxt->xpathStates != NULL)
21826 sto->next = vctxt->xpathStates;
21827 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021828
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021829 /*
21830 * Free the old xpath validation context.
21831 */
21832 if (sto->xpathCtxt != NULL)
21833 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
21834
21835 /*
21836 * Create a new XPath (pattern) validation context.
21837 */
21838 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
21839 (xmlPatternPtr) sel->xpathComp);
21840 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021841 VERROR_INT("xmlSchemaIDCAddStateObject",
21842 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021843 return (-1);
21844 }
21845 sto->type = type;
21846 sto->depth = vctxt->depth;
21847 sto->matcher = matcher;
21848 sto->sel = sel;
21849 sto->nbHistory = 0;
21850
21851#if DEBUG_IDC
21852 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
21853 sto->sel->xpath);
21854#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021855 return (0);
21856}
21857
21858/**
21859 * xmlSchemaXPathEvaluate:
21860 * @vctxt: the WXS validation context
21861 * @nodeType: the nodeType of the current node
21862 *
21863 * Evaluates all active XPath state objects.
21864 *
21865 * Returns the number of IC "field" state objects which resolved to
21866 * this node, 0 if none resolved and -1 on internal errors.
21867 */
21868static int
21869xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021870 xmlElementType nodeType)
21871{
21872 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021873 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021874
21875 if (vctxt->xpathStates == NULL)
21876 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021877
21878 if (nodeType == XML_ATTRIBUTE_NODE)
21879 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021880#if DEBUG_IDC
21881 {
21882 xmlChar *str = NULL;
21883 xmlGenericError(xmlGenericErrorContext,
21884 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021885 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
21886 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021887 FREE_AND_NULL(str)
21888 }
21889#endif
21890 /*
21891 * Process all active XPath state objects.
21892 */
21893 first = vctxt->xpathStates;
21894 sto = first;
21895 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021896#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021897 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021898 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
21899 sto->matcher->aidc->def->name, sto->sel->xpath);
21900 else
21901 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
21902 sto->matcher->aidc->def->name, sto->sel->xpath);
21903#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021904 if (nodeType == XML_ELEMENT_NODE)
21905 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021906 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021907 else
21908 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021909 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021910
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021911 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021912 VERROR_INT("xmlSchemaXPathEvaluate",
21913 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021914 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021915 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021916 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021917 goto next_sto;
21918 /*
21919 * Full match.
21920 */
21921#if DEBUG_IDC
21922 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021923 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021924#endif
21925 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021926 * Register a match in the state object history.
21927 */
21928 if (sto->history == NULL) {
21929 sto->history = (int *) xmlMalloc(5 * sizeof(int));
21930 if (sto->history == NULL) {
21931 xmlSchemaVErrMemory(NULL,
21932 "allocating the state object history", NULL);
21933 return(-1);
21934 }
21935 sto->sizeHistory = 10;
21936 } else if (sto->sizeHistory <= sto->nbHistory) {
21937 sto->sizeHistory *= 2;
21938 sto->history = (int *) xmlRealloc(sto->history,
21939 sto->sizeHistory * sizeof(int));
21940 if (sto->history == NULL) {
21941 xmlSchemaVErrMemory(NULL,
21942 "re-allocating the state object history", NULL);
21943 return(-1);
21944 }
21945 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021946 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021947
21948#ifdef DEBUG_IDC
21949 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
21950 vctxt->depth);
21951#endif
21952
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021953 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
21954 xmlSchemaIDCSelectPtr sel;
21955 /*
21956 * Activate state objects for the IDC fields of
21957 * the IDC selector.
21958 */
21959#if DEBUG_IDC
21960 xmlGenericError(xmlGenericErrorContext, "IDC: "
21961 "activating field states\n");
21962#endif
21963 sel = sto->matcher->aidc->def->fields;
21964 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021965 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
21966 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
21967 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021968 sel = sel->next;
21969 }
21970 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
21971 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000021972 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021973 */
21974#if DEBUG_IDC
21975 xmlGenericError(xmlGenericErrorContext,
21976 "IDC: key found\n");
21977#endif
21978 /*
21979 * Notify that the character value of this node is
21980 * needed.
21981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021982 if (resolved == 0) {
21983 if ((vctxt->inode->flags &
21984 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
21985 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21986 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021987 resolved++;
21988 }
21989next_sto:
21990 if (sto->next == NULL) {
21991 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021992 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021993 */
21994 head = first;
21995 sto = vctxt->xpathStates;
21996 } else
21997 sto = sto->next;
21998 }
21999 return (resolved);
22000}
22001
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022002static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022003xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022004 xmlChar **buf,
22005 xmlSchemaPSVIIDCKeyPtr *seq,
22006 int count)
22007{
22008 int i, res;
22009 const xmlChar *value = NULL;
22010
22011 *buf = xmlStrdup(BAD_CAST "[");
22012 for (i = 0; i < count; i++) {
22013 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022014 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
22015 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022016 if (res == 0)
22017 *buf = xmlStrcat(*buf, value);
22018 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022019 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22020 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022021 *buf = xmlStrcat(*buf, BAD_CAST "???");
22022 }
22023 if (i < count -1)
22024 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22025 else
22026 *buf = xmlStrcat(*buf, BAD_CAST "'");
22027 if (value != NULL) {
22028 xmlFree((xmlChar *) value);
22029 value = NULL;
22030 }
22031 }
22032 *buf = xmlStrcat(*buf, BAD_CAST "]");
22033
22034 return (BAD_CAST *buf);
22035}
22036
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022037/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022038 * xmlSchemaXPathPop:
22039 * @vctxt: the WXS validation context
22040 *
22041 * Pops all XPath states.
22042 *
22043 * Returns 0 on success and -1 on internal errors.
22044 */
22045static int
22046xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22047{
22048 xmlSchemaIDCStateObjPtr sto;
22049 int res;
22050
22051 if (vctxt->xpathStates == NULL)
22052 return(0);
22053 sto = vctxt->xpathStates;
22054 do {
22055 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22056 if (res == -1)
22057 return (-1);
22058 sto = sto->next;
22059 } while (sto != NULL);
22060 return(0);
22061}
22062
22063/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022064 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022065 * @vctxt: the WXS validation context
22066 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022067 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022068 *
22069 * Processes and pops the history items of the IDC state objects.
22070 * IDC key-sequences are validated/created on IDC bindings.
22071 *
22072 * Returns 0 on success and -1 on internal errors.
22073 */
22074static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022075xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022076 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022077{
22078 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022079 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022080 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022081 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022082
22083 if (vctxt->xpathStates == NULL)
22084 return (0);
22085 sto = vctxt->xpathStates;
22086
22087#if DEBUG_IDC
22088 {
22089 xmlChar *str = NULL;
22090 xmlGenericError(xmlGenericErrorContext,
22091 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022092 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22093 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022094 FREE_AND_NULL(str)
22095 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022096#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022097 /*
22098 * Evaluate the state objects.
22099 */
22100 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022101 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22102 if (res == -1) {
22103 VERROR_INT("xmlSchemaXPathProcessHistory",
22104 "calling xmlStreamPop()");
22105 return (-1);
22106 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022107#if DEBUG_IDC
22108 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22109 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022110#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022111 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022112 goto deregister_check;
22113
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022114 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022115
22116 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022117 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022118 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022119 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022120 sto = sto->next;
22121 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022122 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022123 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022124 if (! WXS_IS_SIMPLE(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022125 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022126 /*
22127 * Not qualified if the field resolves to a node of non
22128 * simple type.
22129 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022130 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022131 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022132 WXS_BASIC_CAST sto->matcher->aidc->def,
22133 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022134 "non-simple type",
22135 sto->sel->xpath,
22136 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22137 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022138 sto->nbHistory--;
22139 goto deregister_check;
22140 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022141 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022142 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022143 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022144 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022145 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022146 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022147 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022148 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022149 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022150 sto->nbHistory--;
22151 goto deregister_check;
22152 } else {
22153 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22154 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022155 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022156
22157 /*
22158 * The key will be anchored on the matcher's list of
22159 * key-sequences. The position in this list is determined
22160 * by the target node's depth relative to the matcher's
22161 * depth of creation (i.e. the depth of the scope element).
22162 */
22163 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022164 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022165
22166 /*
22167 * Create/grow the array of key-sequences.
22168 */
22169 if (matcher->keySeqs == NULL) {
22170 if (pos > 9)
22171 matcher->sizeKeySeqs = pos * 2;
22172 else
22173 matcher->sizeKeySeqs = 10;
22174 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22175 xmlMalloc(matcher->sizeKeySeqs *
22176 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22177 if (matcher->keySeqs == NULL) {
22178 xmlSchemaVErrMemory(NULL,
22179 "allocating an array of key-sequences",
22180 NULL);
22181 return(-1);
22182 }
22183 memset(matcher->keySeqs, 0,
22184 matcher->sizeKeySeqs *
22185 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22186 } else if (pos >= matcher->sizeKeySeqs) {
22187 int i = matcher->sizeKeySeqs;
22188
22189 matcher->sizeKeySeqs *= 2;
22190 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22191 xmlRealloc(matcher->keySeqs,
22192 matcher->sizeKeySeqs *
22193 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022194 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022195 xmlSchemaVErrMemory(NULL,
22196 "reallocating an array of key-sequences",
22197 NULL);
22198 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022199 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022200 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022201 * The array needs to be NULLed.
22202 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022203 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022204 for (; i < matcher->sizeKeySeqs; i++)
22205 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022206 }
22207
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022208 /*
22209 * Get/create the key-sequence.
22210 */
22211 keySeq = matcher->keySeqs[pos];
22212 if (keySeq == NULL) {
22213 goto create_sequence;
22214 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022215 if (keySeq[idx] != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022216 xmlChar *str = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022217 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022218 * cvc-identity-constraint:
22219 * 3 For each node in the ·target node set· all
22220 * of the {fields}, with that node as the context
22221 * node, evaluate to either an empty node-set or
22222 * a node-set with exactly one member, which must
22223 * have a simple type.
22224 *
22225 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022226 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022227 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022228 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022229 WXS_BASIC_CAST matcher->aidc->def,
22230 "The XPath '%s' of a field of %s evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022231 "with more than one member",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022232 sto->sel->xpath,
22233 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22234 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022235 sto->nbHistory--;
22236 goto deregister_check;
22237 } else {
22238 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022239 }
22240 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022241
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022242create_sequence:
22243 /*
22244 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022245 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022246 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22247 matcher->aidc->def->nbFields *
22248 sizeof(xmlSchemaPSVIIDCKeyPtr));
22249 if (keySeq == NULL) {
22250 xmlSchemaVErrMemory(NULL,
22251 "allocating an IDC key-sequence", NULL);
22252 return(-1);
22253 }
22254 memset(keySeq, 0, matcher->aidc->def->nbFields *
22255 sizeof(xmlSchemaPSVIIDCKeyPtr));
22256 matcher->keySeqs[pos] = keySeq;
22257create_key:
22258 /*
22259 * Created a key once per node only.
22260 */
22261 if (key == NULL) {
22262 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22263 sizeof(xmlSchemaPSVIIDCKey));
22264 if (key == NULL) {
22265 xmlSchemaVErrMemory(NULL,
22266 "allocating a IDC key", NULL);
22267 xmlFree(keySeq);
22268 matcher->keySeqs[pos] = NULL;
22269 return(-1);
22270 }
22271 /*
22272 * Consume the compiled value.
22273 */
22274 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022275 key->val = vctxt->inode->val;
22276 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022277 /*
22278 * Store the key in a global list.
22279 */
22280 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22281 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022282 return (-1);
22283 }
22284 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022285 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022286 }
22287 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022288
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022289 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22290 xmlSchemaPSVIIDCBindingPtr bind;
22291 xmlSchemaPSVIIDCNodePtr ntItem;
22292 xmlSchemaIDCMatcherPtr matcher;
22293 xmlSchemaIDCPtr idc;
22294 int pos, i, j, nbKeys;
22295 /*
22296 * Here we have the following scenario:
22297 * An IDC 'selector' state object resolved to a target node,
22298 * during the time this target node was in the
22299 * ancestor-or-self axis, the 'field' state object(s) looked
22300 * out for matching nodes to create a key-sequence for this
22301 * target node. Now we are back to this target node and need
22302 * to put the key-sequence, together with the target node
22303 * itself, into the node-table of the corresponding IDC
22304 * binding.
22305 */
22306 matcher = sto->matcher;
22307 idc = matcher->aidc->def;
22308 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022309 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022310 /*
22311 * Check if the matcher has any key-sequences at all, plus
22312 * if it has a key-sequence for the current target node.
22313 */
22314 if ((matcher->keySeqs == NULL) ||
22315 (matcher->sizeKeySeqs <= pos)) {
22316 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22317 goto selector_key_error;
22318 else
22319 goto selector_leave;
22320 }
22321
22322 keySeq = &(matcher->keySeqs[pos]);
22323 if (*keySeq == NULL) {
22324 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22325 goto selector_key_error;
22326 else
22327 goto selector_leave;
22328 }
22329
22330 for (i = 0; i < nbKeys; i++) {
22331 if ((*keySeq)[i] == NULL) {
22332 /*
22333 * Not qualified, if not all fields did resolve.
22334 */
22335 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22336 /*
22337 * All fields of a "key" IDC must resolve.
22338 */
22339 goto selector_key_error;
22340 }
22341 goto selector_leave;
22342 }
22343 }
22344 /*
22345 * All fields did resolve.
22346 */
22347
22348 /*
22349 * 4.1 If the {identity-constraint category} is unique(/key),
22350 * then no two members of the ·qualified node set· have
22351 * ·key-sequences· whose members are pairwise equal, as
22352 * defined by Equal in [XML Schemas: Datatypes].
22353 *
22354 * Get the IDC binding from the matcher and check for
22355 * duplicate key-sequences.
22356 */
22357 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
22358 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22359 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022360 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022361
22362 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022363 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022364 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022365 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022366 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022367 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022368 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022369 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022370 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022371 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022372 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022373 if (res == -1) {
22374 return (-1);
22375 } else if (res == 0)
22376 break;
22377 }
22378 if (res == 1) {
22379 /*
22380 * Duplicate found.
22381 */
22382 break;
22383 }
22384 i++;
22385 } while (i < bind->nbNodes);
22386 if (i != bind->nbNodes) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022387 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022388 /*
22389 * TODO: Try to report the key-sequence.
22390 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022391 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022392 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022393 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022394 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022395 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022396 (*keySeq), nbKeys),
22397 xmlSchemaGetIDCDesignation(&strB, idc));
22398 FREE_AND_NULL(str);
22399 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022400 goto selector_leave;
22401 }
22402 }
22403 /*
22404 * Add a node-table item to the IDC binding.
22405 */
22406 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22407 sizeof(xmlSchemaPSVIIDCNode));
22408 if (ntItem == NULL) {
22409 xmlSchemaVErrMemory(NULL,
22410 "allocating an IDC node-table item", NULL);
22411 xmlFree(*keySeq);
22412 *keySeq = NULL;
22413 return(-1);
22414 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022415 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022416
22417 /*
22418 * Store the node-table item on global list.
22419 */
22420 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22421 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22422 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022423 xmlFree(*keySeq);
22424 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022425 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022426 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022427 ntItem->nodeQNameID = -1;
22428 } else {
22429 /*
22430 * Save a cached QName for this node on the IDC node, to be
22431 * able to report it, even if the node is not saved.
22432 */
22433 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22434 vctxt->inode->localName, vctxt->inode->nsName);
22435 if (ntItem->nodeQNameID == -1) {
22436 xmlFree(ntItem);
22437 xmlFree(*keySeq);
22438 *keySeq = NULL;
22439 return (-1);
22440 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022441 }
22442 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022443 * Init the node-table item: Save the node, position and
22444 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022445 */
22446 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022447 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022448 ntItem->keys = *keySeq;
22449 *keySeq = NULL;
22450 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22451 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22452 /*
22453 * Free the item, since keyref items won't be
22454 * put on a global list.
22455 */
22456 xmlFree(ntItem->keys);
22457 xmlFree(ntItem);
22458 }
22459 return (-1);
22460 }
22461
22462 goto selector_leave;
22463selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022464 {
22465 xmlChar *str = NULL;
22466 /*
22467 * 4.2.1 (KEY) The ·target node set· and the
22468 * ·qualified node set· are equal, that is, every
22469 * member of the ·target node set· is also a member
22470 * of the ·qualified node set· and vice versa.
22471 */
22472 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22473 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022474 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022475 "Not all fields of %s evaluate to a node",
22476 xmlSchemaGetIDCDesignation(&str, idc), NULL);
22477 FREE_AND_NULL(str);
22478 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022479selector_leave:
22480 /*
22481 * Free the key-sequence if not added to the IDC table.
22482 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022483 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022484 xmlFree(*keySeq);
22485 *keySeq = NULL;
22486 }
22487 } /* if selector */
22488
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022489 sto->nbHistory--;
22490
22491deregister_check:
22492 /*
22493 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022494 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022495 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022496#if DEBUG_IDC
22497 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
22498 sto->sel->xpath);
22499#endif
22500 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022501 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022502 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022503 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022504 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022505 nextsto = sto->next;
22506 /*
22507 * Unlink from the list of active XPath state objects.
22508 */
22509 vctxt->xpathStates = sto->next;
22510 sto->next = vctxt->xpathStatePool;
22511 /*
22512 * Link it to the pool of reusable state objects.
22513 */
22514 vctxt->xpathStatePool = sto;
22515 sto = nextsto;
22516 } else
22517 sto = sto->next;
22518 } /* while (sto != NULL) */
22519 return (0);
22520}
22521
22522/**
22523 * xmlSchemaIDCRegisterMatchers:
22524 * @vctxt: the WXS validation context
22525 * @elemDecl: the element declaration
22526 *
22527 * Creates helper objects to evaluate IDC selectors/fields
22528 * successively.
22529 *
22530 * Returns 0 if OK and -1 on internal errors.
22531 */
22532static int
22533xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22534 xmlSchemaElementPtr elemDecl)
22535{
22536 xmlSchemaIDCMatcherPtr matcher, last = NULL;
22537 xmlSchemaIDCPtr idc, refIdc;
22538 xmlSchemaIDCAugPtr aidc;
22539
22540 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22541 if (idc == NULL)
22542 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022543
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022544#if DEBUG_IDC
22545 {
22546 xmlChar *str = NULL;
22547 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022548 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022549 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22550 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022551 FREE_AND_NULL(str)
22552 }
22553#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554 if (vctxt->inode->idcMatchers != NULL) {
22555 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22556 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022557 return (-1);
22558 }
22559 do {
22560 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22561 /*
22562 * Since IDCs bubbles are expensive we need to know the
22563 * depth at which the bubbles should stop; this will be
22564 * the depth of the top-most keyref IDC. If no keyref
22565 * references a key/unique IDC, the bubbleDepth will
22566 * be -1, indicating that no bubbles are needed.
22567 */
22568 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22569 if (refIdc != NULL) {
22570 /*
22571 * Lookup the augmented IDC.
22572 */
22573 aidc = vctxt->aidcs;
22574 while (aidc != NULL) {
22575 if (aidc->def == refIdc)
22576 break;
22577 aidc = aidc->next;
22578 }
22579 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022580 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022581 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022582 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022583 return (-1);
22584 }
22585 if ((aidc->bubbleDepth == -1) ||
22586 (vctxt->depth < aidc->bubbleDepth))
22587 aidc->bubbleDepth = vctxt->depth;
22588 }
22589 }
22590 /*
22591 * Lookup the augmented IDC item for the IDC definition.
22592 */
22593 aidc = vctxt->aidcs;
22594 while (aidc != NULL) {
22595 if (aidc->def == idc)
22596 break;
22597 aidc = aidc->next;
22598 }
22599 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022600 VERROR_INT("xmlSchemaIDCRegisterMatchers",
22601 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022602 return (-1);
22603 }
22604 /*
22605 * Create an IDC matcher for every IDC definition.
22606 */
22607 matcher = (xmlSchemaIDCMatcherPtr)
22608 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22609 if (matcher == NULL) {
22610 xmlSchemaVErrMemory(vctxt,
22611 "allocating an IDC matcher", NULL);
22612 return (-1);
22613 }
22614 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22615 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022616 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022617 else
22618 last->next = matcher;
22619 last = matcher;
22620
22621 matcher->type = IDC_MATCHER;
22622 matcher->depth = vctxt->depth;
22623 matcher->aidc = aidc;
22624#if DEBUG_IDC
22625 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
22626#endif
22627 /*
22628 * Init the automaton state object.
22629 */
22630 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022631 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022632 return (-1);
22633
22634 idc = idc->next;
22635 } while (idc != NULL);
22636 return (0);
22637}
22638
22639/**
22640 * xmlSchemaBubbleIDCNodeTables:
22641 * @depth: the current tree depth
22642 *
22643 * Merges IDC bindings of an element at @depth into the corresponding IDC
22644 * bindings of its parent element. If a duplicate note-table entry is found,
22645 * both, the parent node-table entry and child entry are discarded from the
22646 * node-table of the parent.
22647 *
22648 * Returns 0 if OK and -1 on internal errors.
22649 */
22650static int
22651xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
22652{
22653 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022654 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
22655 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022656 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
22657 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022658 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022659 int duplTop;
22660
22661 /*
22662 * The node table has the following sections:
22663 *
22664 * O --> old node-table entries (first)
22665 * O
22666 * + --> new node-table entries
22667 * +
22668 * % --> new duplicate node-table entries
22669 * %
22670 * # --> old duplicate node-table entries
22671 * # (last)
22672 *
22673 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022674 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022675 if (bind == NULL) {
22676 /* Fine, no table, no bubbles. */
22677 return (0);
22678 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022679
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022680 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
22681 /*
22682 * Walk all bindings; create new or add to existing bindings.
22683 * Remove duplicate key-sequences.
22684 */
22685start_binding:
22686 while (bind != NULL) {
22687 /*
22688 * Skip keyref IDCs.
22689 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022690 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22691 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022692 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022693 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022694 /*
22695 * Check if the key/unique IDC table needs to be bubbled.
22696 */
22697 aidc = vctxt->aidcs;
22698 do {
22699 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022700 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022701 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022702 bind = bind->next;
22703 goto start_binding;
22704 }
22705 break;
22706 }
22707 aidc = aidc->next;
22708 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022709
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022710 if (parTable != NULL)
22711 parBind = *parTable;
22712 while (parBind != NULL) {
22713 /*
22714 * Search a matching parent binding for the
22715 * IDC definition.
22716 */
22717 if (parBind->definition == bind->definition) {
22718
22719 /*
22720 * Compare every node-table entry of the child node,
22721 * i.e. the key-sequence within, ...
22722 */
22723 oldNum = parBind->nbNodes; /* Skip newly added items. */
22724 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022725 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022726
22727 for (i = 0; i < bind->nbNodes; i++) {
22728 node = bind->nodeTable[i];
22729 if (node == NULL)
22730 continue;
22731 /*
22732 * ...with every key-sequence of the parent node, already
22733 * evaluated to be a duplicate key-sequence.
22734 */
22735 if (parBind->nbDupls != 0) {
22736 j = bind->nbNodes + newDupls;
22737 while (j < duplTop) {
22738 parNode = parBind->nodeTable[j];
22739 for (k = 0; k < bind->definition->nbFields; k++) {
22740 key = node->keys[k];
22741 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022742 ret = xmlSchemaAreValuesEqual(key->val,
22743 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022744 if (ret == -1) {
22745 /* TODO: Internal error */
22746 return(-1);
22747 } else if (ret == 0)
22748 break;
22749
22750 }
22751 if (ret == 1)
22752 /* Duplicate found. */
22753 break;
22754 j++;
22755 }
22756 if (j != duplTop) {
22757 /* Duplicate found. */
22758 continue;
22759 }
22760 }
22761 /*
22762 * ... and with every key-sequence of the parent node.
22763 */
22764 j = 0;
22765 while (j < oldNum) {
22766 parNode = parBind->nodeTable[j];
22767 /*
22768 * Compare key by key.
22769 */
22770 for (k = 0; k < parBind->definition->nbFields; k++) {
22771 key = node->keys[k];
22772 parKey = parNode->keys[k];
22773
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022774 ret = xmlSchemaAreValuesEqual(key->val,
22775 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022776 if (ret == -1) {
22777 /* TODO: Internal error */
22778 } else if (ret == 0)
22779 break;
22780
22781 }
22782 if (ret == 1)
22783 /*
22784 * The key-sequences are equal.
22785 */
22786 break;
22787 j++;
22788 }
22789 if (j != oldNum) {
22790 /*
22791 * Handle duplicates.
22792 */
22793 newDupls++;
22794 oldNum--;
22795 parBind->nbNodes--;
22796 /*
22797 * Move last old item to pos of duplicate.
22798 */
22799 parBind->nodeTable[j] =
22800 parBind->nodeTable[oldNum];
22801
22802 if (parBind->nbNodes != oldNum) {
22803 /*
22804 * If new items exist, move last new item to
22805 * last of old items.
22806 */
22807 parBind->nodeTable[oldNum] =
22808 parBind->nodeTable[parBind->nbNodes];
22809 }
22810 /*
22811 * Move duplicate to last pos of new/old items.
22812 */
22813 parBind->nodeTable[parBind->nbNodes] = parNode;
22814
22815 } else {
22816 /*
22817 * Add the node-table entry (node and key-sequence) of
22818 * the child node to the node table of the parent node.
22819 */
22820 if (parBind->nodeTable == NULL) {
22821 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022822 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022823 if (parBind->nodeTable == NULL) {
22824 xmlSchemaVErrMemory(NULL,
22825 "allocating IDC list of node-table items", NULL);
22826 return(-1);
22827 }
22828 parBind->sizeNodes = 1;
22829 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022830 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022831 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22832 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
22833 sizeof(xmlSchemaPSVIIDCNodePtr));
22834 if (parBind->nodeTable == NULL) {
22835 xmlSchemaVErrMemory(NULL,
22836 "re-allocating IDC list of node-table items", NULL);
22837 return(-1);
22838 }
22839 }
22840
22841 /*
22842 * Move first old duplicate to last position
22843 * of old duplicates +1.
22844 */
22845 if (parBind->nbDupls != 0) {
22846 parBind->nodeTable[duplTop] =
22847 parBind->nodeTable[parBind->nbNodes + newDupls];
22848 }
22849 /*
22850 * Move first new duplicate to last position of
22851 * new duplicates +1.
22852 */
22853 if (newDupls != 0) {
22854 parBind->nodeTable[parBind->nbNodes + newDupls] =
22855 parBind->nodeTable[parBind->nbNodes];
22856 }
22857 /*
22858 * Append the new node-table entry to the 'new node-table
22859 * entries' section.
22860 */
22861 parBind->nodeTable[parBind->nbNodes] = node;
22862 parBind->nbNodes++;
22863 duplTop++;
22864 }
22865 }
22866 parBind->nbDupls += newDupls;
22867 break;
22868 }
22869 if (parBind->next == NULL)
22870 lastParBind = parBind;
22871 parBind = parBind->next;
22872 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000022873 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022874 /*
22875 * No binding for the IDC was found: create a new one and
22876 * copy all node-tables.
22877 */
22878 parBind = xmlSchemaIDCNewBinding(bind->definition);
22879 if (parBind == NULL)
22880 return(-1);
22881
22882 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22883 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
22884 if (parBind->nodeTable == NULL) {
22885 xmlSchemaVErrMemory(NULL,
22886 "allocating an array of IDC node-table items", NULL);
22887 xmlSchemaIDCFreeBinding(parBind);
22888 return(-1);
22889 }
22890 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022891 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022892 memcpy(parBind->nodeTable, bind->nodeTable,
22893 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022894 if (*parTable == NULL)
22895 *parTable = parBind;
22896 else
22897 lastParBind->next = parBind;
22898 }
22899 bind = bind->next;
22900 }
22901 return (0);
22902}
22903
22904/**
22905 * xmlSchemaCheckCVCIDCKeyRef:
22906 * @vctxt: the WXS validation context
22907 * @elemDecl: the element declaration
22908 *
22909 * Check the cvc-idc-keyref constraints.
22910 */
22911static int
22912xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
22913{
22914 xmlSchemaPSVIIDCBindingPtr refbind, bind;
22915
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022916 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022917 /*
22918 * Find a keyref.
22919 */
22920 while (refbind != NULL) {
22921 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22922 int i, j, k, res;
22923 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
22924 xmlSchemaPSVIIDCKeyPtr refKey, key;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022925 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022926
22927 /*
22928 * Find the referred key/unique.
22929 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022930 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022931 do {
22932 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
22933 bind->definition)
22934 break;
22935 bind = bind->next;
22936 } while (bind != NULL);
22937
22938 /*
22939 * Search for a matching key-sequences.
22940 */
22941 for (i = 0; i < refbind->nbNodes; i++) {
22942 res = 0;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022943 refNode = refbind->nodeTable[i];
22944 if (bind != NULL) {
22945 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022946 for (j = 0; j < bind->nbNodes; j++) {
22947 keys = bind->nodeTable[j]->keys;
22948 for (k = 0; k < bind->definition->nbFields; k++) {
22949 refKey = refKeys[k];
22950 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022951 res = xmlSchemaAreValuesEqual(key->val,
22952 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022953 if (res == 0)
22954 break;
22955 else if (res == -1) {
22956 return (-1);
22957 }
22958 }
22959 if (res == 1) {
22960 /*
22961 * Match found.
22962 */
22963 break;
22964 }
22965 }
22966 }
22967 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022968 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022969 xmlSchemaKeyrefErr(vctxt,
22970 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022971 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022972 "No match found for key-sequence %s of key "
22973 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022974 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022975 refbind->nodeTable[i]->keys,
22976 refbind->definition->nbFields),
22977 xmlSchemaFormatQName(&strB,
22978 refbind->definition->targetNamespace,
22979 refbind->definition->name));
22980 FREE_AND_NULL(str);
22981 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022982 }
22983 }
22984 }
22985 refbind = refbind->next;
22986 }
22987 return (0);
22988}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022989
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022990/************************************************************************
22991 * *
22992 * XML Reader validation code *
22993 * *
22994 ************************************************************************/
22995
22996static xmlSchemaAttrInfoPtr
22997xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022998{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022999 xmlSchemaAttrInfoPtr iattr;
23000 /*
23001 * Grow/create list of attribute infos.
23002 */
23003 if (vctxt->attrInfos == NULL) {
23004 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23005 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23006 vctxt->sizeAttrInfos = 1;
23007 if (vctxt->attrInfos == NULL) {
23008 xmlSchemaVErrMemory(vctxt,
23009 "allocating attribute info list", NULL);
23010 return (NULL);
23011 }
23012 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23013 vctxt->sizeAttrInfos++;
23014 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23015 xmlRealloc(vctxt->attrInfos,
23016 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23017 if (vctxt->attrInfos == NULL) {
23018 xmlSchemaVErrMemory(vctxt,
23019 "re-allocating attribute info list", NULL);
23020 return (NULL);
23021 }
23022 } else {
23023 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23024 if (iattr->localName != NULL) {
23025 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23026 "attr info not cleared");
23027 return (NULL);
23028 }
23029 iattr->nodeType = XML_ATTRIBUTE_NODE;
23030 return (iattr);
23031 }
23032 /*
23033 * Create an attribute info.
23034 */
23035 iattr = (xmlSchemaAttrInfoPtr)
23036 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23037 if (iattr == NULL) {
23038 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23039 return (NULL);
23040 }
23041 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23042 iattr->nodeType = XML_ATTRIBUTE_NODE;
23043 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23044
23045 return (iattr);
23046}
23047
23048static int
23049xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23050 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023051 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023052 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023053 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023054 int ownedNames,
23055 xmlChar *value,
23056 int ownedValue)
23057{
23058 xmlSchemaAttrInfoPtr attr;
23059
23060 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23061 if (attr == NULL) {
23062 VERROR_INT("xmlSchemaPushAttribute",
23063 "calling xmlSchemaGetFreshAttrInfo()");
23064 return (-1);
23065 }
23066 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023067 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023068 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23069 attr->localName = localName;
23070 attr->nsName = nsName;
23071 if (ownedNames)
23072 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23073 /*
23074 * Evaluate if it's an XSI attribute.
23075 */
23076 if (nsName != NULL) {
23077 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23078 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23079 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23080 }
23081 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23082 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23083 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23084 }
23085 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23086 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23087 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23088 }
23089 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23090 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23091 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23092 }
23093 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23094 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23095 }
23096 }
23097 attr->value = value;
23098 if (ownedValue)
23099 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23100 if (attr->metaType != 0)
23101 attr->state = XML_SCHEMAS_ATTR_META;
23102 return (0);
23103}
23104
23105static void
23106xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23107{
23108 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23109 FREE_AND_NULL(ielem->localName);
23110 FREE_AND_NULL(ielem->nsName);
23111 } else {
23112 ielem->localName = NULL;
23113 ielem->nsName = NULL;
23114 }
23115 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23116 FREE_AND_NULL(ielem->value);
23117 } else {
23118 ielem->value = NULL;
23119 }
23120 if (ielem->val != NULL) {
23121 xmlSchemaFreeValue(ielem->val);
23122 ielem->val = NULL;
23123 }
23124 if (ielem->idcMatchers != NULL) {
23125 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23126 ielem->idcMatchers = NULL;
23127 }
23128 if (ielem->idcTable != NULL) {
23129 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23130 ielem->idcTable = NULL;
23131 }
23132 if (ielem->regexCtxt != NULL) {
23133 xmlRegFreeExecCtxt(ielem->regexCtxt);
23134 ielem->regexCtxt = NULL;
23135 }
23136 if (ielem->nsBindings != NULL) {
23137 xmlFree((xmlChar **)ielem->nsBindings);
23138 ielem->nsBindings = NULL;
23139 ielem->nbNsBindings = 0;
23140 ielem->sizeNsBindings = 0;
23141 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023142}
23143
23144/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023145 * xmlSchemaGetFreshElemInfo:
23146 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023147 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023148 * Creates/reuses and initializes the element info item for
23149 * the currect tree depth.
23150 *
23151 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023152 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023153static xmlSchemaNodeInfoPtr
23154xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023155{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023156 xmlSchemaNodeInfoPtr info = NULL;
23157
23158 if (vctxt->depth > vctxt->sizeElemInfos) {
23159 VERROR_INT("xmlSchemaGetFreshElemInfo",
23160 "inconsistent depth encountered");
23161 return (NULL);
23162 }
23163 if (vctxt->elemInfos == NULL) {
23164 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23165 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23166 if (vctxt->elemInfos == NULL) {
23167 xmlSchemaVErrMemory(vctxt,
23168 "allocating the element info array", NULL);
23169 return (NULL);
23170 }
23171 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23172 vctxt->sizeElemInfos = 10;
23173 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23174 int i = vctxt->sizeElemInfos;
23175
23176 vctxt->sizeElemInfos *= 2;
23177 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23178 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23179 sizeof(xmlSchemaNodeInfoPtr));
23180 if (vctxt->elemInfos == NULL) {
23181 xmlSchemaVErrMemory(vctxt,
23182 "re-allocating the element info array", NULL);
23183 return (NULL);
23184 }
23185 /*
23186 * We need the new memory to be NULLed.
23187 * TODO: Use memset instead?
23188 */
23189 for (; i < vctxt->sizeElemInfos; i++)
23190 vctxt->elemInfos[i] = NULL;
23191 } else
23192 info = vctxt->elemInfos[vctxt->depth];
23193
23194 if (info == NULL) {
23195 info = (xmlSchemaNodeInfoPtr)
23196 xmlMalloc(sizeof(xmlSchemaNodeInfo));
23197 if (info == NULL) {
23198 xmlSchemaVErrMemory(vctxt,
23199 "allocating an element info", NULL);
23200 return (NULL);
23201 }
23202 vctxt->elemInfos[vctxt->depth] = info;
23203 } else {
23204 if (info->localName != NULL) {
23205 VERROR_INT("xmlSchemaGetFreshElemInfo",
23206 "elem info has not been cleared");
23207 return (NULL);
23208 }
23209 }
23210 memset(info, 0, sizeof(xmlSchemaNodeInfo));
23211 info->nodeType = XML_ELEMENT_NODE;
23212 info->depth = vctxt->depth;
23213
23214 return (info);
23215}
23216
23217#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23218#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23219#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23220
23221static int
23222xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23223 xmlNodePtr node,
23224 xmlSchemaTypePtr type,
23225 xmlSchemaValType valType,
23226 const xmlChar * value,
23227 xmlSchemaValPtr val,
23228 unsigned long length,
23229 int fireErrors)
23230{
23231 int ret, error = 0;
23232
23233 xmlSchemaTypePtr tmpType;
23234 xmlSchemaFacetLinkPtr facetLink;
23235 xmlSchemaFacetPtr facet;
23236 unsigned long len = 0;
23237 xmlSchemaWhitespaceValueType ws;
23238
23239 /*
23240 * In Libxml2, derived built-in types have currently no explicit facets.
23241 */
23242 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023243 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023244
23245 /*
23246 * NOTE: Do not jump away, if the facetSet of the given type is
23247 * empty: until now, "pattern" and "enumeration" facets of the
23248 * *base types* need to be checked as well.
23249 */
23250 if (type->facetSet == NULL)
23251 goto pattern_and_enum;
23252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023253 if (! WXS_IS_ATOMIC(type)) {
23254 if (WXS_IS_LIST(type))
23255 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023256 else
23257 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023258 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023259 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023260 * Whitespace handling is only of importance for string-based
23261 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023263 tmpType = xmlSchemaGetPrimitiveType(type);
23264 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023265 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023266 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23267 } else
23268 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23269 /*
23270 * If the value was not computed (for string or
23271 * anySimpleType based types), then use the provided
23272 * type.
23273 */
23274 if (val == NULL)
23275 valType = valType;
23276 else
23277 valType = xmlSchemaGetValType(val);
23278
23279 ret = 0;
23280 for (facetLink = type->facetSet; facetLink != NULL;
23281 facetLink = facetLink->next) {
23282 /*
23283 * Skip the pattern "whiteSpace": it is used to
23284 * format the character content beforehand.
23285 */
23286 switch (facetLink->facet->type) {
23287 case XML_SCHEMA_FACET_WHITESPACE:
23288 case XML_SCHEMA_FACET_PATTERN:
23289 case XML_SCHEMA_FACET_ENUMERATION:
23290 continue;
23291 case XML_SCHEMA_FACET_LENGTH:
23292 case XML_SCHEMA_FACET_MINLENGTH:
23293 case XML_SCHEMA_FACET_MAXLENGTH:
23294 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23295 valType, value, val, &len, ws);
23296 break;
23297 default:
23298 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23299 valType, value, val, ws);
23300 break;
23301 }
23302 if (ret < 0) {
23303 AERROR_INT("xmlSchemaValidateFacets",
23304 "validating against a atomic type facet");
23305 return (-1);
23306 } else if (ret > 0) {
23307 if (fireErrors)
23308 xmlSchemaFacetErr(actxt, ret, node,
23309 value, len, type, facetLink->facet, NULL, NULL, NULL);
23310 else
23311 return (ret);
23312 if (error == 0)
23313 error = ret;
23314 }
23315 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023316 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023317
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023318WXS_IS_LIST:
23319 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023320 goto pattern_and_enum;
23321 /*
23322 * "length", "minLength" and "maxLength" of list types.
23323 */
23324 ret = 0;
23325 for (facetLink = type->facetSet; facetLink != NULL;
23326 facetLink = facetLink->next) {
23327
23328 switch (facetLink->facet->type) {
23329 case XML_SCHEMA_FACET_LENGTH:
23330 case XML_SCHEMA_FACET_MINLENGTH:
23331 case XML_SCHEMA_FACET_MAXLENGTH:
23332 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23333 value, length, NULL);
23334 break;
23335 default:
23336 continue;
23337 }
23338 if (ret < 0) {
23339 AERROR_INT("xmlSchemaValidateFacets",
23340 "validating against a list type facet");
23341 return (-1);
23342 } else if (ret > 0) {
23343 if (fireErrors)
23344 xmlSchemaFacetErr(actxt, ret, node,
23345 value, length, type, facetLink->facet, NULL, NULL, NULL);
23346 else
23347 return (ret);
23348 if (error == 0)
23349 error = ret;
23350 }
23351 ret = 0;
23352 }
23353
23354pattern_and_enum:
23355 if (error >= 0) {
23356 int found = 0;
23357 /*
23358 * Process enumerations. Facet values are in the value space
23359 * of the defining type's base type. This seems to be a bug in the
23360 * XML Schema 1.0 spec. Use the whitespace type of the base type.
23361 * Only the first set of enumerations in the ancestor-or-self axis
23362 * is used for validation.
23363 */
23364 ret = 0;
23365 tmpType = type;
23366 do {
23367 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23368 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23369 continue;
23370 found = 1;
23371 ret = xmlSchemaAreValuesEqual(facet->val, val);
23372 if (ret == 1)
23373 break;
23374 else if (ret < 0) {
23375 AERROR_INT("xmlSchemaValidateFacets",
23376 "validating against an enumeration facet");
23377 return (-1);
23378 }
23379 }
23380 if (ret != 0)
23381 break;
23382 tmpType = tmpType->baseType;
23383 } while ((tmpType != NULL) &&
23384 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23385 if (found && (ret == 0)) {
23386 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23387 if (fireErrors) {
23388 xmlSchemaFacetErr(actxt, ret, node,
23389 value, 0, type, NULL, NULL, NULL, NULL);
23390 } else
23391 return (ret);
23392 if (error == 0)
23393 error = ret;
23394 }
23395 }
23396
23397 if (error >= 0) {
23398 int found;
23399 /*
23400 * Process patters. Pattern facets are ORed at type level
23401 * and ANDed if derived. Walk the base type axis.
23402 */
23403 tmpType = type;
23404 facet = NULL;
23405 do {
23406 found = 0;
23407 for (facetLink = tmpType->facetSet; facetLink != NULL;
23408 facetLink = facetLink->next) {
23409 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23410 continue;
23411 found = 1;
23412 /*
23413 * NOTE that for patterns, @value needs to be the
23414 * normalized vaule.
23415 */
23416 ret = xmlRegexpExec(facetLink->facet->regexp, value);
23417 if (ret == 1)
23418 break;
23419 else if (ret < 0) {
23420 AERROR_INT("xmlSchemaValidateFacets",
23421 "validating against a pattern facet");
23422 return (-1);
23423 } else {
23424 /*
23425 * Save the last non-validating facet.
23426 */
23427 facet = facetLink->facet;
23428 }
23429 }
23430 if (found && (ret != 1)) {
23431 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
23432 if (fireErrors) {
23433 xmlSchemaFacetErr(actxt, ret, node,
23434 value, 0, type, facet, NULL, NULL, NULL);
23435 } else
23436 return (ret);
23437 if (error == 0)
23438 error = ret;
23439 break;
23440 }
23441 tmpType = tmpType->baseType;
23442 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23443 }
23444
23445 return (error);
23446}
23447
23448static xmlChar *
23449xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
23450 const xmlChar *value)
23451{
23452 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
23453 case XML_SCHEMA_WHITESPACE_COLLAPSE:
23454 return (xmlSchemaCollapseString(value));
23455 case XML_SCHEMA_WHITESPACE_REPLACE:
23456 return (xmlSchemaWhiteSpaceReplace(value));
23457 default:
23458 return (NULL);
23459 }
23460}
23461
23462static int
23463xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
23464 const xmlChar *value,
23465 xmlSchemaValPtr *val,
23466 int valNeeded)
23467{
23468 int ret;
23469 const xmlChar *nsName;
23470 xmlChar *local, *prefix = NULL;
23471
23472 ret = xmlValidateQName(value, 1);
23473 if (ret != 0) {
23474 if (ret == -1) {
23475 VERROR_INT("xmlSchemaValidateQName",
23476 "calling xmlValidateQName()");
23477 return (-1);
23478 }
23479 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
23480 }
23481 /*
23482 * NOTE: xmlSplitQName2 will always return a duplicated
23483 * strings.
23484 */
23485 local = xmlSplitQName2(value, &prefix);
23486 if (local == NULL)
23487 local = xmlStrdup(value);
23488 /*
23489 * OPTIMIZE TODO: Use flags for:
23490 * - is there any namespace binding?
23491 * - is there a default namespace?
23492 */
23493 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23494
23495 if (prefix != NULL) {
23496 xmlFree(prefix);
23497 /*
23498 * A namespace must be found if the prefix is
23499 * NOT NULL.
23500 */
23501 if (nsName == NULL) {
23502 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023503 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023504 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023505 "The QName value '%s' has no "
23506 "corresponding namespace declaration in "
23507 "scope", value, NULL);
23508 if (local != NULL)
23509 xmlFree(local);
23510 return (ret);
23511 }
23512 }
23513 if (valNeeded && val) {
23514 if (nsName != NULL)
23515 *val = xmlSchemaNewQNameValue(
23516 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
23517 else
23518 *val = xmlSchemaNewQNameValue(NULL,
23519 BAD_CAST local);
23520 } else
23521 xmlFree(local);
23522 return (0);
23523}
23524
23525/*
23526* cvc-simple-type
23527*/
23528static int
23529xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
23530 xmlNodePtr node,
23531 xmlSchemaTypePtr type,
23532 const xmlChar *value,
23533 xmlSchemaValPtr *retVal,
23534 int fireErrors,
23535 int normalize,
23536 int isNormalized)
23537{
23538 int ret = 0, valNeeded = (retVal) ? 1 : 0;
23539 xmlSchemaValPtr val = NULL;
23540 xmlSchemaWhitespaceValueType ws;
23541 xmlChar *normValue = NULL;
23542
23543#define NORMALIZE(atype) \
23544 if ((! isNormalized) && \
23545 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
23546 normValue = xmlSchemaNormalizeValue(atype, value); \
23547 if (normValue != NULL) \
23548 value = normValue; \
23549 isNormalized = 1; \
23550 }
23551
23552 if ((retVal != NULL) && (*retVal != NULL)) {
23553 xmlSchemaFreeValue(*retVal);
23554 *retVal = NULL;
23555 }
23556 /*
23557 * 3.14.4 Simple Type Definition Validation Rules
23558 * Validation Rule: String Valid
23559 */
23560 /*
23561 * 1 It is schema-valid with respect to that definition as defined
23562 * by Datatype Valid in [XML Schemas: Datatypes].
23563 */
23564 /*
23565 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
23566 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
23567 * the string must be a ·declared entity name·.
23568 */
23569 /*
23570 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
23571 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
23572 * then every whitespace-delimited substring of the string must be a ·declared
23573 * entity name·.
23574 */
23575 /*
23576 * 2.3 otherwise no further condition applies.
23577 */
23578 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
23579 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000023580 if (value == NULL)
23581 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023582 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023583 xmlSchemaTypePtr biType; /* The built-in type. */
23584 /*
23585 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
23586 * a literal in the ·lexical space· of {base type definition}"
23587 */
23588 /*
23589 * Whitespace-normalize.
23590 */
23591 NORMALIZE(type);
23592 if (type->type != XML_SCHEMA_TYPE_BASIC) {
23593 /*
23594 * Get the built-in type.
23595 */
23596 biType = type->baseType;
23597 while ((biType != NULL) &&
23598 (biType->type != XML_SCHEMA_TYPE_BASIC))
23599 biType = biType->baseType;
23600
23601 if (biType == NULL) {
23602 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23603 "could not get the built-in type");
23604 goto internal_error;
23605 }
23606 } else
23607 biType = type;
23608 /*
23609 * NOTATIONs need to be processed here, since they need
23610 * to lookup in the hashtable of NOTATION declarations of the schema.
23611 */
23612 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
23613 switch (biType->builtInType) {
23614 case XML_SCHEMAS_NOTATION:
23615 ret = xmlSchemaValidateNotation(
23616 (xmlSchemaValidCtxtPtr) actxt,
23617 ((xmlSchemaValidCtxtPtr) actxt)->schema,
23618 NULL, value, &val, valNeeded);
23619 break;
23620 case XML_SCHEMAS_QNAME:
23621 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
23622 value, &val, valNeeded);
23623 break;
23624 default:
23625 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23626 if (valNeeded)
23627 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
23628 value, &val, NULL);
23629 else
23630 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
23631 value, NULL, NULL);
23632 break;
23633 }
23634 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
23635 switch (biType->builtInType) {
23636 case XML_SCHEMAS_NOTATION:
23637 ret = xmlSchemaValidateNotation(NULL,
23638 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
23639 value, &val, valNeeded);
23640 break;
23641 default:
23642 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23643 if (valNeeded)
23644 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
23645 value, &val, node);
23646 else
23647 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
23648 value, NULL, node);
23649 break;
23650 }
23651 } else {
23652 /*
23653 * Validation via a public API is not implemented yet.
23654 */
23655 TODO
23656 goto internal_error;
23657 }
23658 if (ret != 0) {
23659 if (ret < 0) {
23660 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23661 "validating against a built-in type");
23662 goto internal_error;
23663 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023664 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023665 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
23666 else
23667 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
23668 }
23669 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
23670 /*
23671 * Check facets.
23672 */
23673 ret = xmlSchemaValidateFacets(actxt, node, type,
23674 (xmlSchemaValType) biType->builtInType, value, val,
23675 0, fireErrors);
23676 if (ret != 0) {
23677 if (ret < 0) {
23678 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23679 "validating facets of atomic simple type");
23680 goto internal_error;
23681 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023682 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023683 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
23684 else
23685 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
23686 }
23687 }
23688 if (fireErrors && (ret > 0))
23689 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023690 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023691
23692 xmlSchemaTypePtr itemType;
23693 const xmlChar *cur, *end;
23694 xmlChar *tmpValue = NULL;
23695 unsigned long len = 0;
23696 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
23697 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
23698 * of white space separated tokens, each of which ·match·es a literal
23699 * in the ·lexical space· of {item type definition}
23700 */
23701 /*
23702 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
23703 * the list type has an enum or pattern facet.
23704 */
23705 NORMALIZE(type);
23706 /*
23707 * VAL TODO: Optimize validation of empty values.
23708 * VAL TODO: We do not have computed values for lists.
23709 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023710 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023711 cur = value;
23712 do {
23713 while (IS_BLANK_CH(*cur))
23714 cur++;
23715 end = cur;
23716 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
23717 end++;
23718 if (end == cur)
23719 break;
23720 tmpValue = xmlStrndup(cur, end - cur);
23721 len++;
23722
23723 if (valNeeded)
23724 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
23725 tmpValue, &curVal, fireErrors, 0, 1);
23726 else
23727 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
23728 tmpValue, NULL, fireErrors, 0, 1);
23729 FREE_AND_NULL(tmpValue);
23730 if (curVal != NULL) {
23731 /*
23732 * Add to list of computed values.
23733 */
23734 if (val == NULL)
23735 val = curVal;
23736 else
23737 xmlSchemaValueAppend(prevVal, curVal);
23738 prevVal = curVal;
23739 curVal = NULL;
23740 }
23741 if (ret != 0) {
23742 if (ret < 0) {
23743 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23744 "validating an item of list simple type");
23745 goto internal_error;
23746 }
23747 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
23748 break;
23749 }
23750 cur = end;
23751 } while (*cur != 0);
23752 FREE_AND_NULL(tmpValue);
23753 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
23754 /*
23755 * Apply facets (pattern, enumeration).
23756 */
23757 ret = xmlSchemaValidateFacets(actxt, node, type,
23758 XML_SCHEMAS_UNKNOWN, value, val,
23759 len, fireErrors);
23760 if (ret != 0) {
23761 if (ret < 0) {
23762 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23763 "validating facets of list simple type");
23764 goto internal_error;
23765 }
23766 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
23767 }
23768 }
23769 if (fireErrors && (ret > 0)) {
23770 /*
23771 * Report the normalized value.
23772 */
23773 normalize = 1;
23774 NORMALIZE(type);
23775 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
23776 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023777 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023778 xmlSchemaTypeLinkPtr memberLink;
23779 /*
23780 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
23781 * not apply directly; however, the normalization behavior of ·union·
23782 * types is controlled by the value of whiteSpace on that one of the
23783 * ·memberTypes· against which the ·union· is successfully validated.
23784 *
23785 * This means that the value is normalized by the first validating
23786 * member type, then the facets of the union type are applied. This
23787 * needs changing of the value!
23788 */
23789
23790 /*
23791 * 1.2.3 if {variety} is ·union· then the string must ·match· a
23792 * literal in the ·lexical space· of at least one member of
23793 * {member type definitions}
23794 */
23795 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
23796 if (memberLink == NULL) {
23797 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23798 "union simple type has no member types");
23799 goto internal_error;
23800 }
23801 /*
23802 * Always normalize union type values, since we currently
23803 * cannot store the whitespace information with the value
23804 * itself; otherwise a later value-comparison would be
23805 * not possible.
23806 */
23807 while (memberLink != NULL) {
23808 if (valNeeded)
23809 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
23810 memberLink->type, value, &val, 0, 1, 0);
23811 else
23812 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
23813 memberLink->type, value, NULL, 0, 1, 0);
23814 if (ret <= 0)
23815 break;
23816 memberLink = memberLink->next;
23817 }
23818 if (ret != 0) {
23819 if (ret < 0) {
23820 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23821 "validating members of union simple type");
23822 goto internal_error;
23823 }
23824 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
23825 }
23826 /*
23827 * Apply facets (pattern, enumeration).
23828 */
23829 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
23830 /*
23831 * The normalization behavior of ·union· types is controlled by
23832 * the value of whiteSpace on that one of the ·memberTypes·
23833 * against which the ·union· is successfully validated.
23834 */
23835 NORMALIZE(memberLink->type);
23836 ret = xmlSchemaValidateFacets(actxt, node, type,
23837 XML_SCHEMAS_UNKNOWN, value, val,
23838 0, fireErrors);
23839 if (ret != 0) {
23840 if (ret < 0) {
23841 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
23842 "validating facets of union simple type");
23843 goto internal_error;
23844 }
23845 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
23846 }
23847 }
23848 if (fireErrors && (ret > 0))
23849 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
23850 }
23851
23852 if (normValue != NULL)
23853 xmlFree(normValue);
23854 if (ret == 0) {
23855 if (retVal != NULL)
23856 *retVal = val;
23857 else if (val != NULL)
23858 xmlSchemaFreeValue(val);
23859 } else if (val != NULL)
23860 xmlSchemaFreeValue(val);
23861 return (ret);
23862internal_error:
23863 if (normValue != NULL)
23864 xmlFree(normValue);
23865 if (val != NULL)
23866 xmlSchemaFreeValue(val);
23867 return (-1);
23868}
23869
23870static int
23871xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
23872 const xmlChar *value,
23873 const xmlChar **nsName,
23874 const xmlChar **localName)
23875{
23876 int ret = 0;
23877
23878 if ((nsName == NULL) || (localName == NULL))
23879 return (-1);
23880 *nsName = NULL;
23881 *localName = NULL;
23882
23883 ret = xmlValidateQName(value, 1);
23884 if (ret == -1)
23885 return (-1);
23886 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023887 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023888 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
23889 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
23890 return (1);
23891 }
23892 {
23893 xmlChar *local = NULL;
23894 xmlChar *prefix;
23895
23896 /*
23897 * NOTE: xmlSplitQName2 will return a duplicated
23898 * string.
23899 */
23900 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023901 if (local == NULL)
23902 *localName = xmlDictLookup(vctxt->dict, value, -1);
23903 else {
23904 *localName = xmlDictLookup(vctxt->dict, local, -1);
23905 xmlFree(local);
23906 }
23907
23908 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
23909
23910 if (prefix != NULL) {
23911 xmlFree(prefix);
23912 /*
23913 * A namespace must be found if the prefix is NOT NULL.
23914 */
23915 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023916 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023917 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023918 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023919 "The QName value '%s' has no "
23920 "corresponding namespace declaration in scope",
23921 value, NULL);
23922 return (2);
23923 }
23924 }
23925 }
23926 return (0);
23927}
23928
23929static int
23930xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
23931 xmlSchemaAttrInfoPtr iattr,
23932 xmlSchemaTypePtr *localType,
23933 xmlSchemaElementPtr elemDecl)
23934{
23935 int ret = 0;
23936 /*
23937 * cvc-elt (3.3.4) : (4)
23938 * AND
23939 * Schema-Validity Assessment (Element) (cvc-assess-elt)
23940 * (1.2.1.2.1) - (1.2.1.2.4)
23941 * Handle 'xsi:type'.
23942 */
23943 if (localType == NULL)
23944 return (-1);
23945 *localType = NULL;
23946 if (iattr == NULL)
23947 return (0);
23948 else {
23949 const xmlChar *nsName = NULL, *local = NULL;
23950 /*
23951 * TODO: We should report a *warning* that the type was overriden
23952 * by the instance.
23953 */
23954 ACTIVATE_ATTRIBUTE(iattr);
23955 /*
23956 * (cvc-elt) (3.3.4) : (4.1)
23957 * (cvc-assess-elt) (1.2.1.2.2)
23958 */
23959 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
23960 &nsName, &local);
23961 if (ret != 0) {
23962 if (ret < 0) {
23963 VERROR_INT("xmlSchemaValidateElementByDeclaration",
23964 "calling xmlSchemaQNameExpand() to validate the "
23965 "attribute 'xsi:type'");
23966 goto internal_error;
23967 }
23968 goto exit;
23969 }
23970 /*
23971 * (cvc-elt) (3.3.4) : (4.2)
23972 * (cvc-assess-elt) (1.2.1.2.3)
23973 */
23974 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
23975 if (*localType == NULL) {
23976 xmlChar *str = NULL;
23977
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023978 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023979 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023980 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023981 "The QName value '%s' of the xsi:type attribute does not "
23982 "resolve to a type definition",
23983 xmlSchemaFormatQName(&str, nsName, local), NULL);
23984 FREE_AND_NULL(str);
23985 ret = vctxt->err;
23986 goto exit;
23987 }
23988 if (elemDecl != NULL) {
23989 int set = 0;
23990
23991 /*
23992 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
23993 * "The ·local type definition· must be validly
23994 * derived from the {type definition} given the union of
23995 * the {disallowed substitutions} and the {type definition}'s
23996 * {prohibited substitutions}, as defined in
23997 * Type Derivation OK (Complex) (§3.4.6)
23998 * (if it is a complex type definition),
23999 * or given {disallowed substitutions} as defined in Type
24000 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
24001 * definition)."
24002 *
24003 * {disallowed substitutions}: the "block" on the element decl.
24004 * {prohibited substitutions}: the "block" on the type def.
24005 */
24006 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24007 (elemDecl->subtypes->flags &
24008 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24009 set |= SUBSET_EXTENSION;
24010
24011 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24012 (elemDecl->subtypes->flags &
24013 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24014 set |= SUBSET_RESTRICTION;
24015
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024016 if ((vctxt->pctxt == NULL) &&
24017 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24018 return (-1);
24019 if (xmlSchemaCheckCOSDerivedOK(vctxt->pctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024020 elemDecl->subtypes, set) != 0) {
24021 xmlChar *str = NULL;
24022
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024023 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024024 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24025 "The type definition '%s', specified by xsi:type, is "
24026 "blocked or not validly derived from the type definition "
24027 "of the element declaration",
24028 xmlSchemaFormatQName(&str,
24029 (*localType)->targetNamespace,
24030 (*localType)->name),
24031 NULL);
24032 FREE_AND_NULL(str);
24033 ret = vctxt->err;
24034 *localType = NULL;
24035 }
24036 }
24037 }
24038exit:
24039 ACTIVATE_ELEM;
24040 return (ret);
24041internal_error:
24042 ACTIVATE_ELEM;
24043 return (-1);
24044}
24045
24046static int
24047xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24048{
24049 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024050 xmlSchemaTypePtr actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024051
24052 /*
24053 * cvc-elt (3.3.4) : 1
24054 */
24055 if (elemDecl == NULL) {
24056 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24057 "No matching declaration available");
24058 return (vctxt->err);
24059 }
24060 /*
24061 * cvc-elt (3.3.4) : 2
24062 */
24063 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24064 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24065 "The element declaration is abstract");
24066 return (vctxt->err);
24067 }
24068 if (actualType == NULL) {
24069 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24070 "The type definition is absent");
24071 return (XML_SCHEMAV_CVC_TYPE_1);
24072 }
24073 if (vctxt->nbAttrInfos != 0) {
24074 int ret;
24075 xmlSchemaAttrInfoPtr iattr;
24076 /*
24077 * cvc-elt (3.3.4) : 3
24078 * Handle 'xsi:nil'.
24079 */
24080 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24081 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24082 if (iattr) {
24083 ACTIVATE_ATTRIBUTE(iattr);
24084 /*
24085 * Validate the value.
24086 */
24087 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024088 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024089 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24090 iattr->value, &(iattr->val), 1, 0, 0);
24091 ACTIVATE_ELEM;
24092 if (ret < 0) {
24093 VERROR_INT("xmlSchemaValidateElemDecl",
24094 "calling xmlSchemaVCheckCVCSimpleType() to "
24095 "validate the attribute 'xsi:nil'");
24096 return (-1);
24097 }
24098 if (ret == 0) {
24099 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24100 /*
24101 * cvc-elt (3.3.4) : 3.1
24102 */
24103 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24104 "The element is not 'nillable'");
24105 /* Does not return an error on purpose. */
24106 } else {
24107 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24108 /*
24109 * cvc-elt (3.3.4) : 3.2.2
24110 */
24111 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24112 (elemDecl->value != NULL)) {
24113 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24114 "The element cannot be 'nilled' because "
24115 "there is a fixed value constraint defined "
24116 "for it");
24117 /* Does not return an error on purpose. */
24118 } else
24119 vctxt->inode->flags |=
24120 XML_SCHEMA_ELEM_INFO_NILLED;
24121 }
24122 }
24123 }
24124 }
24125 /*
24126 * cvc-elt (3.3.4) : 4
24127 * Handle 'xsi:type'.
24128 */
24129 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24130 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24131 if (iattr) {
24132 xmlSchemaTypePtr localType = NULL;
24133
24134 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24135 elemDecl);
24136 if (ret != 0) {
24137 if (ret == -1) {
24138 VERROR_INT("xmlSchemaValidateElemDecl",
24139 "calling xmlSchemaProcessXSIType() to "
24140 "process the attribute 'xsi:type'");
24141 return (-1);
24142 }
24143 /* Does not return an error on purpose. */
24144 }
24145 if (localType != NULL) {
24146 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24147 actualType = localType;
24148 }
24149 }
24150 }
24151 /*
24152 * IDC: Register identity-constraint XPath matchers.
24153 */
24154 if ((elemDecl->idcs != NULL) &&
24155 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24156 return (-1);
24157 /*
24158 * No actual type definition.
24159 */
24160 if (actualType == NULL) {
24161 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24162 "The type definition is absent");
24163 return (XML_SCHEMAV_CVC_TYPE_1);
24164 }
24165 /*
24166 * Remember the actual type definition.
24167 */
24168 vctxt->inode->typeDef = actualType;
24169
24170 return (0);
24171}
24172
24173static int
24174xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24175{
24176 xmlSchemaAttrInfoPtr iattr;
24177 int ret = 0, i;
24178
24179 /*
24180 * SPEC cvc-type (3.1.1)
24181 * "The attributes of must be empty, excepting those whose namespace
24182 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24183 * whose local name is one of type, nil, schemaLocation or
24184 * noNamespaceSchemaLocation."
24185 */
24186 if (vctxt->nbAttrInfos == 0)
24187 return (0);
24188 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24189 iattr = vctxt->attrInfos[i];
24190 if (! iattr->metaType) {
24191 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024192 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024193 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24194 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24195 }
24196 }
24197 ACTIVATE_ELEM
24198 return (ret);
24199}
24200
24201/*
24202* Cleanup currently used attribute infos.
24203*/
24204static void
24205xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24206{
24207 int i;
24208 xmlSchemaAttrInfoPtr attr;
24209
24210 if (vctxt->nbAttrInfos == 0)
24211 return;
24212 for (i = 0; i < vctxt->nbAttrInfos; i++) {
24213 attr = vctxt->attrInfos[i];
24214 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24215 if (attr->localName != NULL)
24216 xmlFree((xmlChar *) attr->localName);
24217 if (attr->nsName != NULL)
24218 xmlFree((xmlChar *) attr->nsName);
24219 }
24220 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24221 if (attr->value != NULL)
24222 xmlFree((xmlChar *) attr->value);
24223 }
24224 if (attr->val != NULL) {
24225 xmlSchemaFreeValue(attr->val);
24226 attr->val = NULL;
24227 }
24228 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24229 }
24230 vctxt->nbAttrInfos = 0;
24231}
24232
24233/*
24234* 3.4.4 Complex Type Definition Validation Rules
24235* Element Locally Valid (Complex Type) (cvc-complex-type)
24236* 3.2.4 Attribute Declaration Validation Rules
24237* Validation Rule: Attribute Locally Valid (cvc-attribute)
24238* Attribute Locally Valid (Use) (cvc-au)
24239*
24240* Only "assessed" attribute information items will be visible to
24241* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24242*/
24243static int
24244xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24245{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024246 xmlSchemaTypePtr type = vctxt->inode->typeDef;
24247 xmlSchemaItemListPtr attrUseList;
24248 xmlSchemaAttributeUsePtr attrUse = NULL;
24249 xmlSchemaAttributePtr attrDecl = NULL;
24250 xmlSchemaAttrInfoPtr iattr, tmpiattr;
24251 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024252 int xpathRes = 0, res, wildIDs = 0, fixed;
24253
24254 /*
24255 * SPEC (cvc-attribute)
24256 * (1) "The declaration must not be ·absent· (see Missing
24257 * Sub-components (§5.3) for how this can fail to be
24258 * the case)."
24259 * (2) "Its {type definition} must not be absent."
24260 *
24261 * NOTE (1) + (2): This is not handled here, since we currently do not
24262 * allow validation against schemas which have missing sub-components.
24263 *
24264 * SPEC (cvc-complex-type)
24265 * (3) "For each attribute information item in the element information
24266 * item's [attributes] excepting those whose [namespace name] is
24267 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24268 * [local name] is one of type, nil, schemaLocation or
24269 * noNamespaceSchemaLocation, the appropriate case among the following
24270 * must be true:
24271 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024272 */
24273 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24274 /*
24275 * @nbAttrs is the number of attributes present in the instance.
24276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024277 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024278 if (attrUseList != NULL)
24279 nbUses = attrUseList->nbItems;
24280 else
24281 nbUses = 0;
24282 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024283 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024284 attrUse = attrUseList->items[i];
24285 attrDecl = WXS_ATTRUSE_DECL(attrUse);
24286 for (j = 0; j < nbAttrs; j++) {
24287 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024288 /*
24289 * SPEC (cvc-complex-type) (3)
24290 * Skip meta attributes.
24291 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024292 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024293 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024294 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024295 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024296 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024297 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024298 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024299 continue;
24300 found = 1;
24301 /*
24302 * SPEC (cvc-complex-type)
24303 * (3.1) "If there is among the {attribute uses} an attribute
24304 * use with an {attribute declaration} whose {name} matches
24305 * the attribute information item's [local name] and whose
24306 * {target namespace} is identical to the attribute information
24307 * item's [namespace name] (where an ·absent· {target namespace}
24308 * is taken to be identical to a [namespace name] with no value),
24309 * then the attribute information must be ·valid· with respect
24310 * to that attribute use as per Attribute Locally Valid (Use)
24311 * (§3.5.4). In this case the {attribute declaration} of that
24312 * attribute use is the ·context-determined declaration· for the
24313 * attribute information item with respect to Schema-Validity
24314 * Assessment (Attribute) (§3.2.4) and
24315 * Assessment Outcome (Attribute) (§3.2.5).
24316 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024317 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24318 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024319 /*
24320 * Context-determined declaration.
24321 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024322 iattr->decl = attrDecl;
24323 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024324 break;
24325 }
24326
24327 if (found)
24328 continue;
24329
24330 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24331 /*
24332 * Handle non-existent, required attributes.
24333 *
24334 * SPEC (cvc-complex-type)
24335 * (4) "The {attribute declaration} of each attribute use in
24336 * the {attribute uses} whose {required} is true matches one
24337 * of the attribute information items in the element information
24338 * item's [attributes] as per clause 3.1 above."
24339 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024340 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24341 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024342 VERROR_INT(
24343 "xmlSchemaVAttributesComplex",
24344 "calling xmlSchemaGetFreshAttrInfo()");
24345 return (-1);
24346 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024347 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24348 tmpiattr->use = attrUse;
24349 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024350 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24351 ((attrUse->defValue != NULL) ||
24352 (attrDecl->defValue != NULL))) {
24353 /*
24354 * Handle non-existent, optional, default/fixed attributes.
24355 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024356 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24357 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024358 VERROR_INT(
24359 "xmlSchemaVAttributesComplex",
24360 "calling xmlSchemaGetFreshAttrInfo()");
24361 return (-1);
24362 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024363 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24364 tmpiattr->use = attrUse;
24365 tmpiattr->decl = attrDecl;
24366 tmpiattr->typeDef = attrDecl->subtypes;
24367 tmpiattr->localName = attrDecl->name;
24368 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024369 }
24370 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024371
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024372 if (vctxt->nbAttrInfos == 0)
24373 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024374 nbUses = vctxt->nbAttrInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024375 /*
24376 * Validate against the wildcard.
24377 */
24378 if (type->attributeWildcard != NULL) {
24379 /*
24380 * SPEC (cvc-complex-type)
24381 * (3.2.1) "There must be an {attribute wildcard}."
24382 */
24383 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024384 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024385 /*
24386 * SPEC (cvc-complex-type) (3)
24387 * Skip meta attributes.
24388 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024389 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024390 continue;
24391 /*
24392 * SPEC (cvc-complex-type)
24393 * (3.2.2) "The attribute information item must be ·valid· with
24394 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
24395 *
24396 * SPEC Item Valid (Wildcard) (cvc-wildcard)
24397 * "... its [namespace name] must be ·valid· with respect to
24398 * the wildcard constraint, as defined in Wildcard allows
24399 * Namespace Name (§3.10.4)."
24400 */
24401 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024402 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024403 /*
24404 * Handle processContents.
24405 *
24406 * SPEC (cvc-wildcard):
24407 * processContents | context-determined declaration:
24408 * "strict" "mustFind"
24409 * "lax" "none"
24410 * "skip" "skip"
24411 */
24412 if (type->attributeWildcard->processContents ==
24413 XML_SCHEMAS_ANY_SKIP) {
24414 /*
24415 * context-determined declaration = "skip"
24416 *
24417 * SPEC PSVI Assessment Outcome (Attribute)
24418 * [validity] = "notKnown"
24419 * [validation attempted] = "none"
24420 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024421 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024422 continue;
24423 }
24424 /*
24425 * Find an attribute declaration.
24426 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024427 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
24428 iattr->localName, iattr->nsName);
24429 if (iattr->decl != NULL) {
24430 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024431 /*
24432 * SPEC (cvc-complex-type)
24433 * (5) "Let [Definition:] the wild IDs be the set of
24434 * all attribute information item to which clause 3.2
24435 * applied and whose ·validation· resulted in a
24436 * ·context-determined declaration· of mustFind or no
24437 * ·context-determined declaration· at all, and whose
24438 * [local name] and [namespace name] resolve (as
24439 * defined by QName resolution (Instance) (§3.15.4)) to
24440 * an attribute declaration whose {type definition} is
24441 * or is derived from ID. Then all of the following
24442 * must be true:"
24443 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024444 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024445 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024446 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024447 /*
24448 * SPEC (5.1) "There must be no more than one
24449 * item in ·wild IDs·."
24450 */
24451 if (wildIDs != 0) {
24452 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024453 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024454 TODO
24455 continue;
24456 }
24457 wildIDs++;
24458 /*
24459 * SPEC (cvc-complex-type)
24460 * (5.2) "If ·wild IDs· is non-empty, there must not
24461 * be any attribute uses among the {attribute uses}
24462 * whose {attribute declaration}'s {type definition}
24463 * is or is derived from ID."
24464 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024465 for (j = 0; j < attrUseList->nbItems; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024466 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024467 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024468 XML_SCHEMAS_ID)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024469 /* URGENT VAL TODO: implement */
24470 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024471 TODO
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024472 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024473 }
24474 }
24475 }
24476 } else if (type->attributeWildcard->processContents ==
24477 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024478 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024479 /*
24480 * SPEC PSVI Assessment Outcome (Attribute)
24481 * [validity] = "notKnown"
24482 * [validation attempted] = "none"
24483 */
24484 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024485 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024486 }
24487 }
24488 }
24489 }
24490
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024491 if (vctxt->nbAttrInfos == 0)
24492 return (0);
24493
24494 /*
24495 * Validate values, create default attributes, evaluate IDCs.
24496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024497 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024498 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024499 /*
24500 * VAL TODO: Note that we won't try to resolve IDCs to
24501 * "lax" and "skip" validated attributes. Check what to
24502 * do in this case.
24503 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024504 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
24505 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024506 continue;
24507 /*
24508 * VAL TODO: What to do if the type definition is missing?
24509 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024510 if (iattr->typeDef == NULL) {
24511 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024512 continue;
24513 }
24514
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024515 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000024516 fixed = 0;
24517 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024518
24519 if (vctxt->xpathStates != NULL) {
24520 /*
24521 * Evaluate IDCs.
24522 */
24523 xpathRes = xmlSchemaXPathEvaluate(vctxt,
24524 XML_ATTRIBUTE_NODE);
24525 if (xpathRes == -1) {
24526 VERROR_INT("xmlSchemaVAttributesComplex",
24527 "calling xmlSchemaXPathEvaluate()");
24528 goto internal_error;
24529 }
24530 }
24531
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024532 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024533 /*
24534 * Default/fixed attributes.
24535 */
24536 if (xpathRes) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024537 if (iattr->use->defValue != NULL) {
24538 iattr->value = (xmlChar *) iattr->use->defValue;
24539 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024540 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024541 iattr->value = (xmlChar *) iattr->decl->defValue;
24542 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024543 }
24544 /*
24545 * IDCs will consume the precomputed default value,
24546 * so we need to clone it.
24547 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024548 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024549 VERROR_INT("xmlSchemaVAttributesComplex",
24550 "default/fixed value on an attribute use was "
24551 "not precomputed");
24552 goto internal_error;
24553 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024554 iattr->val = xmlSchemaCopyValue(iattr->val);
24555 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024556 VERROR_INT("xmlSchemaVAttributesComplex",
24557 "calling xmlSchemaCopyValue()");
24558 goto internal_error;
24559 }
24560 }
24561 /*
24562 * PSVI: Add the default attribute to the current element.
24563 * VAL TODO: Should we use the *normalized* value? This currently
24564 * uses the *initial* value.
24565 */
24566 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024567 (iattr->node != NULL) && (iattr->node->doc != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024568 xmlChar *normValue;
24569 const xmlChar *value;
24570
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024571 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024572 /*
24573 * Normalize the value.
24574 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024575 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
24576 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024577 if (normValue != NULL)
24578 value = BAD_CAST normValue;
24579
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024580 if (iattr->nsName == NULL) {
24581 if (xmlNewProp(iattr->node->parent,
24582 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024583 VERROR_INT("xmlSchemaVAttributesComplex",
24584 "callling xmlNewProp()");
24585 if (normValue != NULL)
24586 xmlFree(normValue);
24587 goto internal_error;
24588 }
24589 } else {
24590 xmlNsPtr ns;
24591
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024592 ns = xmlSearchNsByHref(iattr->node->doc,
24593 iattr->node->parent, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024594 if (ns == NULL) {
24595 xmlChar prefix[12];
24596 int counter = 0;
24597
24598 /*
24599 * Create a namespace declaration on the validation
24600 * root node if no namespace declaration is in scope.
24601 */
24602 do {
24603 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024604 ns = xmlSearchNs(iattr->node->doc,
24605 iattr->node->parent, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024606 if (counter > 1000) {
24607 VERROR_INT(
24608 "xmlSchemaVAttributesComplex",
24609 "could not compute a ns prefix for a "
24610 "default/fixed attribute");
24611 if (normValue != NULL)
24612 xmlFree(normValue);
24613 goto internal_error;
24614 }
24615 } while (ns != NULL);
24616 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024617 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024618 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024619 /*
24620 * TODO:
24621 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
24622 * If we have QNames: do we need to ensure there's a
24623 * prefix defined for the QName?
24624 */
24625 xmlNewNsProp(iattr->node->parent, ns,
24626 iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024627 }
24628 if (normValue != NULL)
24629 xmlFree(normValue);
24630 }
24631 /*
24632 * Go directly to IDC evaluation.
24633 */
24634 goto eval_idcs;
24635 }
24636 /*
24637 * Validate the value.
24638 */
24639 if (vctxt->value != NULL) {
24640 /*
24641 * Free last computed value; just for safety reasons.
24642 */
24643 xmlSchemaFreeValue(vctxt->value);
24644 vctxt->value = NULL;
24645 }
24646 /*
24647 * Note that the attribute *use* can be unavailable, if
24648 * the attribute was a wild attribute.
24649 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024650 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
24651 ((iattr->use != NULL) &&
24652 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024653 fixed = 1;
24654 else
24655 fixed = 0;
24656 /*
24657 * SPEC (cvc-attribute)
24658 * (3) "The item's ·normalized value· must be locally ·valid·
24659 * with respect to that {type definition} as per
24660 * String Valid (§3.14.4)."
24661 *
24662 * VAL TODO: Do we already have the
24663 * "normalized attribute value" here?
24664 */
24665 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024666 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024667 /*
24668 * Request a computed value.
24669 */
24670 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024671 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024672 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024673 1, 1, 0);
24674 } else {
24675 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024676 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024677 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024678 1, 0, 0);
24679 }
24680
24681 if (res != 0) {
24682 if (res == -1) {
24683 VERROR_INT("xmlSchemaVAttributesComplex",
24684 "calling xmlSchemaStreamValidateSimpleTypeValue()");
24685 goto internal_error;
24686 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024687 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024688 /*
24689 * SPEC PSVI Assessment Outcome (Attribute)
24690 * [validity] = "invalid"
24691 */
24692 goto eval_idcs;
24693 }
24694
24695 if (fixed) {
24696 int ws;
24697 /*
24698 * SPEC Attribute Locally Valid (Use) (cvc-au)
24699 * "For an attribute information item to be·valid·
24700 * with respect to an attribute use its *normalized*
24701 * value· must match the *canonical* lexical
24702 * representation of the attribute use's {value
24703 * constraint}value, if it is present and fixed."
24704 *
24705 * VAL TODO: The requirement for the *canonical* value
24706 * will be removed in XML Schema 1.1.
24707 */
24708 /*
24709 * SPEC Attribute Locally Valid (cvc-attribute)
24710 * (4) "The item's *actual* value· must match the *value* of
24711 * the {value constraint}, if it is present and fixed."
24712 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024713 ws = xmlSchemaGetWhiteSpaceFacetValue(iattr->typeDef);
24714 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024715 /* VAL TODO: A value was not precomputed. */
24716 TODO
24717 goto eval_idcs;
24718 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024719 if ((iattr->use != NULL) &&
24720 (iattr->use->defValue != NULL)) {
24721 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024722 /* VAL TODO: A default value was not precomputed. */
24723 TODO
24724 goto eval_idcs;
24725 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024726 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024727 /*
24728 if (xmlSchemaCompareValuesWhtsp(attr->val,
24729 (xmlSchemaWhitespaceValueType) ws,
24730 attr->use->defVal,
24731 (xmlSchemaWhitespaceValueType) ws) != 0) {
24732 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024733 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
24734 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024735 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024736 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024737 /* VAL TODO: A default value was not precomputed. */
24738 TODO
24739 goto eval_idcs;
24740 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024741 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024742 /*
24743 if (xmlSchemaCompareValuesWhtsp(attr->val,
24744 (xmlSchemaWhitespaceValueType) ws,
24745 attrDecl->defVal,
24746 (xmlSchemaWhitespaceValueType) ws) != 0) {
24747 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024748 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
24749 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024750 }
24751 /*
24752 * [validity] = "valid"
24753 */
24754 }
24755eval_idcs:
24756 /*
24757 * Evaluate IDCs.
24758 */
24759 if (xpathRes) {
24760 if (xmlSchemaXPathProcessHistory(vctxt,
24761 vctxt->depth +1) == -1) {
24762 VERROR_INT("xmlSchemaVAttributesComplex",
24763 "calling xmlSchemaXPathEvaluate()");
24764 goto internal_error;
24765 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000024766 } else if (vctxt->xpathStates != NULL)
24767 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024768 }
24769
24770 /*
24771 * Report errors.
24772 */
24773 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024774 iattr = vctxt->attrInfos[i];
24775 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
24776 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
24777 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
24778 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024779 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024780 ACTIVATE_ATTRIBUTE(iattr);
24781 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024782 case XML_SCHEMAS_ATTR_ERR_MISSING: {
24783 xmlChar *str = NULL;
24784 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024785 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024786 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
24787 "The attribute '%s' is required but missing",
24788 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024789 iattr->decl->targetNamespace,
24790 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024791 NULL);
24792 FREE_AND_NULL(str)
24793 break;
24794 }
24795 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
24796 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
24797 "The type definition is absent");
24798 break;
24799 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024800 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024801 XML_SCHEMAV_CVC_AU, NULL, NULL,
24802 "The value '%s' does not match the fixed "
24803 "value constraint '%s'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024804 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 break;
24806 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
24807 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
24808 "No matching global attribute declaration available, but "
24809 "demanded by the strict wildcard");
24810 break;
24811 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024812 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024813 break;
24814 /*
24815 * MAYBE VAL TODO: One might report different error messages
24816 * for the following errors.
24817 */
24818 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024819 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024820 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024821 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024822 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024823 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024824 }
24825 break;
24826 default:
24827 break;
24828 }
24829 }
24830
24831 ACTIVATE_ELEM;
24832 return (0);
24833internal_error:
24834 ACTIVATE_ELEM;
24835 return (-1);
24836}
24837
24838static int
24839xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
24840 int *skip)
24841{
24842 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
24843 /*
24844 * The namespace of the element was already identified to be
24845 * matching the wildcard.
24846 */
24847 if ((skip == NULL) || (wild == NULL) ||
24848 (wild->type != XML_SCHEMA_TYPE_ANY)) {
24849 VERROR_INT("xmlSchemaValidateElemWildcard",
24850 "bad arguments");
24851 return (-1);
24852 }
24853 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024854 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
24855 /*
24856 * URGENT VAL TODO: Either we need to position the stream to the
24857 * next sibling, or walk the whole subtree.
24858 */
24859 *skip = 1;
24860 return (0);
24861 }
24862 {
24863 xmlSchemaElementPtr decl = NULL;
24864
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024865 decl = xmlSchemaGetElem(vctxt->schema,
24866 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024867 if (decl != NULL) {
24868 vctxt->inode->decl = decl;
24869 return (0);
24870 }
24871 }
24872 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
24873 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024874 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024875 "No matching global element declaration available, but "
24876 "demanded by the strict wildcard");
24877 return (vctxt->err);
24878 }
24879 if (vctxt->nbAttrInfos != 0) {
24880 xmlSchemaAttrInfoPtr iattr;
24881 /*
24882 * SPEC Validation Rule: Schema-Validity Assessment (Element)
24883 * (1.2.1.2.1) - (1.2.1.2.3 )
24884 *
24885 * Use the xsi:type attribute for the type definition.
24886 */
24887 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24888 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24889 if (iattr != NULL) {
24890 if (xmlSchemaProcessXSIType(vctxt, iattr,
24891 &(vctxt->inode->typeDef), NULL) == -1) {
24892 VERROR_INT("xmlSchemaValidateElemWildcard",
24893 "calling xmlSchemaProcessXSIType() to "
24894 "process the attribute 'xsi:nil'");
24895 return (-1);
24896 }
24897 /*
24898 * Don't return an error on purpose.
24899 */
24900 return (0);
24901 }
24902 }
24903 /*
24904 * SPEC Validation Rule: Schema-Validity Assessment (Element)
24905 *
24906 * Fallback to "anyType".
24907 */
24908 vctxt->inode->typeDef =
24909 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
24910 return (0);
24911}
24912
24913/*
24914* xmlSchemaCheckCOSValidDefault:
24915*
24916* This will be called if: not nilled, no content and a default/fixed
24917* value is provided.
24918*/
24919
24920static int
24921xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
24922 const xmlChar *value,
24923 xmlSchemaValPtr *val)
24924{
24925 int ret = 0;
24926 xmlSchemaNodeInfoPtr inode = vctxt->inode;
24927
24928 /*
24929 * cos-valid-default:
24930 * Schema Component Constraint: Element Default Valid (Immediate)
24931 * For a string to be a valid default with respect to a type
24932 * definition the appropriate case among the following must be true:
24933 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024934 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024935 /*
24936 * Complex type.
24937 *
24938 * SPEC (2.1) "its {content type} must be a simple type definition
24939 * or mixed."
24940 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
24941 * type}'s particle must be ·emptiable· as defined by
24942 * Particle Emptiable (§3.9.6)."
24943 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024944 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
24945 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
24946 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024947 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
24948 /* NOTE that this covers (2.2.2) as well. */
24949 VERROR(ret, NULL,
24950 "For a string to be a valid default, the type definition "
24951 "must be a simple type or a complex type with simple content "
24952 "or mixed content and a particle emptiable");
24953 return(ret);
24954 }
24955 }
24956 /*
24957 * 1 If the type definition is a simple type definition, then the string
24958 * must be ·valid· with respect to that definition as defined by String
24959 * Valid (§3.14.4).
24960 *
24961 * AND
24962 *
24963 * 2.2.1 If the {content type} is a simple type definition, then the
24964 * string must be ·valid· with respect to that simple type definition
24965 * as defined by String Valid (§3.14.4).
24966 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024967 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024968
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024969 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024970 NULL, inode->typeDef, value, val, 1, 1, 0);
24971
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024972 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024973
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024974 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024975 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
24976 }
24977 if (ret < 0) {
24978 VERROR_INT("xmlSchemaCheckCOSValidDefault",
24979 "calling xmlSchemaVCheckCVCSimpleType()");
24980 }
24981 return (ret);
24982}
24983
24984static void
24985xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
24986 const xmlChar * name ATTRIBUTE_UNUSED,
24987 xmlSchemaElementPtr item,
24988 xmlSchemaNodeInfoPtr inode)
24989{
24990 inode->decl = item;
24991#ifdef DEBUG_CONTENT
24992 {
24993 xmlChar *str = NULL;
24994
24995 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
24996 xmlGenericError(xmlGenericErrorContext,
24997 "AUTOMATON callback for '%s' [declaration]\n",
24998 xmlSchemaFormatQName(&str,
24999 inode->localName, inode->nsName));
25000 } else {
25001 xmlGenericError(xmlGenericErrorContext,
25002 "AUTOMATON callback for '%s' [wildcard]\n",
25003 xmlSchemaFormatQName(&str,
25004 inode->localName, inode->nsName));
25005
25006 }
25007 FREE_AND_NULL(str)
25008 }
25009#endif
25010}
25011
25012static int
25013xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025014{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025015 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25016 if (vctxt->inode == NULL) {
25017 VERROR_INT("xmlSchemaValidatorPushElem",
25018 "calling xmlSchemaGetFreshElemInfo()");
25019 return (-1);
25020 }
25021 vctxt->nbAttrInfos = 0;
25022 return (0);
25023}
25024
25025static int
25026xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25027 xmlSchemaNodeInfoPtr inode,
25028 xmlSchemaTypePtr type,
25029 const xmlChar *value)
25030{
25031 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25032 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025033 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025034 type, value, &(inode->val), 1, 1, 0));
25035 else
25036 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025037 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025038 type, value, NULL, 1, 0, 0));
25039}
25040
25041
25042
25043/*
25044* Process END of element.
25045*/
25046static int
25047xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25048{
25049 int ret = 0;
25050 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25051
25052 if (vctxt->nbAttrInfos != 0)
25053 xmlSchemaClearAttrInfos(vctxt);
25054 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25055 /*
25056 * This element was not expected;
25057 * we will not validate child elements of broken parents.
25058 * Skip validation of all content of the parent.
25059 */
25060 vctxt->skipDepth = vctxt->depth -1;
25061 goto end_elem;
25062 }
25063 if ((inode->typeDef == NULL) ||
25064 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25065 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025066 * 1. the type definition might be missing if the element was
25067 * error prone
25068 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025069 */
25070 goto end_elem;
25071 }
25072 /*
25073 * Check the content model.
25074 */
25075 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25076 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25077
25078 /*
25079 * Workaround for "anyType".
25080 */
25081 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25082 goto character_content;
25083
25084 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25085 xmlChar *values[10];
25086 int terminal, nbval = 10, nbneg;
25087
25088 if (inode->regexCtxt == NULL) {
25089 /*
25090 * Create the regex context.
25091 */
25092 inode->regexCtxt =
25093 xmlRegNewExecCtxt(inode->typeDef->contModel,
25094 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25095 vctxt);
25096 if (inode->regexCtxt == NULL) {
25097 VERROR_INT("xmlSchemaValidatorPopElem",
25098 "failed to create a regex context");
25099 goto internal_error;
25100 }
25101#ifdef DEBUG_AUTOMATA
25102 xmlGenericError(xmlGenericErrorContext,
25103 "AUTOMATON create on '%s'\n", inode->localName);
25104#endif
25105 }
25106 /*
25107 * Get hold of the still expected content, since a further
25108 * call to xmlRegExecPushString() will loose this information.
25109 */
25110 xmlRegExecNextValues(inode->regexCtxt,
25111 &nbval, &nbneg, &values[0], &terminal);
25112 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25113 if (ret <= 0) {
25114 /*
25115 * Still missing something.
25116 */
25117 ret = 1;
25118 inode->flags |=
25119 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025120 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025121 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25122 "Missing child element(s)",
25123 nbval, nbneg, values);
25124#ifdef DEBUG_AUTOMATA
25125 xmlGenericError(xmlGenericErrorContext,
25126 "AUTOMATON missing ERROR on '%s'\n",
25127 inode->localName);
25128#endif
25129 } else {
25130 /*
25131 * Content model is satisfied.
25132 */
25133 ret = 0;
25134#ifdef DEBUG_AUTOMATA
25135 xmlGenericError(xmlGenericErrorContext,
25136 "AUTOMATON succeeded on '%s'\n",
25137 inode->localName);
25138#endif
25139 }
25140
25141 }
25142 }
25143 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25144 goto end_elem;
25145
25146character_content:
25147
25148 if (vctxt->value != NULL) {
25149 xmlSchemaFreeValue(vctxt->value);
25150 vctxt->value = NULL;
25151 }
25152 /*
25153 * Check character content.
25154 */
25155 if (inode->decl == NULL) {
25156 /*
25157 * Speedup if no declaration exists.
25158 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025159 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025160 ret = xmlSchemaVCheckINodeDataType(vctxt,
25161 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025162 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025163 ret = xmlSchemaVCheckINodeDataType(vctxt,
25164 inode, inode->typeDef->contentTypeDef,
25165 inode->value);
25166 }
25167 if (ret < 0) {
25168 VERROR_INT("xmlSchemaValidatorPopElem",
25169 "calling xmlSchemaVCheckCVCSimpleType()");
25170 goto internal_error;
25171 }
25172 goto end_elem;
25173 }
25174 /*
25175 * cvc-elt (3.3.4) : 5
25176 * The appropriate case among the following must be true:
25177 */
25178 /*
25179 * cvc-elt (3.3.4) : 5.1
25180 * If the declaration has a {value constraint},
25181 * the item has neither element nor character [children] and
25182 * clause 3.2 has not applied, then all of the following must be true:
25183 */
25184 if ((inode->decl->value != NULL) &&
25185 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25186 (! INODE_NILLED(inode))) {
25187 /*
25188 * cvc-elt (3.3.4) : 5.1.1
25189 * If the ·actual type definition· is a ·local type definition·
25190 * then the canonical lexical representation of the {value constraint}
25191 * value must be a valid default for the ·actual type definition· as
25192 * defined in Element Default Valid (Immediate) (§3.3.6).
25193 */
25194 /*
25195 * NOTE: 'local' above means types aquired by xsi:type.
25196 * NOTE: Although the *canonical* value is stated, it is not
25197 * relevant if canonical or not. Additionally XML Schema 1.1
25198 * will removed this requirement as well.
25199 */
25200 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25201
25202 ret = xmlSchemaCheckCOSValidDefault(vctxt,
25203 inode->decl->value, &(inode->val));
25204 if (ret != 0) {
25205 if (ret < 0) {
25206 VERROR_INT("xmlSchemaValidatorPopElem",
25207 "calling xmlSchemaCheckCOSValidDefault()");
25208 goto internal_error;
25209 }
25210 goto end_elem;
25211 }
25212 /*
25213 * Stop here, to avoid redundant validation of the value
25214 * (see following).
25215 */
25216 goto default_psvi;
25217 }
25218 /*
25219 * cvc-elt (3.3.4) : 5.1.2
25220 * The element information item with the canonical lexical
25221 * representation of the {value constraint} value used as its
25222 * ·normalized value· must be ·valid· with respect to the
25223 * ·actual type definition· as defined by Element Locally Valid (Type)
25224 * (§3.3.4).
25225 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025226 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025227 ret = xmlSchemaVCheckINodeDataType(vctxt,
25228 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025229 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025230 ret = xmlSchemaVCheckINodeDataType(vctxt,
25231 inode, inode->typeDef->contentTypeDef,
25232 inode->decl->value);
25233 }
25234 if (ret != 0) {
25235 if (ret < 0) {
25236 VERROR_INT("xmlSchemaValidatorPopElem",
25237 "calling xmlSchemaVCheckCVCSimpleType()");
25238 goto internal_error;
25239 }
25240 goto end_elem;
25241 }
25242
25243default_psvi:
25244 /*
25245 * PSVI: Create a text node on the instance element.
25246 */
25247 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25248 (inode->node != NULL)) {
25249 xmlNodePtr textChild;
25250 xmlChar *normValue;
25251 /*
25252 * VAL TODO: Normalize the value.
25253 */
25254 normValue = xmlSchemaNormalizeValue(inode->typeDef,
25255 inode->decl->value);
25256 if (normValue != NULL) {
25257 textChild = xmlNewText(BAD_CAST normValue);
25258 xmlFree(normValue);
25259 } else
25260 textChild = xmlNewText(inode->decl->value);
25261 if (textChild == NULL) {
25262 VERROR_INT("xmlSchemaValidatorPopElem",
25263 "calling xmlNewText()");
25264 goto internal_error;
25265 } else
25266 xmlAddChild(inode->node, textChild);
25267 }
25268
25269 } else if (! INODE_NILLED(inode)) {
25270 /*
25271 * 5.2.1 The element information item must be ·valid· with respect
25272 * to the ·actual type definition· as defined by Element Locally
25273 * Valid (Type) (§3.3.4).
25274 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025275 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025276 /*
25277 * SPEC (cvc-type) (3.1)
25278 * "If the type definition is a simple type definition, ..."
25279 * (3.1.3) "If clause 3.2 of Element Locally Valid
25280 * (Element) (§3.3.4) did not apply, then the ·normalized value·
25281 * must be ·valid· with respect to the type definition as defined
25282 * by String Valid (§3.14.4).
25283 */
25284 ret = xmlSchemaVCheckINodeDataType(vctxt,
25285 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025286 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025287 /*
25288 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25289 * definition, then the element information item must be
25290 * ·valid· with respect to the type definition as per
25291 * Element Locally Valid (Complex Type) (§3.4.4);"
25292 *
25293 * SPEC (cvc-complex-type) (2.2)
25294 * "If the {content type} is a simple type definition, ...
25295 * the ·normalized value· of the element information item is
25296 * ·valid· with respect to that simple type definition as
25297 * defined by String Valid (§3.14.4)."
25298 */
25299 ret = xmlSchemaVCheckINodeDataType(vctxt,
25300 inode, inode->typeDef->contentTypeDef, inode->value);
25301 }
25302 if (ret != 0) {
25303 if (ret < 0) {
25304 VERROR_INT("xmlSchemaValidatorPopElem",
25305 "calling xmlSchemaVCheckCVCSimpleType()");
25306 goto internal_error;
25307 }
25308 goto end_elem;
25309 }
25310 /*
25311 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25312 * not applied, all of the following must be true:
25313 */
25314 if ((inode->decl->value != NULL) &&
25315 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25316
25317 /*
25318 * TODO: We will need a computed value, when comparison is
25319 * done on computed values.
25320 */
25321 /*
25322 * 5.2.2.1 The element information item must have no element
25323 * information item [children].
25324 */
25325 if (inode->flags &
25326 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25327 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25328 VERROR(ret, NULL,
25329 "The content must not containt element nodes since "
25330 "there is a fixed value constraint");
25331 goto end_elem;
25332 } else {
25333 /*
25334 * 5.2.2.2 The appropriate case among the following must
25335 * be true:
25336 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025337 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025338 /*
25339 * 5.2.2.2.1 If the {content type} of the ·actual type
25340 * definition· is mixed, then the *initial value* of the
25341 * item must match the canonical lexical representation
25342 * of the {value constraint} value.
25343 *
25344 * ... the *initial value* of an element information
25345 * item is the string composed of, in order, the
25346 * [character code] of each character information item in
25347 * the [children] of that element information item.
25348 */
25349 if (! xmlStrEqual(inode->value, inode->decl->value)){
25350 /*
25351 * VAL TODO: Report invalid & expected values as well.
25352 * VAL TODO: Implement the canonical stuff.
25353 */
25354 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025355 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025356 ret, NULL, NULL,
25357 "The initial value '%s' does not match the fixed "
25358 "value constraint '%s'",
25359 inode->value, inode->decl->value);
25360 goto end_elem;
25361 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025362 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025363 /*
25364 * 5.2.2.2.2 If the {content type} of the ·actual type
25365 * definition· is a simple type definition, then the
25366 * *actual value* of the item must match the canonical
25367 * lexical representation of the {value constraint} value.
25368 */
25369 /*
25370 * VAL TODO: *actual value* is the normalized value, impl.
25371 * this.
25372 * VAL TODO: Report invalid & expected values as well.
25373 * VAL TODO: Implement a comparison with the computed values.
25374 */
25375 if (! xmlStrEqual(inode->value,
25376 inode->decl->value)) {
25377 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025378 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025379 ret, NULL, NULL,
25380 "The actual value '%s' does not match the fixed "
25381 "value constraint '%s'",
25382 inode->value,
25383 inode->decl->value);
25384 goto end_elem;
25385 }
25386 }
25387 }
25388 }
25389 }
25390
25391end_elem:
25392 if (vctxt->depth < 0) {
25393 /* TODO: raise error? */
25394 return (0);
25395 }
25396 if (vctxt->depth == vctxt->skipDepth)
25397 vctxt->skipDepth = -1;
25398 /*
25399 * Evaluate the history of XPath state objects.
25400 */
25401 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
25402 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025403 /*
25404 * TODO: 6 The element information item must be ·valid· with respect to each of
25405 * the {identity-constraint definitions} as per Identity-constraint
25406 * Satisfied (§3.11.4).
25407 */
25408 /*
25409 * Validate IDC keyrefs.
25410 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025411 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
25412 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025413 /*
25414 * Merge/free the IDC table.
25415 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025416 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025417#ifdef DEBUG_IDC
25418 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025419 inode->nsName,
25420 inode->localName,
25421 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025422#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025423 if (vctxt->depth > 0) {
25424 /*
25425 * Merge the IDC node table with the table of the parent node.
25426 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025427 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
25428 goto internal_error;
25429 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025430 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025431 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025432 * Clear the current ielem.
25433 * VAL TODO: Don't free the PSVI IDC tables if they are
25434 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025435 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025436 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025437 /*
25438 * Skip further processing if we are on the validation root.
25439 */
25440 if (vctxt->depth == 0) {
25441 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025442 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025443 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025444 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025445 /*
25446 * Reset the bubbleDepth if needed.
25447 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000025448 if (vctxt->aidcs != NULL) {
25449 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
25450 do {
25451 if (aidc->bubbleDepth == vctxt->depth) {
25452 /*
25453 * A bubbleDepth of a key/unique IDC matches the current
25454 * depth, this means that we are leaving the scope of the
25455 * top-most keyref IDC.
25456 */
25457 aidc->bubbleDepth = -1;
25458 }
25459 aidc = aidc->next;
25460 } while (aidc != NULL);
25461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025462 vctxt->depth--;
25463 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000025464 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025465 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025466 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
25467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025468 return (ret);
25469
25470internal_error:
25471 vctxt->err = -1;
25472 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025473}
25474
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025475/*
25476* 3.4.4 Complex Type Definition Validation Rules
25477* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
25478*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000025479static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025480xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000025481{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025482 xmlSchemaNodeInfoPtr pielem;
25483 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000025484 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000025485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025486 if (vctxt->depth <= 0) {
25487 VERROR_INT("xmlSchemaValidateChildElem",
25488 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025489 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025490 }
25491 pielem = vctxt->elemInfos[vctxt->depth -1];
25492 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
25493 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025494 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025495 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025497 if (INODE_NILLED(pielem)) {
25498 /*
25499 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
25500 */
25501 ACTIVATE_PARENT_ELEM;
25502 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
25503 VERROR(ret, NULL,
25504 "Neither character nor element content is allowed, "
25505 "because the element was 'nilled'");
25506 ACTIVATE_ELEM;
25507 goto unexpected_elem;
25508 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025509
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025510 ptype = pielem->typeDef;
25511
25512 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
25513 /*
25514 * Workaround for "anyType": we have currently no content model
25515 * assigned for "anyType", so handle it explicitely.
25516 * "anyType" has an unbounded, lax "any" wildcard.
25517 */
25518 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
25519 vctxt->inode->localName,
25520 vctxt->inode->nsName);
25521
25522 if (vctxt->inode->decl == NULL) {
25523 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000025524 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025525 * Process "xsi:type".
25526 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000025527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025528 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25529 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25530 if (iattr != NULL) {
25531 ret = xmlSchemaProcessXSIType(vctxt, iattr,
25532 &(vctxt->inode->typeDef), NULL);
25533 if (ret != 0) {
25534 if (ret == -1) {
25535 VERROR_INT("xmlSchemaValidateChildElem",
25536 "calling xmlSchemaProcessXSIType() to "
25537 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000025538 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000025539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025540 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000025541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025542 } else {
25543 /*
25544 * Fallback to "anyType".
25545 *
25546 * SPEC (cvc-assess-elt)
25547 * "If the item cannot be ·strictly assessed·, [...]
25548 * an element information item's schema validity may be laxly
25549 * assessed if its ·context-determined declaration· is not
25550 * skip by ·validating· with respect to the ·ur-type
25551 * definition· as per Element Locally Valid (Type) (§3.3.4)."
25552 */
25553 vctxt->inode->typeDef =
25554 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025555 }
25556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025557 return (0);
25558 }
25559
25560 switch (ptype->contentType) {
25561 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025562 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025563 * SPEC (2.1) "If the {content type} is empty, then the
25564 * element information item has no character or element
25565 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025567 ACTIVATE_PARENT_ELEM
25568 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
25569 VERROR(ret, NULL,
25570 "Element content is not allowed, "
25571 "because the content type is empty");
25572 ACTIVATE_ELEM
25573 goto unexpected_elem;
25574 break;
25575
25576 case XML_SCHEMA_CONTENT_MIXED:
25577 case XML_SCHEMA_CONTENT_ELEMENTS: {
25578 xmlRegExecCtxtPtr regexCtxt;
25579 xmlChar *values[10];
25580 int terminal, nbval = 10, nbneg;
25581
25582 /* VAL TODO: Optimized "anyType" validation.*/
25583
25584 if (ptype->contModel == NULL) {
25585 VERROR_INT("xmlSchemaValidateChildElem",
25586 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000025587 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000025588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025589 /*
25590 * Safety belf for evaluation if the cont. model was already
25591 * examined to be invalid.
25592 */
25593 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
25594 VERROR_INT("xmlSchemaValidateChildElem",
25595 "validating elem, but elem content is already invalid");
25596 return (-1);
25597 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000025598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025599 regexCtxt = pielem->regexCtxt;
25600 if (regexCtxt == NULL) {
25601 /*
25602 * Create the regex context.
25603 */
25604 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
25605 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25606 vctxt);
25607 if (regexCtxt == NULL) {
25608 VERROR_INT("xmlSchemaValidateChildElem",
25609 "failed to create a regex context");
25610 return (-1);
25611 }
25612 pielem->regexCtxt = regexCtxt;
25613#ifdef DEBUG_AUTOMATA
25614 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
25615 pielem->localName);
25616#endif
25617 }
25618
25619 /*
25620 * SPEC (2.4) "If the {content type} is element-only or mixed,
25621 * then the sequence of the element information item's
25622 * element information item [children], if any, taken in
25623 * order, is ·valid· with respect to the {content type}'s
25624 * particle, as defined in Element Sequence Locally Valid
25625 * (Particle) (§3.9.4)."
25626 */
25627 ret = xmlRegExecPushString2(regexCtxt,
25628 vctxt->inode->localName,
25629 vctxt->inode->nsName,
25630 vctxt->inode);
25631#ifdef DEBUG_AUTOMATA
25632 if (ret < 0)
25633 xmlGenericError(xmlGenericErrorContext,
25634 "AUTOMATON push ERROR for '%s' on '%s'\n",
25635 vctxt->inode->localName, pielem->localName);
25636 else
25637 xmlGenericError(xmlGenericErrorContext,
25638 "AUTOMATON push OK for '%s' on '%s'\n",
25639 vctxt->inode->localName, pielem->localName);
25640#endif
25641 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
25642 VERROR_INT("xmlSchemaValidateChildElem",
25643 "calling xmlRegExecPushString2()");
25644 return (-1);
25645 }
25646 if (ret < 0) {
25647 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
25648 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025649 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025650 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
25651 "This element is not expected",
25652 nbval, nbneg, values);
25653 ret = vctxt->err;
25654 goto unexpected_elem;
25655 } else
25656 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000025657 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025658 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025659 case XML_SCHEMA_CONTENT_SIMPLE:
25660 case XML_SCHEMA_CONTENT_BASIC:
25661 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025662 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025663 /*
25664 * SPEC (cvc-complex-type) (2.2)
25665 * "If the {content type} is a simple type definition, then
25666 * the element information item has no element information
25667 * item [children], ..."
25668 */
25669 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
25670 VERROR(ret, NULL, "Element content is not allowed, "
25671 "because the content type is a simple type definition");
25672 } else {
25673 /*
25674 * SPEC (cvc-type) (3.1.2) "The element information item must
25675 * have no element information item [children]."
25676 */
25677 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
25678 VERROR(ret, NULL, "Element content is not allowed, "
25679 "because the type definition is simple");
25680 }
25681 ACTIVATE_ELEM
25682 ret = vctxt->err;
25683 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025684 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025685
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025686 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025687 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025688 }
25689 return (ret);
25690unexpected_elem:
25691 /*
25692 * Pop this element and set the skipDepth to skip
25693 * all further content of the parent element.
25694 */
25695 vctxt->skipDepth = vctxt->depth;
25696 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
25697 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
25698 return (ret);
25699}
25700
25701#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
25702#define XML_SCHEMA_PUSH_TEXT_CREATED 2
25703#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
25704
25705static int
25706xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
25707 int nodeType, const xmlChar *value, int len,
25708 int mode, int *consumed)
25709{
25710 /*
25711 * Unfortunately we have to duplicate the text sometimes.
25712 * OPTIMIZE: Maybe we could skip it, if:
25713 * 1. content type is simple
25714 * 2. whitespace is "collapse"
25715 * 3. it consists of whitespace only
25716 *
25717 * Process character content.
25718 */
25719 if (consumed != NULL)
25720 *consumed = 0;
25721 if (INODE_NILLED(vctxt->inode)) {
25722 /*
25723 * SPEC cvc-elt (3.3.4 - 3.2.1)
25724 * "The element information item must have no character or
25725 * element information item [children]."
25726 */
25727 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
25728 "Neither character nor element content is allowed "
25729 "because the element is 'nilled'");
25730 return (vctxt->err);
25731 }
25732 /*
25733 * SPEC (2.1) "If the {content type} is empty, then the
25734 * element information item has no character or element
25735 * information item [children]."
25736 */
25737 if (vctxt->inode->typeDef->contentType ==
25738 XML_SCHEMA_CONTENT_EMPTY) {
25739 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
25740 "Character content is not allowed, "
25741 "because the content type is empty");
25742 return (vctxt->err);
25743 }
25744
25745 if (vctxt->inode->typeDef->contentType ==
25746 XML_SCHEMA_CONTENT_ELEMENTS) {
25747 if ((nodeType != XML_TEXT_NODE) ||
25748 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
25749 /*
25750 * SPEC cvc-complex-type (2.3)
25751 * "If the {content type} is element-only, then the
25752 * element information item has no character information
25753 * item [children] other than those whose [character
25754 * code] is defined as a white space in [XML 1.0 (Second
25755 * Edition)]."
25756 */
25757 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
25758 "Character content other than whitespace is not allowed "
25759 "because the content type is 'element-only'");
25760 return (vctxt->err);
25761 }
25762 return (0);
25763 }
25764
25765 if ((value == NULL) || (value[0] == 0))
25766 return (0);
25767 /*
25768 * Save the value.
25769 * NOTE that even if the content type is *mixed*, we need the
25770 * *initial value* for default/fixed value constraints.
25771 */
25772 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
25773 ((vctxt->inode->decl == NULL) ||
25774 (vctxt->inode->decl->value == NULL)))
25775 return (0);
25776
25777 if (vctxt->inode->value == NULL) {
25778 /*
25779 * Set the value.
25780 */
25781 switch (mode) {
25782 case XML_SCHEMA_PUSH_TEXT_PERSIST:
25783 /*
25784 * When working on a tree.
25785 */
25786 vctxt->inode->value = value;
25787 break;
25788 case XML_SCHEMA_PUSH_TEXT_CREATED:
25789 /*
25790 * When working with the reader.
25791 * The value will be freed by the element info.
25792 */
25793 vctxt->inode->value = value;
25794 if (consumed != NULL)
25795 *consumed = 1;
25796 vctxt->inode->flags |=
25797 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
25798 break;
25799 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
25800 /*
25801 * When working with SAX.
25802 * The value will be freed by the element info.
25803 */
25804 if (len != -1)
25805 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
25806 else
25807 vctxt->inode->value = BAD_CAST xmlStrdup(value);
25808 vctxt->inode->flags |=
25809 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
25810 break;
25811 default:
25812 break;
25813 }
25814 } else {
25815 /*
25816 * Concat the value.
25817 */
25818 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000025819 vctxt->inode->value = BAD_CAST xmlStrncat(
25820 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025821 } else {
25822 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025823 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025824 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
25825 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025826 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025827
25828 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000025829}
25830
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025831static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025832xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000025833{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025834 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000025835
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025836 if ((vctxt->skipDepth != -1) &&
25837 (vctxt->depth >= vctxt->skipDepth)) {
25838 VERROR_INT("xmlSchemaValidateElem",
25839 "in skip-state");
25840 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025841 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025842 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025843 /*
25844 * URGENT TODO: Better to fully stop validation
25845 * if there was an error during dynamic schema construction.
25846 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025847 if (xmlSchemaAssembleByXSI(vctxt) == -1)
25848 goto internal_error;
25849 }
25850 if (vctxt->depth > 0) {
25851 /*
25852 * Validate this element against the content model
25853 * of the parent.
25854 */
25855 ret = xmlSchemaValidateChildElem(vctxt);
25856 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025857 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025858 VERROR_INT("xmlSchemaValidateElem",
25859 "calling xmlSchemaStreamValidateChildElement()");
25860 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025862 goto exit;
25863 }
25864 if (vctxt->depth == vctxt->skipDepth)
25865 goto exit;
25866 if ((vctxt->inode->decl == NULL) &&
25867 (vctxt->inode->typeDef == NULL)) {
25868 VERROR_INT("xmlSchemaValidateElem",
25869 "the child element was valid but neither the "
25870 "declaration nor the type was set");
25871 goto internal_error;
25872 }
25873 } else {
25874 /*
25875 * Get the declaration of the validation root.
25876 */
25877 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
25878 vctxt->inode->localName,
25879 vctxt->inode->nsName);
25880 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000025881 ret = XML_SCHEMAV_CVC_ELT_1;
25882 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025883 "No matching global declaration available "
25884 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025885 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025886 }
25887 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000025888
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025889 if (vctxt->inode->decl == NULL)
25890 goto type_validation;
25891
25892 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
25893 int skip;
25894 /*
25895 * Wildcards.
25896 */
25897 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
25898 if (ret != 0) {
25899 if (ret < 0) {
25900 VERROR_INT("xmlSchemaValidateElem",
25901 "calling xmlSchemaValidateElemWildcard()");
25902 goto internal_error;
25903 }
25904 goto exit;
25905 }
25906 if (skip) {
25907 vctxt->skipDepth = vctxt->depth;
25908 goto exit;
25909 }
25910 /*
25911 * The declaration might be set by the wildcard validation,
25912 * when the processContents is "lax" or "strict".
25913 */
25914 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
25915 /*
25916 * Clear the "decl" field to not confuse further processing.
25917 */
25918 vctxt->inode->decl = NULL;
25919 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000025920 }
Daniel Veillard4255d502002-04-16 15:50:10 +000025921 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025922 /*
25923 * Validate against the declaration.
25924 */
25925 ret = xmlSchemaValidateElemDecl(vctxt);
25926 if (ret != 0) {
25927 if (ret < 0) {
25928 VERROR_INT("xmlSchemaValidateElem",
25929 "calling xmlSchemaValidateElemDecl()");
25930 goto internal_error;
25931 }
25932 goto exit;
25933 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000025934 /*
25935 * Validate against the type definition.
25936 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025937type_validation:
25938
25939 if (vctxt->inode->typeDef == NULL) {
25940 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
25941 ret = XML_SCHEMAV_CVC_TYPE_1;
25942 VERROR(ret, NULL,
25943 "The type definition is absent");
25944 goto exit;
25945 }
25946 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
25947 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
25948 ret = XML_SCHEMAV_CVC_TYPE_2;
25949 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000025950 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025951 goto exit;
25952 }
25953 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000025954 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025955 * during validation against the declaration. This must be done
25956 * _before_ attribute validation.
25957 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025958 if (vctxt->xpathStates != NULL) {
25959 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
25960 if (ret == -1) {
25961 VERROR_INT("xmlSchemaValidateElem",
25962 "calling xmlSchemaXPathEvaluate()");
25963 goto internal_error;
25964 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025965 }
25966 /*
25967 * Validate attributes.
25968 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025969 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025970 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025971 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025972
25973 ret = xmlSchemaVAttributesComplex(vctxt);
25974 }
25975 } else if (vctxt->nbAttrInfos != 0) {
25976
25977 ret = xmlSchemaVAttributesSimple(vctxt);
25978 }
25979 /*
25980 * Clear registered attributes.
25981 */
25982 if (vctxt->nbAttrInfos != 0)
25983 xmlSchemaClearAttrInfos(vctxt);
25984 if (ret == -1) {
25985 VERROR_INT("xmlSchemaValidateElem",
25986 "calling attributes validation");
25987 goto internal_error;
25988 }
25989 /*
25990 * Don't return an error if attributes are invalid on purpose.
25991 */
25992 ret = 0;
25993
25994exit:
25995 if (ret != 0)
25996 vctxt->skipDepth = vctxt->depth;
25997 return (ret);
25998internal_error:
25999 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026000}
26001
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026002#ifdef XML_SCHEMA_READER_ENABLED
26003static int
26004xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026005{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026006 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26007 int depth, nodeType, ret = 0, consumed;
26008 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000026009
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026010 vctxt->depth = -1;
26011 ret = xmlTextReaderRead(vctxt->reader);
26012 /*
26013 * Move to the document element.
26014 */
26015 while (ret == 1) {
26016 nodeType = xmlTextReaderNodeType(vctxt->reader);
26017 if (nodeType == XML_ELEMENT_NODE)
26018 goto root_found;
26019 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026021 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026022
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026023root_found:
26024
26025 do {
26026 depth = xmlTextReaderDepth(vctxt->reader);
26027 nodeType = xmlTextReaderNodeType(vctxt->reader);
26028
26029 if (nodeType == XML_ELEMENT_NODE) {
26030
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026031 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026032 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26033 VERROR_INT("xmlSchemaVReaderWalk",
26034 "calling xmlSchemaValidatorPushElem()");
26035 goto internal_error;
26036 }
26037 ielem = vctxt->inode;
26038 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26039 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26040 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26041 /*
26042 * Is the element empty?
26043 */
26044 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26045 if (ret == -1) {
26046 VERROR_INT("xmlSchemaVReaderWalk",
26047 "calling xmlTextReaderIsEmptyElement()");
26048 goto internal_error;
26049 }
26050 if (ret) {
26051 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26052 }
26053 /*
26054 * Register attributes.
26055 */
26056 vctxt->nbAttrInfos = 0;
26057 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26058 if (ret == -1) {
26059 VERROR_INT("xmlSchemaVReaderWalk",
26060 "calling xmlTextReaderMoveToFirstAttribute()");
26061 goto internal_error;
26062 }
26063 if (ret == 1) {
26064 do {
26065 /*
26066 * VAL TODO: How do we know that the reader works on a
26067 * node tree, to be able to pass a node here?
26068 */
26069 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26070 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26071 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26072 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26073
26074 VERROR_INT("xmlSchemaVReaderWalk",
26075 "calling xmlSchemaValidatorPushAttribute()");
26076 goto internal_error;
26077 }
26078 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26079 if (ret == -1) {
26080 VERROR_INT("xmlSchemaVReaderWalk",
26081 "calling xmlTextReaderMoveToFirstAttribute()");
26082 goto internal_error;
26083 }
26084 } while (ret == 1);
26085 /*
26086 * Back to element position.
26087 */
26088 ret = xmlTextReaderMoveToElement(vctxt->reader);
26089 if (ret == -1) {
26090 VERROR_INT("xmlSchemaVReaderWalk",
26091 "calling xmlTextReaderMoveToElement()");
26092 goto internal_error;
26093 }
26094 }
26095 /*
26096 * Validate the element.
26097 */
26098 ret= xmlSchemaValidateElem(vctxt);
26099 if (ret != 0) {
26100 if (ret == -1) {
26101 VERROR_INT("xmlSchemaVReaderWalk",
26102 "calling xmlSchemaValidateElem()");
26103 goto internal_error;
26104 }
26105 goto exit;
26106 }
26107 if (vctxt->depth == vctxt->skipDepth) {
26108 int curDepth;
26109 /*
26110 * Skip all content.
26111 */
26112 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26113 ret = xmlTextReaderRead(vctxt->reader);
26114 curDepth = xmlTextReaderDepth(vctxt->reader);
26115 while ((ret == 1) && (curDepth != depth)) {
26116 ret = xmlTextReaderRead(vctxt->reader);
26117 curDepth = xmlTextReaderDepth(vctxt->reader);
26118 }
26119 if (ret < 0) {
26120 /*
26121 * VAL TODO: A reader error occured; what to do here?
26122 */
26123 ret = 1;
26124 goto exit;
26125 }
26126 }
26127 goto leave_elem;
26128 }
26129 /*
26130 * READER VAL TODO: Is an END_ELEM really never called
26131 * if the elem is empty?
26132 */
26133 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26134 goto leave_elem;
26135 } else if (nodeType == END_ELEM) {
26136 /*
26137 * Process END of element.
26138 */
26139leave_elem:
26140 ret = xmlSchemaValidatorPopElem(vctxt);
26141 if (ret != 0) {
26142 if (ret < 0) {
26143 VERROR_INT("xmlSchemaVReaderWalk",
26144 "calling xmlSchemaValidatorPopElem()");
26145 goto internal_error;
26146 }
26147 goto exit;
26148 }
26149 if (vctxt->depth >= 0)
26150 ielem = vctxt->inode;
26151 else
26152 ielem = NULL;
26153 } else if ((nodeType == XML_TEXT_NODE) ||
26154 (nodeType == XML_CDATA_SECTION_NODE) ||
26155 (nodeType == WHTSP) ||
26156 (nodeType == SIGN_WHTSP)) {
26157 /*
26158 * Process character content.
26159 */
26160 xmlChar *value;
26161
26162 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26163 nodeType = XML_TEXT_NODE;
26164
26165 value = xmlTextReaderValue(vctxt->reader);
26166 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26167 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26168 if (! consumed)
26169 xmlFree(value);
26170 if (ret == -1) {
26171 VERROR_INT("xmlSchemaVReaderWalk",
26172 "calling xmlSchemaVPushText()");
26173 goto internal_error;
26174 }
26175 } else if ((nodeType == XML_ENTITY_NODE) ||
26176 (nodeType == XML_ENTITY_REF_NODE)) {
26177 /*
26178 * VAL TODO: What to do with entities?
26179 */
26180 TODO
26181 }
26182 /*
26183 * Read next node.
26184 */
26185 ret = xmlTextReaderRead(vctxt->reader);
26186 } while (ret == 1);
26187
26188exit:
26189 return (ret);
26190internal_error:
26191 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026192}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026193#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000026194
26195/************************************************************************
26196 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026197 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000026198 * *
26199 ************************************************************************/
26200
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026201/*
26202* Process text content.
26203*/
26204static void
26205xmlSchemaSAXHandleText(void *ctx,
26206 const xmlChar * ch,
26207 int len)
26208{
26209 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26210
26211 if (vctxt->depth < 0)
26212 return;
26213 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26214 return;
26215 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26216 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26217 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26218 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26219 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26220 "calling xmlSchemaVPushText()");
26221 vctxt->err = -1;
26222 xmlStopParser(vctxt->parserCtxt);
26223 }
26224}
26225
26226/*
26227* Process CDATA content.
26228*/
26229static void
26230xmlSchemaSAXHandleCDataSection(void *ctx,
26231 const xmlChar * ch,
26232 int len)
26233{
26234 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26235
26236 if (vctxt->depth < 0)
26237 return;
26238 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26239 return;
26240 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26241 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26242 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26243 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26244 VERROR_INT("xmlSchemaSAXHandleCDataSection",
26245 "calling xmlSchemaVPushText()");
26246 vctxt->err = -1;
26247 xmlStopParser(vctxt->parserCtxt);
26248 }
26249}
26250
26251static void
26252xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26253 const xmlChar * name ATTRIBUTE_UNUSED)
26254{
26255 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26256
26257 if (vctxt->depth < 0)
26258 return;
26259 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26260 return;
26261 /* SAX VAL TODO: What to do here? */
26262 TODO
26263}
26264
26265static void
26266xmlSchemaSAXHandleStartElementNs(void *ctx,
26267 const xmlChar * localname,
26268 const xmlChar * prefix ATTRIBUTE_UNUSED,
26269 const xmlChar * URI,
26270 int nb_namespaces,
26271 const xmlChar ** namespaces,
26272 int nb_attributes,
26273 int nb_defaulted ATTRIBUTE_UNUSED,
26274 const xmlChar ** attributes)
26275{
26276 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26277 int ret;
26278 xmlSchemaNodeInfoPtr ielem;
26279 int i, j;
26280
26281 /*
26282 * SAX VAL TODO: What to do with nb_defaulted?
26283 */
26284 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026285 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026286 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026287 vctxt->depth++;
26288 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026289 return;
26290 /*
26291 * Push the element.
26292 */
26293 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26294 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26295 "calling xmlSchemaValidatorPushElem()");
26296 goto internal_error;
26297 }
26298 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026299 /*
26300 * TODO: Is this OK?
26301 */
26302 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026303 ielem->localName = localname;
26304 ielem->nsName = URI;
26305 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26306 /*
26307 * Register namespaces on the elem info.
26308 */
26309 if (nb_namespaces != 0) {
26310 /*
26311 * Although the parser builds its own namespace list,
26312 * we have no access to it, so we'll use an own one.
26313 */
26314 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26315 /*
26316 * Store prefix and namespace name.
26317 */
26318 if (ielem->nsBindings == NULL) {
26319 ielem->nsBindings =
26320 (const xmlChar **) xmlMalloc(10 *
26321 sizeof(const xmlChar *));
26322 if (ielem->nsBindings == NULL) {
26323 xmlSchemaVErrMemory(vctxt,
26324 "allocating namespace bindings for SAX validation",
26325 NULL);
26326 goto internal_error;
26327 }
26328 ielem->nbNsBindings = 0;
26329 ielem->sizeNsBindings = 5;
26330 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26331 ielem->sizeNsBindings *= 2;
26332 ielem->nsBindings =
26333 (const xmlChar **) xmlRealloc(
26334 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026335 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026336 if (ielem->nsBindings == NULL) {
26337 xmlSchemaVErrMemory(vctxt,
26338 "re-allocating namespace bindings for SAX validation",
26339 NULL);
26340 goto internal_error;
26341 }
26342 }
26343
26344 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26345 if (namespaces[j+1][0] == 0) {
26346 /*
26347 * Handle xmlns="".
26348 */
26349 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26350 } else
26351 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26352 namespaces[j+1];
26353 ielem->nbNsBindings++;
26354 }
26355 }
26356 /*
26357 * Register attributes.
26358 * SAX VAL TODO: We are not adding namespace declaration
26359 * attributes yet.
26360 */
26361 if (nb_attributes != 0) {
26362 xmlChar *value;
26363
26364 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
26365 /*
26366 * Duplicate the value.
26367 */
26368 value = xmlStrndup(attributes[j+3],
26369 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026370 /*
26371 * TODO: Set the node line.
26372 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026373 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026374 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026375 value, 1);
26376 if (ret == -1) {
26377 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26378 "calling xmlSchemaValidatorPushAttribute()");
26379 goto internal_error;
26380 }
26381 }
26382 }
26383 /*
26384 * Validate the element.
26385 */
26386 ret = xmlSchemaValidateElem(vctxt);
26387 if (ret != 0) {
26388 if (ret == -1) {
26389 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26390 "calling xmlSchemaValidateElem()");
26391 goto internal_error;
26392 }
26393 goto exit;
26394 }
26395
26396exit:
26397 return;
26398internal_error:
26399 vctxt->err = -1;
26400 xmlStopParser(vctxt->parserCtxt);
26401 return;
26402}
26403
26404static void
26405xmlSchemaSAXHandleEndElementNs(void *ctx,
26406 const xmlChar * localname ATTRIBUTE_UNUSED,
26407 const xmlChar * prefix ATTRIBUTE_UNUSED,
26408 const xmlChar * URI ATTRIBUTE_UNUSED)
26409{
26410 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26411 int res;
26412
26413 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026414 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026415 */
26416 if (vctxt->skipDepth != -1) {
26417 if (vctxt->depth > vctxt->skipDepth) {
26418 vctxt->depth--;
26419 return;
26420 } else
26421 vctxt->skipDepth = -1;
26422 }
26423 /*
26424 * SAX VAL TODO: Just a temporary check.
26425 */
26426 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
26427 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
26428 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26429 "elem pop mismatch");
26430 }
26431 res = xmlSchemaValidatorPopElem(vctxt);
26432 if (res != 0) {
26433 if (res < 0) {
26434 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
26435 "calling xmlSchemaValidatorPopElem()");
26436 goto internal_error;
26437 }
26438 goto exit;
26439 }
26440exit:
26441 return;
26442internal_error:
26443 vctxt->err = -1;
26444 xmlStopParser(vctxt->parserCtxt);
26445 return;
26446}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026447
Daniel Veillard4255d502002-04-16 15:50:10 +000026448/************************************************************************
26449 * *
26450 * Validation interfaces *
26451 * *
26452 ************************************************************************/
26453
26454/**
26455 * xmlSchemaNewValidCtxt:
26456 * @schema: a precompiled XML Schemas
26457 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026458 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000026459 *
26460 * Returns the validation context or NULL in case of error
26461 */
26462xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026463xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
26464{
Daniel Veillard4255d502002-04-16 15:50:10 +000026465 xmlSchemaValidCtxtPtr ret;
26466
26467 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
26468 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026469 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000026470 return (NULL);
26471 }
26472 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026473 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026474 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000026475 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026476 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000026477 return (ret);
26478}
26479
26480/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026481 * xmlSchemaClearValidCtxt:
26482 * @ctxt: the schema validation context
26483 *
26484 * Free the resources associated to the schema validation context;
26485 * leaves some fields alive intended for reuse of the context.
26486 */
26487static void
26488xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
26489{
26490 if (vctxt == NULL)
26491 return;
26492
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026493 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026494 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026495 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000026496#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026497 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000026498#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026499 if (vctxt->value != NULL) {
26500 xmlSchemaFreeValue(vctxt->value);
26501 vctxt->value = NULL;
26502 }
26503 /*
26504 * Augmented IDC information.
26505 */
26506 if (vctxt->aidcs != NULL) {
26507 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
26508 do {
26509 next = cur->next;
26510 xmlFree(cur);
26511 cur = next;
26512 } while (cur != NULL);
26513 vctxt->aidcs = NULL;
26514 }
26515 if (vctxt->idcNodes != NULL) {
26516 int i;
26517 xmlSchemaPSVIIDCNodePtr item;
26518
26519 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026520 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026521 xmlFree(item->keys);
26522 xmlFree(item);
26523 }
26524 xmlFree(vctxt->idcNodes);
26525 vctxt->idcNodes = NULL;
26526 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026527 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026528 * Note that we won't delete the XPath state pool here.
26529 */
26530 if (vctxt->xpathStates != NULL) {
26531 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
26532 vctxt->xpathStates = NULL;
26533 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026534 /*
26535 * Attribute info.
26536 */
26537 if (vctxt->nbAttrInfos != 0) {
26538 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026540 /*
26541 * Element info.
26542 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026543 if (vctxt->elemInfos != NULL) {
26544 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026545 xmlSchemaNodeInfoPtr ei;
26546
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026547 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026548 ei = vctxt->elemInfos[i];
26549 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026550 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026551 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026552 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026553 }
26554 xmlSchemaItemListClear(vctxt->nodeQNames);
26555 /* Recreate the dict. */
26556 xmlDictFree(vctxt->dict);
26557 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026558}
26559
26560/**
Daniel Veillard4255d502002-04-16 15:50:10 +000026561 * xmlSchemaFreeValidCtxt:
26562 * @ctxt: the schema validation context
26563 *
26564 * Free the resources associated to the schema validation context
26565 */
26566void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026567xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
26568{
Daniel Veillard4255d502002-04-16 15:50:10 +000026569 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026570 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000026571 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026572 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026573 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026574 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026575 if (ctxt->idcNodes != NULL) {
26576 int i;
26577 xmlSchemaPSVIIDCNodePtr item;
26578
26579 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026580 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026581 xmlFree(item->keys);
26582 xmlFree(item);
26583 }
26584 xmlFree(ctxt->idcNodes);
26585 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026586 if (ctxt->idcKeys != NULL) {
26587 int i;
26588 for (i = 0; i < ctxt->nbIdcKeys; i++)
26589 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
26590 xmlFree(ctxt->idcKeys);
26591 }
26592
26593 if (ctxt->xpathStates != NULL)
26594 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
26595 if (ctxt->xpathStatePool != NULL)
26596 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
26597
26598 /*
26599 * Augmented IDC information.
26600 */
26601 if (ctxt->aidcs != NULL) {
26602 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
26603 do {
26604 next = cur->next;
26605 xmlFree(cur);
26606 cur = next;
26607 } while (cur != NULL);
26608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026609 if (ctxt->attrInfos != NULL) {
26610 int i;
26611 xmlSchemaAttrInfoPtr attr;
26612
26613 /* Just a paranoid call to the cleanup. */
26614 if (ctxt->nbAttrInfos != 0)
26615 xmlSchemaClearAttrInfos(ctxt);
26616 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
26617 attr = ctxt->attrInfos[i];
26618 xmlFree(attr);
26619 }
26620 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026621 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026622 if (ctxt->elemInfos != NULL) {
26623 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026624 xmlSchemaNodeInfoPtr ei;
26625
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026626 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026627 ei = ctxt->elemInfos[i];
26628 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026629 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026630 xmlSchemaClearElemInfo(ei);
26631 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026632 }
26633 xmlFree(ctxt->elemInfos);
26634 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026635 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000026636 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026637 if (ctxt->dict != NULL)
26638 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000026639 xmlFree(ctxt);
26640}
26641
26642/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000026643 * xmlSchemaIsValid:
26644 * @ctxt: the schema validation context
26645 *
26646 * Check if any error was detected during validation.
26647 *
26648 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
26649 * of internal error.
26650 */
26651int
26652xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
26653{
26654 if (ctxt == NULL)
26655 return(-1);
26656 return(ctxt->err == 0);
26657}
26658
26659/**
Daniel Veillard4255d502002-04-16 15:50:10 +000026660 * xmlSchemaSetValidErrors:
26661 * @ctxt: a schema validation context
26662 * @err: the error function
26663 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000026664 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000026665 *
William M. Brack2f2a6632004-08-20 23:09:47 +000026666 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000026667 */
26668void
26669xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026670 xmlSchemaValidityErrorFunc err,
26671 xmlSchemaValidityWarningFunc warn, void *ctx)
26672{
Daniel Veillard4255d502002-04-16 15:50:10 +000026673 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000026674 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000026675 ctxt->error = err;
26676 ctxt->warning = warn;
26677 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026678 if (ctxt->pctxt != NULL)
26679 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000026680}
26681
26682/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000026683 * xmlSchemaSetValidStructuredErrors:
26684 * @ctxt: a schema validation context
26685 * @serror: the structured error function
26686 * @ctx: the functions context
26687 *
26688 * Set the structured error callback
26689 */
26690void
26691xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
26692 xmlStructuredErrorFunc serror, void *ctx)
26693{
26694 if (ctxt == NULL)
26695 return;
26696 ctxt->serror = serror;
26697 ctxt->error = NULL;
26698 ctxt->warning = NULL;
26699 ctxt->userData = ctx;
26700}
26701
26702/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000026703 * xmlSchemaGetValidErrors:
26704 * @ctxt: a XML-Schema validation context
26705 * @err: the error function result
26706 * @warn: the warning function result
26707 * @ctx: the functions context result
26708 *
26709 * Get the error and warning callback informations
26710 *
26711 * Returns -1 in case of error and 0 otherwise
26712 */
26713int
26714xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
26715 xmlSchemaValidityErrorFunc * err,
26716 xmlSchemaValidityWarningFunc * warn, void **ctx)
26717{
26718 if (ctxt == NULL)
26719 return (-1);
26720 if (err != NULL)
26721 *err = ctxt->error;
26722 if (warn != NULL)
26723 *warn = ctxt->warning;
26724 if (ctx != NULL)
26725 *ctx = ctxt->userData;
26726 return (0);
26727}
26728
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026729
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026730/**
Daniel Veillard6927b102004-10-27 17:29:04 +000026731 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026732 * @ctxt: a schema validation context
26733 * @options: a combination of xmlSchemaValidOption
26734 *
26735 * Sets the options to be used during the validation.
26736 *
26737 * Returns 0 in case of success, -1 in case of an
26738 * API error.
26739 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026740int
26741xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
26742 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026743
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026744{
26745 int i;
26746
26747 if (ctxt == NULL)
26748 return (-1);
26749 /*
26750 * WARNING: Change the start value if adding to the
26751 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026752 * TODO: Is there an other, more easy to maintain,
26753 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026754 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026755 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026756 if (options & 1<<i)
26757 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026758 }
26759 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026760 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026761}
26762
26763/**
Daniel Veillard6927b102004-10-27 17:29:04 +000026764 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026765 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026766 *
William M. Brack21e4ef22005-01-02 09:53:13 +000026767 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026768 *
William M. Brack21e4ef22005-01-02 09:53:13 +000026769 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026770 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026771int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026772xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026773
26774{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026775 if (ctxt == NULL)
26776 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026777 else
26778 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026779}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026780
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026781static int
26782xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
26783{
26784 xmlAttrPtr attr;
26785 int ret = 0;
26786 xmlSchemaNodeInfoPtr ielem = NULL;
26787 xmlNodePtr node, valRoot;
26788 const xmlChar *nsName;
26789
26790 /* DOC VAL TODO: Move this to the start function. */
26791 valRoot = xmlDocGetRootElement(vctxt->doc);
26792 if (valRoot == NULL) {
26793 /* VAL TODO: Error code? */
26794 VERROR(1, NULL, "The document has no document element");
26795 return (1);
26796 }
26797 vctxt->depth = -1;
26798 vctxt->validationRoot = valRoot;
26799 node = valRoot;
26800 while (node != NULL) {
26801 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26802 goto next_sibling;
26803 if (node->type == XML_ELEMENT_NODE) {
26804
26805 /*
26806 * Init the node-info.
26807 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026808 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026809 if (xmlSchemaValidatorPushElem(vctxt) == -1)
26810 goto internal_error;
26811 ielem = vctxt->inode;
26812 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026813 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026814 ielem->localName = node->name;
26815 if (node->ns != NULL)
26816 ielem->nsName = node->ns->href;
26817 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26818 /*
26819 * Register attributes.
26820 * DOC VAL TODO: We do not register namespace declaration
26821 * attributes yet.
26822 */
26823 vctxt->nbAttrInfos = 0;
26824 if (node->properties != NULL) {
26825 attr = node->properties;
26826 do {
26827 if (attr->ns != NULL)
26828 nsName = attr->ns->href;
26829 else
26830 nsName = NULL;
26831 ret = xmlSchemaValidatorPushAttribute(vctxt,
26832 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000026833 /*
26834 * Note that we give it the line number of the
26835 * parent element.
26836 */
26837 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026838 attr->name, nsName, 0,
26839 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
26840 if (ret == -1) {
26841 VERROR_INT("xmlSchemaDocWalk",
26842 "calling xmlSchemaValidatorPushAttribute()");
26843 goto internal_error;
26844 }
26845 attr = attr->next;
26846 } while (attr);
26847 }
26848 /*
26849 * Validate the element.
26850 */
26851 ret = xmlSchemaValidateElem(vctxt);
26852 if (ret != 0) {
26853 if (ret == -1) {
26854 VERROR_INT("xmlSchemaDocWalk",
26855 "calling xmlSchemaValidateElem()");
26856 goto internal_error;
26857 }
26858 /*
26859 * Don't stop validation; just skip the content
26860 * of this element.
26861 */
26862 goto leave_node;
26863 }
26864 if ((vctxt->skipDepth != -1) &&
26865 (vctxt->depth >= vctxt->skipDepth))
26866 goto leave_node;
26867 } else if ((node->type == XML_TEXT_NODE) ||
26868 (node->type == XML_CDATA_SECTION_NODE)) {
26869 /*
26870 * Process character content.
26871 */
26872 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26873 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26874 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
26875 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
26876 if (ret < 0) {
26877 VERROR_INT("xmlSchemaVDocWalk",
26878 "calling xmlSchemaVPushText()");
26879 goto internal_error;
26880 }
26881 /*
26882 * DOC VAL TODO: Should we skip further validation of the
26883 * element content here?
26884 */
26885 } else if ((node->type == XML_ENTITY_NODE) ||
26886 (node->type == XML_ENTITY_REF_NODE)) {
26887 /*
26888 * DOC VAL TODO: What to do with entities?
26889 */
26890 TODO
26891 } else {
26892 goto leave_node;
26893 /*
26894 * DOC VAL TODO: XInclude nodes, etc.
26895 */
26896 }
26897 /*
26898 * Walk the doc.
26899 */
26900 if (node->children != NULL) {
26901 node = node->children;
26902 continue;
26903 }
26904leave_node:
26905 if (node->type == XML_ELEMENT_NODE) {
26906 /*
26907 * Leaving the scope of an element.
26908 */
26909 if (node != vctxt->inode->node) {
26910 VERROR_INT("xmlSchemaVDocWalk",
26911 "element position mismatch");
26912 goto internal_error;
26913 }
26914 ret = xmlSchemaValidatorPopElem(vctxt);
26915 if (ret != 0) {
26916 if (ret < 0) {
26917 VERROR_INT("xmlSchemaVDocWalk",
26918 "calling xmlSchemaValidatorPopElem()");
26919 goto internal_error;
26920 }
26921 }
26922 if (node == valRoot)
26923 goto exit;
26924 }
26925next_sibling:
26926 if (node->next != NULL)
26927 node = node->next;
26928 else {
26929 node = node->parent;
26930 goto leave_node;
26931 }
26932 }
26933
26934exit:
26935 return (ret);
26936internal_error:
26937 return (-1);
26938}
26939
26940static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000026941xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026942 /*
26943 * Some initialization.
26944 */
26945 vctxt->err = 0;
26946 vctxt->nberrors = 0;
26947 vctxt->depth = -1;
26948 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026949 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026950 /*
26951 * Create a schema + parser if necessary.
26952 */
26953 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026954 xmlSchemaParserCtxtPtr pctxt;
26955
26956 vctxt->xsiAssemble = 1;
26957 /*
26958 * If not schema was given then we will create a schema
26959 * dynamically using XSI schema locations.
26960 *
26961 * Create the schema parser context.
26962 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026963 if ((vctxt->pctxt == NULL) &&
26964 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
26965 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026966 pctxt = vctxt->pctxt;
26967 pctxt->xsiAssemble = 1;
26968 /*
26969 * Create the schema.
26970 */
26971 vctxt->schema = xmlSchemaNewSchema(pctxt);
26972 if (vctxt->schema == NULL)
26973 return (-1);
26974 /*
26975 * Create the schema construction context.
26976 */
26977 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
26978 if (pctxt->constructor == NULL)
26979 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026980 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026981 /*
26982 * Take ownership of the constructor to be able to free it.
26983 */
26984 pctxt->ownsConstructor = 1;
26985 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026986 /*
26987 * Augment the IDC definitions.
26988 */
26989 if (vctxt->schema->idcDef != NULL) {
26990 xmlHashScan(vctxt->schema->idcDef,
26991 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
26992 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000026993 return(0);
26994}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026995
Daniel Veillardf10ae122005-07-10 19:03:16 +000026996static void
26997xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026998 if (vctxt->xsiAssemble) {
26999 if (vctxt->schema != NULL) {
27000 xmlSchemaFree(vctxt->schema);
27001 vctxt->schema = NULL;
27002 }
27003 }
27004 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027005}
27006
27007static int
27008xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27009{
27010 int ret = 0;
27011
27012 if (xmlSchemaPreRun(vctxt) < 0)
27013 return(-1);
27014
27015 if (vctxt->doc != NULL) {
27016 /*
27017 * Tree validation.
27018 */
27019 ret = xmlSchemaVDocWalk(vctxt);
27020#ifdef LIBXML_READER_ENABLED
27021 } else if (vctxt->reader != NULL) {
27022 /*
27023 * XML Reader validation.
27024 */
27025#ifdef XML_SCHEMA_READER_ENABLED
27026 ret = xmlSchemaVReaderWalk(vctxt);
27027#endif
27028#endif
27029 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27030 /*
27031 * SAX validation.
27032 */
27033 ret = xmlParseDocument(vctxt->parserCtxt);
27034 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027035 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000027036 "no instance to validate");
27037 ret = -1;
27038 }
27039
27040 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027041 if (ret == 0)
27042 ret = vctxt->err;
27043 return (ret);
27044}
27045
27046/**
27047 * xmlSchemaValidateOneElement:
27048 * @ctxt: a schema validation context
27049 * @elem: an element node
27050 *
27051 * Validate a branch of a tree, starting with the given @elem.
27052 *
27053 * Returns 0 if the element and its subtree is valid, a positive error
27054 * code number otherwise and -1 in case of an internal or API error.
27055 */
27056int
27057xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27058{
27059 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27060 return (-1);
27061
27062 if (ctxt->schema == NULL)
27063 return (-1);
27064
27065 ctxt->doc = elem->doc;
27066 ctxt->node = elem;
27067 ctxt->validationRoot = elem;
27068 return(xmlSchemaVStart(ctxt));
27069}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027070
Daniel Veillard259f0df2004-08-18 09:13:18 +000027071/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027072 * xmlSchemaValidateDoc:
27073 * @ctxt: a schema validation context
27074 * @doc: a parsed document tree
27075 *
27076 * Validate a document tree in memory.
27077 *
27078 * Returns 0 if the document is schemas valid, a positive error code
27079 * number otherwise and -1 in case of internal or API error.
27080 */
27081int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027082xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27083{
Daniel Veillard4255d502002-04-16 15:50:10 +000027084 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027085 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027086
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027087 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027088 ctxt->node = xmlDocGetRootElement(doc);
27089 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027090 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027091 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27092 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027093 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027094 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027095 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027096 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027097 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000027098}
27099
Daniel Veillardcdc82732005-07-08 15:04:06 +000027100
27101/************************************************************************
27102 * *
27103 * Function and data for SAX streaming API *
27104 * *
27105 ************************************************************************/
27106typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27107typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27108
27109struct _xmlSchemaSplitSAXData {
27110 xmlSAXHandlerPtr user_sax;
27111 void *user_data;
27112 xmlSchemaValidCtxtPtr ctxt;
27113 xmlSAXHandlerPtr schemas_sax;
27114};
27115
Daniel Veillard971771e2005-07-09 17:32:57 +000027116#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27117
27118struct _xmlSchemaSAXPlug {
27119 unsigned int magic;
27120
27121 /* the original callbacks informations */
27122 xmlSAXHandlerPtr *user_sax_ptr;
27123 xmlSAXHandlerPtr user_sax;
27124 void **user_data_ptr;
27125 void *user_data;
27126
27127 /* the block plugged back and validation informations */
27128 xmlSAXHandler schemas_sax;
27129 xmlSchemaValidCtxtPtr ctxt;
27130};
27131
Daniel Veillardcdc82732005-07-08 15:04:06 +000027132/* All those functions just bounces to the user provided SAX handlers */
27133static void
27134internalSubsetSplit(void *ctx, const xmlChar *name,
27135 const xmlChar *ExternalID, const xmlChar *SystemID)
27136{
Daniel Veillard971771e2005-07-09 17:32:57 +000027137 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027138 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27139 (ctxt->user_sax->internalSubset != NULL))
27140 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27141 SystemID);
27142}
27143
27144static int
27145isStandaloneSplit(void *ctx)
27146{
Daniel Veillard971771e2005-07-09 17:32:57 +000027147 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027148 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27149 (ctxt->user_sax->isStandalone != NULL))
27150 return(ctxt->user_sax->isStandalone(ctxt->user_data));
27151 return(0);
27152}
27153
27154static int
27155hasInternalSubsetSplit(void *ctx)
27156{
Daniel Veillard971771e2005-07-09 17:32:57 +000027157 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027158 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27159 (ctxt->user_sax->hasInternalSubset != NULL))
27160 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27161 return(0);
27162}
27163
27164static int
27165hasExternalSubsetSplit(void *ctx)
27166{
Daniel Veillard971771e2005-07-09 17:32:57 +000027167 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027168 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27169 (ctxt->user_sax->hasExternalSubset != NULL))
27170 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27171 return(0);
27172}
27173
27174static void
27175externalSubsetSplit(void *ctx, const xmlChar *name,
27176 const xmlChar *ExternalID, const xmlChar *SystemID)
27177{
Daniel Veillard971771e2005-07-09 17:32:57 +000027178 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027179 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27180 (ctxt->user_sax->internalSubset != NULL))
27181 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27182 SystemID);
27183}
27184
27185static xmlParserInputPtr
27186resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27187{
Daniel Veillard971771e2005-07-09 17:32:57 +000027188 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027189 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27190 (ctxt->user_sax->resolveEntity != NULL))
27191 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27192 systemId));
27193 return(NULL);
27194}
27195
27196static xmlEntityPtr
27197getEntitySplit(void *ctx, const xmlChar *name)
27198{
Daniel Veillard971771e2005-07-09 17:32:57 +000027199 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027200 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27201 (ctxt->user_sax->getEntity != NULL))
27202 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27203 return(NULL);
27204}
27205
27206static xmlEntityPtr
27207getParameterEntitySplit(void *ctx, const xmlChar *name)
27208{
Daniel Veillard971771e2005-07-09 17:32:57 +000027209 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027210 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27211 (ctxt->user_sax->getParameterEntity != NULL))
27212 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27213 return(NULL);
27214}
27215
27216
27217static void
27218entityDeclSplit(void *ctx, const xmlChar *name, int type,
27219 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27220{
Daniel Veillard971771e2005-07-09 17:32:57 +000027221 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027222 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27223 (ctxt->user_sax->entityDecl != NULL))
27224 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27225 systemId, content);
27226}
27227
27228static void
27229attributeDeclSplit(void *ctx, const xmlChar * elem,
27230 const xmlChar * name, int type, int def,
27231 const xmlChar * defaultValue, xmlEnumerationPtr tree)
27232{
Daniel Veillard971771e2005-07-09 17:32:57 +000027233 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027234 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27235 (ctxt->user_sax->attributeDecl != NULL)) {
27236 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27237 def, defaultValue, tree);
27238 } else {
27239 xmlFreeEnumeration(tree);
27240 }
27241}
27242
27243static void
27244elementDeclSplit(void *ctx, const xmlChar *name, int type,
27245 xmlElementContentPtr content)
27246{
Daniel Veillard971771e2005-07-09 17:32:57 +000027247 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027248 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27249 (ctxt->user_sax->elementDecl != NULL))
27250 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27251}
27252
27253static void
27254notationDeclSplit(void *ctx, const xmlChar *name,
27255 const xmlChar *publicId, const xmlChar *systemId)
27256{
Daniel Veillard971771e2005-07-09 17:32:57 +000027257 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027258 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27259 (ctxt->user_sax->notationDecl != NULL))
27260 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27261 systemId);
27262}
27263
27264static void
27265unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27266 const xmlChar *publicId, const xmlChar *systemId,
27267 const xmlChar *notationName)
27268{
Daniel Veillard971771e2005-07-09 17:32:57 +000027269 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027270 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27271 (ctxt->user_sax->unparsedEntityDecl != NULL))
27272 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27273 systemId, notationName);
27274}
27275
27276static void
27277setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27278{
Daniel Veillard971771e2005-07-09 17:32:57 +000027279 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027280 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27281 (ctxt->user_sax->setDocumentLocator != NULL))
27282 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27283}
27284
27285static void
27286startDocumentSplit(void *ctx)
27287{
Daniel Veillard971771e2005-07-09 17:32:57 +000027288 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027289 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27290 (ctxt->user_sax->startDocument != NULL))
27291 ctxt->user_sax->startDocument(ctxt->user_data);
27292}
27293
27294static void
27295endDocumentSplit(void *ctx)
27296{
Daniel Veillard971771e2005-07-09 17:32:57 +000027297 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027298 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27299 (ctxt->user_sax->endDocument != NULL))
27300 ctxt->user_sax->endDocument(ctxt->user_data);
27301}
27302
27303static void
27304processingInstructionSplit(void *ctx, const xmlChar *target,
27305 const xmlChar *data)
27306{
Daniel Veillard971771e2005-07-09 17:32:57 +000027307 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027308 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27309 (ctxt->user_sax->processingInstruction != NULL))
27310 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27311}
27312
27313static void
27314commentSplit(void *ctx, const xmlChar *value)
27315{
Daniel Veillard971771e2005-07-09 17:32:57 +000027316 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027317 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27318 (ctxt->user_sax->comment != NULL))
27319 ctxt->user_sax->comment(ctxt->user_data, value);
27320}
27321
27322/*
27323 * Varargs error callbacks to the user application, harder ...
27324 */
27325
Daniel Veillardffa3c742005-07-21 13:24:09 +000027326static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027327warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027328 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027329 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27330 (ctxt->user_sax->warning != NULL)) {
27331 TODO
27332 }
27333}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027334static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027335errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027336 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027337 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27338 (ctxt->user_sax->error != NULL)) {
27339 TODO
27340 }
27341}
Daniel Veillardffa3c742005-07-21 13:24:09 +000027342static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000027343fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027344 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027345 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27346 (ctxt->user_sax->fatalError != NULL)) {
27347 TODO
27348 }
27349}
27350
27351/*
27352 * Those are function where both the user handler and the schemas handler
27353 * need to be called.
27354 */
27355static void
27356charactersSplit(void *ctx, const xmlChar *ch, int len)
27357{
Daniel Veillard971771e2005-07-09 17:32:57 +000027358 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027359 if (ctxt == NULL)
27360 return;
27361 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
27362 ctxt->user_sax->characters(ctxt->user_data, ch, len);
27363 if (ctxt->ctxt != NULL)
27364 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27365}
27366
27367static void
27368ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
27369{
Daniel Veillard971771e2005-07-09 17:32:57 +000027370 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027371 if (ctxt == NULL)
27372 return;
27373 if ((ctxt->user_sax != NULL) &&
27374 (ctxt->user_sax->ignorableWhitespace != NULL))
27375 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
27376 if (ctxt->ctxt != NULL)
27377 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
27378}
27379
27380static void
27381cdataBlockSplit(void *ctx, const xmlChar *value, int len)
27382{
Daniel Veillard971771e2005-07-09 17:32:57 +000027383 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027384 if (ctxt == NULL)
27385 return;
27386 if ((ctxt->user_sax != NULL) &&
27387 (ctxt->user_sax->ignorableWhitespace != NULL))
27388 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
27389 if (ctxt->ctxt != NULL)
27390 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
27391}
27392
27393static void
27394referenceSplit(void *ctx, const xmlChar *name)
27395{
Daniel Veillard971771e2005-07-09 17:32:57 +000027396 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027397 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27398 (ctxt->user_sax->reference != NULL))
27399 ctxt->user_sax->reference(ctxt->user_data, name);
27400 if (ctxt->ctxt != NULL)
27401 xmlSchemaSAXHandleReference(ctxt->user_data, name);
27402}
27403
27404static void
27405startElementNsSplit(void *ctx, const xmlChar * localname,
27406 const xmlChar * prefix, const xmlChar * URI,
27407 int nb_namespaces, const xmlChar ** namespaces,
27408 int nb_attributes, int nb_defaulted,
27409 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027410 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027411 if (ctxt == NULL)
27412 return;
27413 if ((ctxt->user_sax != NULL) &&
27414 (ctxt->user_sax->startElementNs != NULL))
27415 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
27416 URI, nb_namespaces, namespaces,
27417 nb_attributes, nb_defaulted,
27418 attributes);
27419 if (ctxt->ctxt != NULL)
27420 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
27421 URI, nb_namespaces, namespaces,
27422 nb_attributes, nb_defaulted,
27423 attributes);
27424}
27425
27426static void
27427endElementNsSplit(void *ctx, const xmlChar * localname,
27428 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000027429 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027430 if (ctxt == NULL)
27431 return;
27432 if ((ctxt->user_sax != NULL) &&
27433 (ctxt->user_sax->endElementNs != NULL))
27434 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
27435 if (ctxt->ctxt != NULL)
27436 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
27437}
27438
Daniel Veillard4255d502002-04-16 15:50:10 +000027439/**
Daniel Veillard971771e2005-07-09 17:32:57 +000027440 * xmlSchemaSAXPlug:
27441 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000027442 * @sax: a pointer to the original xmlSAXHandlerPtr
27443 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000027444 *
27445 * Plug a SAX based validation layer in a SAX parsing event flow.
27446 * The original @saxptr and @dataptr data are replaced by new pointers
27447 * but the calls to the original will be maintained.
27448 *
27449 * Returns a pointer to a data structure needed to unplug the validation layer
27450 * or NULL in case of errors.
27451 */
27452xmlSchemaSAXPlugPtr
27453xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
27454 xmlSAXHandlerPtr *sax, void **user_data)
27455{
27456 xmlSchemaSAXPlugPtr ret;
27457 xmlSAXHandlerPtr old_sax;
27458
27459 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
27460 return(NULL);
27461
27462 /*
27463 * We only allow to plug into SAX2 event streams
27464 */
27465 old_sax = *sax;
27466 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
27467 return(NULL);
27468 if ((old_sax != NULL) &&
27469 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
27470 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
27471 return(NULL);
27472
27473 /*
27474 * everything seems right allocate the local data needed for that layer
27475 */
27476 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
27477 if (ret == NULL) {
27478 return(NULL);
27479 }
27480 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
27481 ret->magic = XML_SAX_PLUG_MAGIC;
27482 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
27483 ret->ctxt = ctxt;
27484 ret->user_sax_ptr = sax;
27485 ret->user_sax = old_sax;
27486 if (old_sax == NULL) {
27487 /*
27488 * go direct, no need for the split block and functions.
27489 */
27490 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
27491 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
27492 /*
27493 * Note that we use the same text-function for both, to prevent
27494 * the parser from testing for ignorable whitespace.
27495 */
27496 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
27497 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
27498
27499 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
27500 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
27501
27502 ret->user_data = ctxt;
27503 *user_data = ctxt;
27504 } else {
27505 /*
27506 * for each callback unused by Schemas initialize it to the Split
27507 * routine only if non NULL in the user block, this can speed up
27508 * things at the SAX level.
27509 */
27510 if (old_sax->internalSubset != NULL)
27511 ret->schemas_sax.internalSubset = internalSubsetSplit;
27512 if (old_sax->isStandalone != NULL)
27513 ret->schemas_sax.isStandalone = isStandaloneSplit;
27514 if (old_sax->hasInternalSubset != NULL)
27515 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
27516 if (old_sax->hasExternalSubset != NULL)
27517 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
27518 if (old_sax->resolveEntity != NULL)
27519 ret->schemas_sax.resolveEntity = resolveEntitySplit;
27520 if (old_sax->getEntity != NULL)
27521 ret->schemas_sax.getEntity = getEntitySplit;
27522 if (old_sax->entityDecl != NULL)
27523 ret->schemas_sax.entityDecl = entityDeclSplit;
27524 if (old_sax->notationDecl != NULL)
27525 ret->schemas_sax.notationDecl = notationDeclSplit;
27526 if (old_sax->attributeDecl != NULL)
27527 ret->schemas_sax.attributeDecl = attributeDeclSplit;
27528 if (old_sax->elementDecl != NULL)
27529 ret->schemas_sax.elementDecl = elementDeclSplit;
27530 if (old_sax->unparsedEntityDecl != NULL)
27531 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
27532 if (old_sax->setDocumentLocator != NULL)
27533 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
27534 if (old_sax->startDocument != NULL)
27535 ret->schemas_sax.startDocument = startDocumentSplit;
27536 if (old_sax->endDocument != NULL)
27537 ret->schemas_sax.endDocument = endDocumentSplit;
27538 if (old_sax->processingInstruction != NULL)
27539 ret->schemas_sax.processingInstruction = processingInstructionSplit;
27540 if (old_sax->comment != NULL)
27541 ret->schemas_sax.comment = commentSplit;
27542 if (old_sax->warning != NULL)
27543 ret->schemas_sax.warning = warningSplit;
27544 if (old_sax->error != NULL)
27545 ret->schemas_sax.error = errorSplit;
27546 if (old_sax->fatalError != NULL)
27547 ret->schemas_sax.fatalError = fatalErrorSplit;
27548 if (old_sax->getParameterEntity != NULL)
27549 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
27550 if (old_sax->externalSubset != NULL)
27551 ret->schemas_sax.externalSubset = externalSubsetSplit;
27552
27553 /*
27554 * the 6 schemas callback have to go to the splitter functions
27555 * Note that we use the same text-function for ignorableWhitespace
27556 * if possible, to prevent the parser from testing for ignorable
27557 * whitespace.
27558 */
27559 ret->schemas_sax.characters = charactersSplit;
27560 if ((old_sax->ignorableWhitespace != NULL) &&
27561 (old_sax->ignorableWhitespace != old_sax->characters))
27562 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
27563 else
27564 ret->schemas_sax.ignorableWhitespace = charactersSplit;
27565 ret->schemas_sax.cdataBlock = cdataBlockSplit;
27566 ret->schemas_sax.reference = referenceSplit;
27567 ret->schemas_sax.startElementNs = startElementNsSplit;
27568 ret->schemas_sax.endElementNs = endElementNsSplit;
27569
27570 ret->user_data_ptr = user_data;
27571 ret->user_data = *user_data;
27572 *user_data = ret;
27573 }
27574
27575 /*
27576 * plug the pointers back.
27577 */
27578 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000027579 ctxt->sax = *sax;
27580 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
27581 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000027582 return(ret);
27583}
27584
27585/**
27586 * xmlSchemaSAXUnplug:
27587 * @plug: a data structure returned by xmlSchemaSAXPlug
27588 *
27589 * Unplug a SAX based validation layer in a SAX parsing event flow.
27590 * The original pointers used in the call are restored.
27591 *
27592 * Returns 0 in case of success and -1 in case of failure.
27593 */
27594int
27595xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
27596{
27597 xmlSAXHandlerPtr *sax;
27598 void **user_data;
27599
27600 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
27601 return(-1);
27602 plug->magic = 0;
27603
Daniel Veillardf10ae122005-07-10 19:03:16 +000027604 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000027605 /* restore the data */
27606 sax = plug->user_sax_ptr;
27607 *sax = plug->user_sax;
27608 if (plug->user_sax != NULL) {
27609 user_data = plug->user_data_ptr;
27610 *user_data = plug->user_data;
27611 }
27612
27613 /* free and return */
27614 xmlFree(plug);
27615 return(0);
27616}
27617
27618/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027619 * xmlSchemaValidateStream:
27620 * @ctxt: a schema validation context
27621 * @input: the input to use for reading the data
27622 * @enc: an optional encoding information
27623 * @sax: a SAX handler for the resulting events
27624 * @user_data: the context to provide to the SAX handler.
27625 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000027626 * Validate an input based on a flow of SAX event from the parser
27627 * and forward the events to the @sax handler with the provided @user_data
27628 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000027629 *
27630 * Returns 0 if the document is schemas valid, a positive error code
27631 * number otherwise and -1 in case of internal or API error.
27632 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027633int
Daniel Veillard4255d502002-04-16 15:50:10 +000027634xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027635 xmlParserInputBufferPtr input, xmlCharEncoding enc,
27636 xmlSAXHandlerPtr sax, void *user_data)
27637{
Daniel Veillard971771e2005-07-09 17:32:57 +000027638 xmlSchemaSAXPlugPtr plug = NULL;
27639 xmlSAXHandlerPtr old_sax = NULL;
27640 xmlParserCtxtPtr pctxt = NULL;
27641 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027642 int ret;
27643
Daniel Veillard4255d502002-04-16 15:50:10 +000027644 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027645 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000027646
Daniel Veillardcdc82732005-07-08 15:04:06 +000027647 /*
27648 * prepare the parser
27649 */
27650 pctxt = xmlNewParserCtxt();
27651 if (pctxt == NULL)
27652 return (-1);
27653 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000027654 pctxt->sax = sax;
27655 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027656#if 0
27657 if (options)
27658 xmlCtxtUseOptions(pctxt, options);
27659#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000027660 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027661
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000027662 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027663 if (inputStream == NULL) {
27664 ret = -1;
27665 goto done;
27666 }
27667 inputPush(pctxt, inputStream);
27668 ctxt->parserCtxt = pctxt;
27669 ctxt->input = input;
27670
27671 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000027672 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000027673 */
Daniel Veillard971771e2005-07-09 17:32:57 +000027674 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
27675 if (plug == NULL) {
27676 ret = -1;
27677 goto done;
27678 }
27679 ctxt->input = input;
27680 ctxt->enc = enc;
27681 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000027682 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
27683 ret = xmlSchemaVStart(ctxt);
27684
27685 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
27686 ret = ctxt->parserCtxt->errNo;
27687 if (ret == 0)
27688 ret = 1;
27689 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000027690
27691done:
Daniel Veillard971771e2005-07-09 17:32:57 +000027692 ctxt->parserCtxt = NULL;
27693 ctxt->sax = NULL;
27694 ctxt->input = NULL;
27695 if (plug != NULL) {
27696 xmlSchemaSAXUnplug(plug);
27697 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000027698 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000027699 if (pctxt != NULL) {
27700 pctxt->sax = old_sax;
27701 xmlFreeParserCtxt(pctxt);
27702 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000027703 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000027704}
27705
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027706/**
27707 * xmlSchemaValidateFile:
27708 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000027709 * @filename: the URI of the instance
27710 * @options: a future set of options, currently unused
27711 *
27712 * Do a schemas validation of the given resource, it will use the
27713 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027714 *
27715 * Returns 0 if the document is valid, a positive error code
27716 * number otherwise and -1 in case of an internal or API error.
27717 */
27718int
27719xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000027720 const char * filename,
27721 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027722{
27723 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000027724 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027725
27726 if ((ctxt == NULL) || (filename == NULL))
27727 return (-1);
27728
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000027729 input = xmlParserInputBufferCreateFilename(filename,
27730 XML_CHAR_ENCODING_NONE);
27731 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027732 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000027733 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
27734 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027735 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000027736}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027737
Daniel Veillard5d4644e2005-04-01 13:11:58 +000027738#define bottom_xmlschemas
27739#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000027740#endif /* LIBXML_SCHEMAS_ENABLED */