blob: 1938d7ea6a1b418587df33e83ec20652f756548e [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000046 */
Stéphane Michaut454e3972017-08-28 14:30:43 +020047
48/* To avoid EBCDIC trouble when parsing on zOS */
49#if defined(__MVS__)
50#pragma convert("ISO8859-1")
51#endif
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define IN_LIBXML
54#include "libxml.h"
55
56#ifdef LIBXML_SCHEMAS_ENABLED
57
58#include <string.h>
59#include <libxml/xmlmemory.h>
60#include <libxml/parser.h>
61#include <libxml/parserInternals.h>
62#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000063#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000064#include <libxml/xmlschemas.h>
65#include <libxml/schemasInternals.h>
66#include <libxml/xmlschemastypes.h>
67#include <libxml/xmlautomata.h>
68#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000069#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000070#include <libxml/encoding.h>
71#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000072#ifdef LIBXML_PATTERN_ENABLED
73#include <libxml/pattern.h>
74#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000075#ifdef LIBXML_READER_ENABLED
76#include <libxml/xmlreader.h>
77#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000078
Daniel Veillarda84c0b32003-06-02 16:58:46 +000079/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000080
Daniel Veillard82bbbd42003-05-11 20:16:09 +000081/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082
Daniel Veillard82bbbd42003-05-11 20:16:09 +000083/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000084
Daniel Veillard118aed72002-09-24 14:13:13 +000085/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000086
Daniel Veillard4255d502002-04-16 15:50:10 +000087/* #define DEBUG_AUTOMATA 1 */
88
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000089/* #define DEBUG_IDC */
90
91/* #define DEBUG_IDC_NODE_TABLE */
92
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000093/* #define WXS_ELEM_DECL_CONS_ENABLED */
94
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000095#ifdef DEBUG_IDC
96 #ifndef DEBUG_IDC_NODE_TABLE
97 #define DEBUG_IDC_NODE_TABLE
98 #endif
Daniel Veillarddee23482008-04-11 12:58:43 +000099#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000100
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000101/* #define ENABLE_PARTICLE_RESTRICTION 1 */
102
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000103#define ENABLE_REDEFINE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000104
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000105/* #define ENABLE_NAMED_LOCALS */
106
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +0000107/* #define ENABLE_IDC_NODE_TABLES_TEST */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000108
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000109#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000110
111#ifdef LIBXML_READER_ENABLED
112/* #define XML_SCHEMA_READER_ENABLED */
113#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000114
Daniel Veillard4255d502002-04-16 15:50:10 +0000115#define UNBOUNDED (1 << 30)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800116#define TODO \
Daniel Veillard4255d502002-04-16 15:50:10 +0000117 xmlGenericError(xmlGenericErrorContext, \
118 "Unimplemented block at %s:%d\n", \
119 __FILE__, __LINE__);
120
William M. Brack2f2a6632004-08-20 23:09:47 +0000121#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +0000122
Daniel Veillard4255d502002-04-16 15:50:10 +0000123/*
124 * The XML Schemas namespaces
125 */
126static const xmlChar *xmlSchemaNs = (const xmlChar *)
127 "http://www.w3.org/2001/XMLSchema";
128
129static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130 "http://www.w3.org/2001/XMLSchema-instance";
131
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000132static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133 "http://www.w3.org/2000/xmlns/";
134
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000135/*
136* Come casting macros.
137*/
138#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +0000139#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000141#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143#define WXS_PTC_CAST (xmlSchemaParticlePtr)
144#define WXS_TYPE_CAST (xmlSchemaTypePtr)
145#define WXS_ELEM_CAST (xmlSchemaElementPtr)
146#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152#define WXS_IDC_CAST (xmlSchemaIDCPtr)
153#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154#define WXS_LIST_CAST (xmlSchemaItemListPtr)
Daniel Veillardc0826a72004-08-10 14:17:33 +0000155
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000156/*
157* Macros to query common properties of components.
158*/
159#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
Daniel Veillard4255d502002-04-16 15:50:10 +0000160
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000161#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
162/*
163* Macros for element declarations.
164*/
165#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
Daniel Veillardc0826a72004-08-10 14:17:33 +0000166
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000167#define WXS_SUBST_HEAD(item) (item)->refDecl
168/*
169* Macros for attribute declarations.
170*/
171#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
172/*
173* Macros for attribute uses.
174*/
Nick Wellnhofer1a595cd2017-06-17 14:13:51 +0200175#define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000176
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000177#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000178
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000179#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
180
181#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
182/*
183* Macros for attribute groups.
184*/
185#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
187/*
188* Macros for particles.
189*/
190#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
191
192#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
193
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000194#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
195
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000196#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
197/*
198* Macros for model groups definitions.
199*/
200#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
201/*
202* Macros for model groups.
203*/
204#define WXS_IS_MODEL_GROUP(i) \
205 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207 ((i)->type == XML_SCHEMA_TYPE_ALL))
208
209#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
210/*
211* Macros for schema buckets.
212*/
213#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
215
216#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
218
219#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
220
221#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
222/*
223* Macros for complex/simple types.
224*/
225#define WXS_IS_ANYTYPE(i) \
226 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
228
229#define WXS_IS_COMPLEX(i) \
230 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
232
233#define WXS_IS_SIMPLE(item) \
234 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000236 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000237
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000238#define WXS_IS_ANY_SIMPLE_TYPE(i) \
239 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000241
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000242#define WXS_IS_RESTRICTION(t) \
243 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000244
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000245#define WXS_IS_EXTENSION(t) \
246 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
247
248#define WXS_IS_TYPE_NOT_FIXED(i) \
249 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
251
252#define WXS_IS_TYPE_NOT_FIXED_1(item) \
253 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000254 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000255
256#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
257
258#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000259/*
260* Macros for exclusively for complex types.
261*/
262#define WXS_HAS_COMPLEX_CONTENT(item) \
263 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000265 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
266
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000267#define WXS_HAS_SIMPLE_CONTENT(item) \
268 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000269 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
270
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000271#define WXS_HAS_MIXED_CONTENT(item) \
272 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000273
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000274#define WXS_EMPTIABLE(t) \
275 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000276
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000277#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000278
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000279#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000280
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000281#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
282/*
283* Macros for exclusively for simple types.
284*/
285#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000286
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000287#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000288
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000289#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000290
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000291#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
292/*
293* Misc parser context macros.
294*/
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000295#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
296
297#define WXS_HAS_BUCKETS(ctx) \
298( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
300
301#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
302
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000303#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000304
305#define WXS_SCHEMA(ctx) (ctx)->schema
306
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000307#define WXS_ADD_LOCAL(ctx, item) \
308 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000309
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000310#define WXS_ADD_GLOBAL(ctx, item) \
311 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000312
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000313#define WXS_ADD_PENDING(ctx, item) \
314 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
315/*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000316* xmlSchemaItemList macros.
317*/
318#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
319/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000320* Misc macros.
321*/
322#define IS_SCHEMA(node, type) \
323 ((node != NULL) && (node->ns != NULL) && \
324 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000326
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000327#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000328
329/*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000330* Since we put the default/fixed values into the dict, we can
331* use pointer comparison for those values.
332* REMOVED: (xmlStrEqual((v1), (v2)))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000333*/
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000334#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000335
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000336#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000337
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000338#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000339
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000340#define HFAILURE if (res == -1) goto exit_failure;
341
342#define HERROR if (res != 0) goto exit_error;
343
344#define HSTOP(ctx) if ((ctx)->stop) goto exit;
345/*
346* Some flags used for various schema constraints.
347*/
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000348#define SUBSET_RESTRICTION 1<<0
349#define SUBSET_EXTENSION 1<<1
350#define SUBSET_SUBSTITUTION 1<<2
351#define SUBSET_LIST 1<<3
352#define SUBSET_UNION 1<<4
353
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000354typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000356
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000357typedef struct _xmlSchemaItemList xmlSchemaItemList;
358typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000359struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000360 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000361 int nbItems; /* used for dynamic addition of schemata */
362 int sizeItems; /* used for dynamic addition of schemata */
363};
364
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000365#define XML_SCHEMA_CTXT_PARSER 1
366#define XML_SCHEMA_CTXT_VALIDATOR 2
367
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000368typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370struct _xmlSchemaAbstractCtxt {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000371 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
Nick Wellnhofer1a595cd2017-06-17 14:13:51 +0200372 void *dummy; /* Fix alignment issues */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000373};
374
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000375typedef struct _xmlSchemaBucket xmlSchemaBucket;
376typedef xmlSchemaBucket *xmlSchemaBucketPtr;
377
378#define XML_SCHEMA_SCHEMA_MAIN 0
379#define XML_SCHEMA_SCHEMA_IMPORT 1
380#define XML_SCHEMA_SCHEMA_INCLUDE 2
381#define XML_SCHEMA_SCHEMA_REDEFINE 3
382
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000383/**
Daniel Veillarddee23482008-04-11 12:58:43 +0000384 * xmlSchemaSchemaRelation:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000385 *
386 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000387 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000388typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390struct _xmlSchemaSchemaRelation {
391 xmlSchemaSchemaRelationPtr next;
392 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393 const xmlChar *importNamespace;
394 xmlSchemaBucketPtr bucket;
395};
396
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000397#define XML_SCHEMA_BUCKET_MARKED 1<<0
398#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
399
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000400struct _xmlSchemaBucket {
401 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000402 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000403 const xmlChar *schemaLocation;
404 const xmlChar *origTargetNamespace;
405 const xmlChar *targetNamespace;
406 xmlDocPtr doc;
407 xmlSchemaSchemaRelationPtr relations;
408 int located;
409 int parsed;
410 int imported;
411 int preserveDoc;
Daniel Veillarddee23482008-04-11 12:58:43 +0000412 xmlSchemaItemListPtr globals; /* Global components. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000413 xmlSchemaItemListPtr locals; /* Local components. */
414};
415
416/**
Daniel Veillarddee23482008-04-11 12:58:43 +0000417 * xmlSchemaImport:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000418 * (extends xmlSchemaBucket)
419 *
420 * Reflects a schema. Holds some information
421 * about the schema and its toplevel components. Duplicate
422 * toplevel components are not checked at this level.
423 */
424typedef struct _xmlSchemaImport xmlSchemaImport;
425typedef xmlSchemaImport *xmlSchemaImportPtr;
426struct _xmlSchemaImport {
427 int type; /* Main OR import OR include. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000428 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000429 const xmlChar *schemaLocation; /* The URI of the schema document. */
430 /* For chameleon includes, @origTargetNamespace will be NULL */
431 const xmlChar *origTargetNamespace;
Daniel Veillarddee23482008-04-11 12:58:43 +0000432 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000433 * For chameleon includes, @targetNamespace will be the
Daniel Veillarddee23482008-04-11 12:58:43 +0000434 * targetNamespace of the including schema.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000435 */
436 const xmlChar *targetNamespace;
437 xmlDocPtr doc; /* The schema node-tree. */
438 /* @relations will hold any included/imported/redefined schemas. */
439 xmlSchemaSchemaRelationPtr relations;
440 int located;
441 int parsed;
442 int imported;
443 int preserveDoc;
444 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000445 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000446 /* The imported schema. */
447 xmlSchemaPtr schema;
448};
449
450/*
451* (extends xmlSchemaBucket)
452*/
453typedef struct _xmlSchemaInclude xmlSchemaInclude;
454typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455struct _xmlSchemaInclude {
456 int type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000457 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000458 const xmlChar *schemaLocation;
459 const xmlChar *origTargetNamespace;
460 const xmlChar *targetNamespace;
461 xmlDocPtr doc;
462 xmlSchemaSchemaRelationPtr relations;
463 int located;
464 int parsed;
465 int imported;
466 int preserveDoc;
Daniel Veillarddee23482008-04-11 12:58:43 +0000467 xmlSchemaItemListPtr globals; /* Global components. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000468 xmlSchemaItemListPtr locals; /* Local components. */
469
470 /* The owning main or import schema bucket. */
471 xmlSchemaImportPtr ownerImport;
472};
473
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000474/**
475 * xmlSchemaBasicItem:
476 *
477 * The abstract base type for schema components.
478 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000479typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481struct _xmlSchemaBasicItem {
482 xmlSchemaTypeType type;
Nick Wellnhofer1a595cd2017-06-17 14:13:51 +0200483 void *dummy; /* Fix alignment issues */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000484};
485
486/**
487 * xmlSchemaAnnotItem:
488 *
489 * The abstract base type for annotated schema components.
490 * (Extends xmlSchemaBasicItem)
491 */
492typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494struct _xmlSchemaAnnotItem {
495 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000496 xmlSchemaAnnotPtr annot;
497};
498
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000499/**
500 * xmlSchemaTreeItem:
501 *
502 * The abstract base type for tree-like structured schema components.
503 * (Extends xmlSchemaAnnotItem)
504 */
505typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507struct _xmlSchemaTreeItem {
508 xmlSchemaTypeType type;
509 xmlSchemaAnnotPtr annot;
510 xmlSchemaTreeItemPtr next;
511 xmlSchemaTreeItemPtr children;
512};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000513
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000514
515#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
516/**
517 * xmlSchemaAttributeUsePtr:
518 *
519 * The abstract base type for tree-like structured schema components.
520 * (Extends xmlSchemaTreeItem)
521 */
522typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524struct _xmlSchemaAttributeUse {
525 xmlSchemaTypeType type;
526 xmlSchemaAnnotPtr annot;
527 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000528 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000529 * The attr. decl. OR a QName-ref. to an attr. decl. OR
530 * a QName-ref. to an attribute group definition.
531 */
532 xmlSchemaAttributePtr attrDecl;
533
534 int flags;
535 xmlNodePtr node;
536 int occurs; /* required, optional */
537 const xmlChar * defValue;
538 xmlSchemaValPtr defVal;
539};
540
541/**
542 * xmlSchemaAttributeUseProhibPtr:
543 *
544 * A helper component to reflect attribute prohibitions.
545 * (Extends xmlSchemaBasicItem)
546 */
547typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549struct _xmlSchemaAttributeUseProhib {
550 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551 xmlNodePtr node;
552 const xmlChar *name;
553 const xmlChar *targetNamespace;
554 int isRef;
555};
556
557/**
558 * xmlSchemaRedef:
559 */
560typedef struct _xmlSchemaRedef xmlSchemaRedef;
561typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562struct _xmlSchemaRedef {
563 xmlSchemaRedefPtr next;
564 xmlSchemaBasicItemPtr item; /* The redefining component. */
565 xmlSchemaBasicItemPtr reference; /* The referencing component. */
566 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567 const xmlChar *refName; /* The name of the to-be-redefined component. */
568 const xmlChar *refTargetNs; /* The target namespace of the
569 to-be-redefined comp. */
570 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
571};
572
573/**
574 * xmlSchemaConstructionCtxt:
575 */
576typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578struct _xmlSchemaConstructionCtxt {
579 xmlSchemaPtr mainSchema; /* The main schema. */
580 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581 xmlDictPtr dict;
582 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000584 xmlSchemaBucketPtr bucket; /* The current schema bucket */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000585 xmlSchemaItemListPtr pending; /* All Components of all schemas that
586 need to be fixed. */
587 xmlHashTablePtr substGroups;
588 xmlSchemaRedefPtr redefs;
589 xmlSchemaRedefPtr lastRedef;
590};
591
592#define XML_SCHEMAS_PARSE_ERROR 1
593#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
594
595struct _xmlSchemaParserCtxt {
596 int type;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +0000597 void *errCtxt; /* user specific error context */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000598 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
599 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Kasimier T. Buchcikdfbc33a2006-01-03 10:51:59 +0000600 int err;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000601 int nberrors;
602 xmlStructuredErrorFunc serror;
603
604 xmlSchemaConstructionCtxtPtr constructor;
605 int ownsConstructor; /* TODO: Move this to parser *flags*. */
606
607 /* xmlSchemaPtr topschema; */
608 /* xmlHashTablePtr namespaces; */
609
610 xmlSchemaPtr schema; /* The main schema in use */
611 int counter;
612
613 const xmlChar *URL;
614 xmlDocPtr doc;
615 int preserve; /* Whether the doc should be freed */
616
617 const char *buffer;
618 int size;
619
620 /*
621 * Used to build complex element content models
622 */
623 xmlAutomataPtr am;
624 xmlAutomataStatePtr start;
625 xmlAutomataStatePtr end;
626 xmlAutomataStatePtr state;
627
Jan Pokornýbb654fe2016-04-13 16:56:07 +0200628 xmlDictPtr dict; /* dictionary for interned string names */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000629 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630 int options;
631 xmlSchemaValidCtxtPtr vctxt;
632 int isS4S;
633 int isRedefine;
634 int xsiAssemble;
635 int stop; /* If the parser should stop; i.e. a critical error. */
636 const xmlChar *targetNamespace;
637 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
638
639 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
Daniel Veillarddee23482008-04-11 12:58:43 +0000640 int redefCounter; /* Used for redefinitions. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000641 xmlSchemaItemListPtr attrProhibs;
642};
643
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000644/**
645 * xmlSchemaQNameRef:
646 *
647 * A component reference item (not a schema component)
648 * (Extends xmlSchemaBasicItem)
649 */
650typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652struct _xmlSchemaQNameRef {
653 xmlSchemaTypeType type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000654 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000655 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 const xmlChar *name;
657 const xmlChar *targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000658 xmlNodePtr node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000659};
660
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000661/**
662 * xmlSchemaParticle:
663 *
664 * A particle component.
665 * (Extends xmlSchemaTreeItem)
666 */
667typedef struct _xmlSchemaParticle xmlSchemaParticle;
668typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669struct _xmlSchemaParticle {
670 xmlSchemaTypeType type;
671 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000672 xmlSchemaTreeItemPtr next; /* next particle */
673 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675 etc.) */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000676 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000677 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000678 xmlNodePtr node;
679};
680
681/**
682 * xmlSchemaModelGroup:
683 *
684 * A model group component.
685 * (Extends xmlSchemaTreeItem)
686 */
687typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689struct _xmlSchemaModelGroup {
690 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691 xmlSchemaAnnotPtr annot;
692 xmlSchemaTreeItemPtr next; /* not used */
693 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694 xmlNodePtr node;
695};
696
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000697#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000698#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000699/**
700 * xmlSchemaModelGroupDef:
701 *
702 * A model group definition component.
703 * (Extends xmlSchemaTreeItem)
704 */
705typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707struct _xmlSchemaModelGroupDef {
708 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709 xmlSchemaAnnotPtr annot;
710 xmlSchemaTreeItemPtr next; /* not used */
711 xmlSchemaTreeItemPtr children; /* the "model group" */
712 const xmlChar *name;
713 const xmlChar *targetNamespace;
714 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000715 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000716};
717
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000718typedef struct _xmlSchemaIDC xmlSchemaIDC;
719typedef xmlSchemaIDC *xmlSchemaIDCPtr;
720
721/**
722 * xmlSchemaIDCSelect:
723 *
724 * The identity-constraint "field" and "selector" item, holding the
725 * XPath expression.
726 */
727typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000729struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000730 xmlSchemaIDCSelectPtr next;
731 xmlSchemaIDCPtr idc;
732 int index; /* an index position if significant for IDC key-sequences */
733 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000734 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000735};
736
737/**
738 * xmlSchemaIDC:
739 *
740 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000741 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000742 */
743
744struct _xmlSchemaIDC {
745 xmlSchemaTypeType type;
746 xmlSchemaAnnotPtr annot;
747 xmlSchemaIDCPtr next;
748 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000749 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000750 const xmlChar *targetNamespace;
751 xmlSchemaIDCSelectPtr selector;
752 xmlSchemaIDCSelectPtr fields;
753 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000754 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000755};
756
757/**
758 * xmlSchemaIDCAug:
759 *
760 * The augmented IDC information used for validation.
761 */
762typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764struct _xmlSchemaIDCAug {
765 xmlSchemaIDCAugPtr next; /* next in a list */
766 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000767 int keyrefDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000768 tables need to be bubbled upwards */
769};
770
771/**
772 * xmlSchemaPSVIIDCKeySequence:
773 *
774 * The key sequence of a node table item.
775 */
776typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778struct _xmlSchemaPSVIIDCKey {
779 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000780 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000781};
782
783/**
784 * xmlSchemaPSVIIDCNode:
785 *
786 * The node table item of a node table.
787 */
788typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790struct _xmlSchemaPSVIIDCNode {
791 xmlNodePtr node;
792 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000793 int nodeLine;
Daniel Veillarddee23482008-04-11 12:58:43 +0000794 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000795
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000796};
797
798/**
799 * xmlSchemaPSVIIDCBinding:
800 *
801 * The identity-constraint binding item of the [identity-constraint table].
802 */
803typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805struct _xmlSchemaPSVIIDCBinding {
806 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807 xmlSchemaIDCPtr definition; /* the IDC definition */
808 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809 int nbNodes; /* number of entries in the node table */
810 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000811 xmlSchemaItemListPtr dupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000812};
813
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000814
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000815#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
817
818#define XPATH_STATE_OBJ_MATCHES -2
819#define XPATH_STATE_OBJ_BLOCKED -3
820
821typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
823
824/**
825 * xmlSchemaIDCStateObj:
826 *
827 * The state object used to evaluate XPath expressions.
828 */
829typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000832 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000833 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000834 int depth; /* depth of creation */
835 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000836 int nbHistory;
837 int sizeHistory;
838 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839 matcher */
840 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000841 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000842};
843
844#define IDC_MATCHER 0
845
846/**
847 * xmlSchemaIDCMatcher:
848 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000849 * Used to evaluate IDC selectors (and fields).
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000850 */
851struct _xmlSchemaIDCMatcher {
852 int type;
853 int depth; /* the tree depth at creation time */
854 xmlSchemaIDCMatcherPtr next; /* next in the list */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +0000855 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000856 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000857 int idcType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000858 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859 elements */
860 int sizeKeySeqs;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000861 xmlSchemaItemListPtr targets; /* list of target-node
862 (xmlSchemaPSVIIDCNodePtr) entries */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000863};
864
865/*
866* Element info flags.
867*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000868#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
869#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
870#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
871#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
872
873#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
874#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
875#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
876
877#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
878#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
879#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
880#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000881
882/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000883 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000884 *
885 * Holds information of an element node.
886 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000887struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000888 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000889 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000890 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000891 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000892 const xmlChar *nsName;
893 const xmlChar *value;
894 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000895 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000896
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000897 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000898
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000899 int valNeeded;
900 int normVal;
901
902 xmlSchemaElementPtr decl; /* the element/attribute declaration */
903 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000904 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
905 for the scope element*/
906 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
907 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000908 xmlRegExecCtxtPtr regexCtxt;
909
910 const xmlChar **nsBindings; /* Namespace bindings on this element */
911 int nbNsBindings;
Daniel Veillarddee23482008-04-11 12:58:43 +0000912 int sizeNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000913
914 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000915 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000916};
917
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000918#define XML_SCHEMAS_ATTR_UNKNOWN 1
919#define XML_SCHEMAS_ATTR_ASSESSED 2
920#define XML_SCHEMAS_ATTR_PROHIBITED 3
921#define XML_SCHEMAS_ATTR_ERR_MISSING 4
922#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
923#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
924#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
925#define XML_SCHEMAS_ATTR_DEFAULT 8
926#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
927#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
928#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
929#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
930#define XML_SCHEMAS_ATTR_WILD_SKIP 13
931#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
932#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
933#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
934#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000935/*
936* @metaType values of xmlSchemaAttrInfo.
937*/
938#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
939#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
940#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
941#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
942#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000943
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000944typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
945typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
946struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000947 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000948 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000949 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000950 const xmlChar *localName;
951 const xmlChar *nsName;
952 const xmlChar *value;
953 xmlSchemaValPtr val; /* the pre-computed value if any */
954 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
955 int flags; /* combination of node info flags */
956
957 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000958 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000959 int state;
960 int metaType;
961 const xmlChar *vcValue; /* the value constraint value */
962 xmlSchemaNodeInfoPtr parent;
963};
964
965
966#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000967/**
968 * xmlSchemaValidCtxt:
969 *
970 * A Schemas validation context
971 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000972struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000973 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000974 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000975 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000976 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000977 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000978
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000979 xmlSchemaPtr schema; /* The schema in use */
980 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000981 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000982 xmlCharEncoding enc;
983 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000984 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000985 void *user_data; /* TODO: What is this for? */
Daniel Veillard97fa5b32012-08-14 11:01:07 +0800986 char *filename;
Daniel Veillard4255d502002-04-16 15:50:10 +0000987
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000988 int err;
989 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000990
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000991 xmlNodePtr node;
992 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000993 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000994
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000995 xmlRegExecCtxtPtr regexp;
996 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000997
Daniel Veillardc0826a72004-08-10 14:17:33 +0000998 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000999 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001000 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001001 xmlSchemaParserCtxtPtr pctxt;
1002 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001003
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001004 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001005 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001006 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001007 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001008
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001009 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1010
1011 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1012 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +00001013 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001014
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001015 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1016 int nbIdcNodes;
1017 int sizeIdcNodes;
1018
1019 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1020 int nbIdcKeys;
1021 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001022
1023 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001024
1025 xmlDictPtr dict;
1026
Daniel Veillard39e5c892005-07-03 22:48:50 +00001027#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001028 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001029#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001030
1031 xmlSchemaAttrInfoPtr *attrInfos;
1032 int nbAttrInfos;
1033 int sizeAttrInfos;
1034
1035 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001036 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001037 int hasKeyrefs;
1038 int createIDCNodeTables;
1039 int psviExposeIDCNodeTables;
Daniel Veillard97fa5b32012-08-14 11:01:07 +08001040
1041 /* Locator for error reporting in streaming mode */
1042 xmlSchemaValidityLocatorFunc locFunc;
1043 void *locCtxt;
Daniel Veillard4255d502002-04-16 15:50:10 +00001044};
1045
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001046/**
1047 * xmlSchemaSubstGroup:
1048 *
1049 *
1050 */
1051typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1052typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1053struct _xmlSchemaSubstGroup {
1054 xmlSchemaElementPtr head;
1055 xmlSchemaItemListPtr members;
1056};
1057
Daniel Veillard4255d502002-04-16 15:50:10 +00001058/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001059 * *
1060 * Some predeclarations *
1061 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00001062 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001063
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001064static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1065 xmlSchemaPtr schema,
1066 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001067static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1068 xmlSchemaPtr schema,
1069 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001070static int
1071xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001072 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001073static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001074xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1075static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001076xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1077 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001078static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001079xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1080 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001081static void
1082xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001083static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001084xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001085static xmlSchemaTreeItemPtr
1086xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1087 xmlNodePtr node, xmlSchemaTypeType type,
1088 int withParticle);
1089static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001090xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001091static xmlSchemaTypeLinkPtr
1092xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001093static void
1094xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1095 const char *funcName,
David Kilzer4472c3a2016-05-13 15:13:17 +08001096 const char *message) LIBXML_ATTR_FORMAT(3,0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001097static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001098xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001099 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001100 xmlSchemaTypePtr baseType,
1101 int subset);
1102static void
1103xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001104 xmlSchemaParserCtxtPtr ctxt);
1105static void
1106xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001107static xmlSchemaQNameRefPtr
1108xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1109 xmlSchemaPtr schema,
1110 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001111
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001112/************************************************************************
1113 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001114 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001115 * *
1116 ************************************************************************/
1117
1118/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001119 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001120 * @type: the type of the schema item
1121 *
1122 * Returns the component name of a schema item.
1123 */
1124static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001125xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001126{
1127 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001128 case XML_SCHEMA_TYPE_BASIC:
1129 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001130 case XML_SCHEMA_TYPE_SIMPLE:
1131 return(BAD_CAST "simple type definition");
1132 case XML_SCHEMA_TYPE_COMPLEX:
1133 return(BAD_CAST "complex type definition");
1134 case XML_SCHEMA_TYPE_ELEMENT:
1135 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001136 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1137 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001138 case XML_SCHEMA_TYPE_ATTRIBUTE:
1139 return(BAD_CAST "attribute declaration");
1140 case XML_SCHEMA_TYPE_GROUP:
1141 return(BAD_CAST "model group definition");
1142 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1143 return(BAD_CAST "attribute group definition");
1144 case XML_SCHEMA_TYPE_NOTATION:
1145 return(BAD_CAST "notation declaration");
1146 case XML_SCHEMA_TYPE_SEQUENCE:
1147 return(BAD_CAST "model group (sequence)");
1148 case XML_SCHEMA_TYPE_CHOICE:
1149 return(BAD_CAST "model group (choice)");
1150 case XML_SCHEMA_TYPE_ALL:
1151 return(BAD_CAST "model group (all)");
1152 case XML_SCHEMA_TYPE_PARTICLE:
1153 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001154 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001155 return(BAD_CAST "unique identity-constraint");
1156 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001157 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001158 return(BAD_CAST "key identity-constraint");
1159 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001160 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001161 return(BAD_CAST "keyref identity-constraint");
1162 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001163 case XML_SCHEMA_TYPE_ANY:
1164 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001165 case XML_SCHEMA_EXTRA_QNAMEREF:
1166 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001167 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1168 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001169 default:
1170 return(BAD_CAST "Not a schema component");
1171 }
1172}
1173
1174/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001175 * xmlSchemaGetComponentTypeStr:
1176 * @type: the type of the schema item
1177 *
1178 * Returns the component name of a schema item.
1179 */
1180static const xmlChar *
1181xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1182{
1183 switch (item->type) {
1184 case XML_SCHEMA_TYPE_BASIC:
1185 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1186 return(BAD_CAST "complex type definition");
1187 else
Daniel Veillarddee23482008-04-11 12:58:43 +00001188 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001189 default:
1190 return(xmlSchemaItemTypeToStr(item->type));
1191 }
1192}
1193
1194/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001195 * xmlSchemaGetComponentNode:
1196 * @item: a schema component
1197 *
1198 * Returns node associated with the schema component.
1199 * NOTE that such a node need not be available; plus, a component's
1200 * node need not to reflect the component directly, since there is no
1201 * one-to-one relationship between the XML Schema representation and
1202 * the component representation.
1203 */
1204static xmlNodePtr
1205xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1206{
1207 switch (item->type) {
1208 case XML_SCHEMA_TYPE_ELEMENT:
1209 return (((xmlSchemaElementPtr) item)->node);
1210 case XML_SCHEMA_TYPE_ATTRIBUTE:
1211 return (((xmlSchemaAttributePtr) item)->node);
1212 case XML_SCHEMA_TYPE_COMPLEX:
1213 case XML_SCHEMA_TYPE_SIMPLE:
1214 return (((xmlSchemaTypePtr) item)->node);
1215 case XML_SCHEMA_TYPE_ANY:
1216 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1217 return (((xmlSchemaWildcardPtr) item)->node);
1218 case XML_SCHEMA_TYPE_PARTICLE:
1219 return (((xmlSchemaParticlePtr) item)->node);
1220 case XML_SCHEMA_TYPE_SEQUENCE:
1221 case XML_SCHEMA_TYPE_CHOICE:
1222 case XML_SCHEMA_TYPE_ALL:
1223 return (((xmlSchemaModelGroupPtr) item)->node);
1224 case XML_SCHEMA_TYPE_GROUP:
1225 return (((xmlSchemaModelGroupDefPtr) item)->node);
1226 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1227 return (((xmlSchemaAttributeGroupPtr) item)->node);
1228 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1229 case XML_SCHEMA_TYPE_IDC_KEY:
1230 case XML_SCHEMA_TYPE_IDC_KEYREF:
1231 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001232 case XML_SCHEMA_EXTRA_QNAMEREF:
1233 return(((xmlSchemaQNameRefPtr) item)->node);
1234 /* TODO: What to do with NOTATIONs?
1235 case XML_SCHEMA_TYPE_NOTATION:
1236 return (((xmlSchemaNotationPtr) item)->node);
1237 */
1238 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1239 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001240 default:
1241 return (NULL);
1242 }
1243}
1244
1245#if 0
1246/**
1247 * xmlSchemaGetNextComponent:
1248 * @item: a schema component
1249 *
1250 * Returns the next sibling of the schema component.
1251 */
1252static xmlSchemaBasicItemPtr
1253xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1254{
1255 switch (item->type) {
1256 case XML_SCHEMA_TYPE_ELEMENT:
1257 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1258 case XML_SCHEMA_TYPE_ATTRIBUTE:
1259 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1260 case XML_SCHEMA_TYPE_COMPLEX:
1261 case XML_SCHEMA_TYPE_SIMPLE:
1262 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1263 case XML_SCHEMA_TYPE_ANY:
1264 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1265 return (NULL);
1266 case XML_SCHEMA_TYPE_PARTICLE:
1267 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1268 case XML_SCHEMA_TYPE_SEQUENCE:
1269 case XML_SCHEMA_TYPE_CHOICE:
1270 case XML_SCHEMA_TYPE_ALL:
1271 return (NULL);
1272 case XML_SCHEMA_TYPE_GROUP:
1273 return (NULL);
1274 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1275 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1276 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1277 case XML_SCHEMA_TYPE_IDC_KEY:
1278 case XML_SCHEMA_TYPE_IDC_KEYREF:
1279 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1280 default:
1281 return (NULL);
1282 }
1283}
1284#endif
1285
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001286
1287/**
1288 * xmlSchemaFormatQName:
1289 * @buf: the string buffer
1290 * @namespaceName: the namespace name
1291 * @localName: the local name
1292 *
1293 * Returns the given QName in the format "{namespaceName}localName" or
1294 * just "localName" if @namespaceName is NULL.
1295 *
1296 * Returns the localName if @namespaceName is NULL, a formatted
1297 * string otherwise.
1298 */
1299static const xmlChar*
1300xmlSchemaFormatQName(xmlChar **buf,
1301 const xmlChar *namespaceName,
1302 const xmlChar *localName)
1303{
1304 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001305 if (namespaceName != NULL) {
1306 *buf = xmlStrdup(BAD_CAST "{");
1307 *buf = xmlStrcat(*buf, namespaceName);
1308 *buf = xmlStrcat(*buf, BAD_CAST "}");
1309 }
1310 if (localName != NULL) {
1311 if (namespaceName == NULL)
1312 return(localName);
1313 *buf = xmlStrcat(*buf, localName);
1314 } else {
1315 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
Daniel Veillarddee23482008-04-11 12:58:43 +00001316 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001317 return ((const xmlChar *) *buf);
1318}
1319
Daniel Veillarddee23482008-04-11 12:58:43 +00001320static const xmlChar*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001321xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1322{
1323 if (ns != NULL)
1324 return (xmlSchemaFormatQName(buf, ns->href, localName));
1325 else
1326 return (xmlSchemaFormatQName(buf, NULL, localName));
1327}
1328
1329static const xmlChar *
1330xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1331{
1332 switch (item->type) {
1333 case XML_SCHEMA_TYPE_ELEMENT:
1334 return (((xmlSchemaElementPtr) item)->name);
1335 case XML_SCHEMA_TYPE_ATTRIBUTE:
1336 return (((xmlSchemaAttributePtr) item)->name);
1337 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1338 return (((xmlSchemaAttributeGroupPtr) item)->name);
1339 case XML_SCHEMA_TYPE_BASIC:
1340 case XML_SCHEMA_TYPE_SIMPLE:
1341 case XML_SCHEMA_TYPE_COMPLEX:
1342 return (((xmlSchemaTypePtr) item)->name);
1343 case XML_SCHEMA_TYPE_GROUP:
1344 return (((xmlSchemaModelGroupDefPtr) item)->name);
1345 case XML_SCHEMA_TYPE_IDC_KEY:
1346 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1347 case XML_SCHEMA_TYPE_IDC_KEYREF:
1348 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001349 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1350 if (WXS_ATTRUSE_DECL(item) != NULL) {
1351 return(xmlSchemaGetComponentName(
1352 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1353 } else
1354 return(NULL);
1355 case XML_SCHEMA_EXTRA_QNAMEREF:
1356 return (((xmlSchemaQNameRefPtr) item)->name);
1357 case XML_SCHEMA_TYPE_NOTATION:
1358 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001359 default:
1360 /*
1361 * Other components cannot have names.
1362 */
1363 break;
1364 }
1365 return (NULL);
1366}
1367
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001368#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1369#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1370/*
1371static const xmlChar *
1372xmlSchemaGetQNameRefName(void *ref)
1373{
1374 return(((xmlSchemaQNameRefPtr) ref)->name);
1375}
1376
1377static const xmlChar *
1378xmlSchemaGetQNameRefTargetNs(void *ref)
1379{
1380 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1381}
1382*/
1383
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001384static const xmlChar *
1385xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1386{
1387 switch (item->type) {
1388 case XML_SCHEMA_TYPE_ELEMENT:
1389 return (((xmlSchemaElementPtr) item)->targetNamespace);
1390 case XML_SCHEMA_TYPE_ATTRIBUTE:
1391 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1392 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1393 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1394 case XML_SCHEMA_TYPE_BASIC:
1395 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1396 case XML_SCHEMA_TYPE_SIMPLE:
1397 case XML_SCHEMA_TYPE_COMPLEX:
1398 return (((xmlSchemaTypePtr) item)->targetNamespace);
1399 case XML_SCHEMA_TYPE_GROUP:
1400 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1401 case XML_SCHEMA_TYPE_IDC_KEY:
1402 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1403 case XML_SCHEMA_TYPE_IDC_KEYREF:
1404 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001405 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1406 if (WXS_ATTRUSE_DECL(item) != NULL) {
1407 return(xmlSchemaGetComponentTargetNs(
1408 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1409 }
1410 /* TODO: Will returning NULL break something? */
1411 break;
1412 case XML_SCHEMA_EXTRA_QNAMEREF:
1413 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1414 case XML_SCHEMA_TYPE_NOTATION:
1415 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001416 default:
1417 /*
1418 * Other components cannot have names.
1419 */
1420 break;
1421 }
1422 return (NULL);
1423}
1424
1425static const xmlChar*
1426xmlSchemaGetComponentQName(xmlChar **buf,
1427 void *item)
1428{
1429 return (xmlSchemaFormatQName(buf,
1430 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1431 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1432}
1433
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001434static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001435xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001436{
1437 xmlChar *str = NULL;
1438
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001439 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001440 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001441 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1442 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001443 *buf = xmlStrcat(*buf, BAD_CAST "'");
1444 FREE_AND_NULL(str);
1445 return(*buf);
1446}
1447
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001448static const xmlChar*
1449xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1450{
1451 return(xmlSchemaGetComponentDesignation(buf, idc));
1452}
1453
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001454/**
1455 * xmlSchemaWildcardPCToString:
1456 * @pc: the type of processContents
1457 *
1458 * Returns a string representation of the type of
1459 * processContents.
1460 */
1461static const xmlChar *
1462xmlSchemaWildcardPCToString(int pc)
1463{
1464 switch (pc) {
1465 case XML_SCHEMAS_ANY_SKIP:
1466 return (BAD_CAST "skip");
1467 case XML_SCHEMAS_ANY_LAX:
1468 return (BAD_CAST "lax");
1469 case XML_SCHEMAS_ANY_STRICT:
1470 return (BAD_CAST "strict");
1471 default:
1472 return (BAD_CAST "invalid process contents");
1473 }
1474}
1475
1476/**
1477 * xmlSchemaGetCanonValueWhtspExt:
1478 * @val: the precomputed value
1479 * @retValue: the returned value
1480 * @ws: the whitespace type of the value
1481 *
Jan Pokorný7a7cad62013-11-29 23:26:26 +01001482 * Get a the canonical representation of the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001483 * The caller has to free the returned retValue.
1484 *
1485 * Returns 0 if the value could be built and -1 in case of
1486 * API errors or if the value type is not supported yet.
1487 */
1488static int
1489xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1490 xmlSchemaWhitespaceValueType ws,
1491 xmlChar **retValue)
1492{
1493 int list;
1494 xmlSchemaValType valType;
1495 const xmlChar *value, *value2 = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00001496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001497
1498 if ((retValue == NULL) || (val == NULL))
1499 return (-1);
1500 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1501 *retValue = NULL;
1502 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00001503 value = NULL;
1504 valType = xmlSchemaGetValType(val);
1505 switch (valType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001506 case XML_SCHEMAS_STRING:
1507 case XML_SCHEMAS_NORMSTRING:
1508 case XML_SCHEMAS_ANYSIMPLETYPE:
1509 value = xmlSchemaValueGetAsString(val);
1510 if (value != NULL) {
1511 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1512 value2 = xmlSchemaCollapseString(value);
1513 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1514 value2 = xmlSchemaWhiteSpaceReplace(value);
1515 if (value2 != NULL)
1516 value = value2;
1517 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001518 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001519 default:
1520 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1521 if (value2 != NULL)
1522 xmlFree((xmlChar *) value2);
1523 goto internal_error;
1524 }
1525 value = value2;
1526 }
1527 if (*retValue == NULL)
1528 if (value == NULL) {
1529 if (! list)
1530 *retValue = xmlStrdup(BAD_CAST "");
1531 } else
1532 *retValue = xmlStrdup(value);
1533 else if (value != NULL) {
1534 /* List. */
1535 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1536 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1537 }
1538 FREE_AND_NULL(value2)
1539 val = xmlSchemaValueGetNext(val);
1540 } while (val != NULL);
1541
1542 return (0);
1543internal_error:
1544 if (*retValue != NULL)
1545 xmlFree((xmlChar *) (*retValue));
1546 if (value2 != NULL)
1547 xmlFree((xmlChar *) value2);
1548 return (-1);
1549}
1550
1551/**
1552 * xmlSchemaFormatItemForReport:
1553 * @buf: the string buffer
1554 * @itemDes: the designation of the item
1555 * @itemName: the name of the item
Daniel Veillarddee23482008-04-11 12:58:43 +00001556 * @item: the item as an object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001557 * @itemNode: the node of the item
1558 * @local: the local name
1559 * @parsing: if the function is used during the parse
1560 *
1561 * Returns a representation of the given item used
Daniel Veillarddee23482008-04-11 12:58:43 +00001562 * for error reports.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563 *
Daniel Veillarddee23482008-04-11 12:58:43 +00001564 * The following order is used to build the resulting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001565 * designation if the arguments are not NULL:
1566 * 1a. If itemDes not NULL -> itemDes
1567 * 1b. If (itemDes not NULL) and (itemName not NULL)
1568 * -> itemDes + itemName
1569 * 2. If the preceding was NULL and (item not NULL) -> item
1570 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
Daniel Veillarddee23482008-04-11 12:58:43 +00001571 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001572 * If the itemNode is an attribute node, the name of the attribute
1573 * will be appended to the result.
1574 *
1575 * Returns the formatted string and sets @buf to the resulting value.
Daniel Veillarddee23482008-04-11 12:58:43 +00001576 */
1577static xmlChar*
1578xmlSchemaFormatItemForReport(xmlChar **buf,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001579 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001580 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 xmlNodePtr itemNode)
1582{
1583 xmlChar *str = NULL;
1584 int named = 1;
1585
1586 if (*buf != NULL) {
1587 xmlFree(*buf);
1588 *buf = NULL;
1589 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001590
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 if (itemDes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00001592 *buf = xmlStrdup(itemDes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001593 } else if (item != NULL) {
1594 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001595 case XML_SCHEMA_TYPE_BASIC: {
1596 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1597
1598 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001599 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001600 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001602 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001603 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1604 else
1605 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001606 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001607 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001609 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001610 case XML_SCHEMA_TYPE_SIMPLE: {
1611 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1612
1613 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001614 *buf = xmlStrdup(BAD_CAST"");
1615 } else {
1616 *buf = xmlStrdup(BAD_CAST "local ");
1617 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001618 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001619 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001620 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001622 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001623 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1624 else
1625 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001626 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001627 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001628 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001629 *buf = xmlStrcat(*buf, BAD_CAST "'");
1630 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001631 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001632 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001633 case XML_SCHEMA_TYPE_COMPLEX: {
1634 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1635
1636 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001637 *buf = xmlStrdup(BAD_CAST "");
1638 else
1639 *buf = xmlStrdup(BAD_CAST "local ");
1640 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001641 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001642 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001643 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001644 *buf = xmlStrcat(*buf, BAD_CAST "'");
1645 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001646 }
1647 break;
1648 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1649 xmlSchemaAttributeUsePtr ause;
Daniel Veillarddee23482008-04-11 12:58:43 +00001650
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001651 ause = WXS_ATTR_USE_CAST item;
1652 *buf = xmlStrdup(BAD_CAST "attribute use ");
1653 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1654 *buf = xmlStrcat(*buf, BAD_CAST "'");
1655 *buf = xmlStrcat(*buf,
1656 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1657 FREE_AND_NULL(str)
1658 *buf = xmlStrcat(*buf, BAD_CAST "'");
1659 } else {
1660 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1661 }
1662 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001663 break;
1664 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1665 xmlSchemaAttributePtr attr;
Daniel Veillarddee23482008-04-11 12:58:43 +00001666
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001667 attr = (xmlSchemaAttributePtr) item;
1668 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1669 *buf = xmlStrcat(*buf, BAD_CAST " '");
1670 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1671 attr->targetNamespace, attr->name));
1672 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001673 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001674 }
1675 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001676 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1677 xmlSchemaGetComponentDesignation(buf, item);
1678 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001679 case XML_SCHEMA_TYPE_ELEMENT: {
1680 xmlSchemaElementPtr elem;
1681
Daniel Veillarddee23482008-04-11 12:58:43 +00001682 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001683 *buf = xmlStrdup(BAD_CAST "element decl.");
1684 *buf = xmlStrcat(*buf, BAD_CAST " '");
1685 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1686 elem->targetNamespace, elem->name));
1687 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001688 }
1689 break;
1690 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1691 case XML_SCHEMA_TYPE_IDC_KEY:
Daniel Veillarddee23482008-04-11 12:58:43 +00001692 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001693 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1694 *buf = xmlStrdup(BAD_CAST "unique '");
1695 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1696 *buf = xmlStrdup(BAD_CAST "key '");
1697 else
1698 *buf = xmlStrdup(BAD_CAST "keyRef '");
1699 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1700 *buf = xmlStrcat(*buf, BAD_CAST "'");
1701 break;
1702 case XML_SCHEMA_TYPE_ANY:
1703 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1704 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1705 ((xmlSchemaWildcardPtr) item)->processContents));
1706 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1707 break;
1708 case XML_SCHEMA_FACET_MININCLUSIVE:
1709 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1710 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1711 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1712 case XML_SCHEMA_FACET_TOTALDIGITS:
1713 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1714 case XML_SCHEMA_FACET_PATTERN:
1715 case XML_SCHEMA_FACET_ENUMERATION:
1716 case XML_SCHEMA_FACET_WHITESPACE:
1717 case XML_SCHEMA_FACET_LENGTH:
1718 case XML_SCHEMA_FACET_MAXLENGTH:
1719 case XML_SCHEMA_FACET_MINLENGTH:
1720 *buf = xmlStrdup(BAD_CAST "facet '");
1721 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1722 *buf = xmlStrcat(*buf, BAD_CAST "'");
1723 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001724 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001725 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001726 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001727 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001728 *buf = xmlStrcat(*buf, BAD_CAST "'");
1729 FREE_AND_NULL(str)
1730 }
1731 break;
1732 case XML_SCHEMA_TYPE_SEQUENCE:
1733 case XML_SCHEMA_TYPE_CHOICE:
1734 case XML_SCHEMA_TYPE_ALL:
1735 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001736 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1737 break;
1738 case XML_SCHEMA_TYPE_NOTATION: {
1739 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1740 *buf = xmlStrcat(*buf, BAD_CAST " '");
1741 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1742 *buf = xmlStrcat(*buf, BAD_CAST "'");
1743 FREE_AND_NULL(str);
1744 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001745 default:
1746 named = 0;
1747 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001748 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001749 named = 0;
1750
1751 if ((named == 0) && (itemNode != NULL)) {
1752 xmlNodePtr elem;
1753
1754 if (itemNode->type == XML_ATTRIBUTE_NODE)
1755 elem = itemNode->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00001756 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001757 elem = itemNode;
1758 *buf = xmlStrdup(BAD_CAST "Element '");
1759 if (elem->ns != NULL) {
1760 *buf = xmlStrcat(*buf,
1761 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1762 FREE_AND_NULL(str)
1763 } else
1764 *buf = xmlStrcat(*buf, elem->name);
1765 *buf = xmlStrcat(*buf, BAD_CAST "'");
Daniel Veillarddee23482008-04-11 12:58:43 +00001766
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001767 }
1768 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1769 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1770 if (itemNode->ns != NULL) {
1771 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1772 itemNode->ns->href, itemNode->name));
1773 FREE_AND_NULL(str)
1774 } else
1775 *buf = xmlStrcat(*buf, itemNode->name);
1776 *buf = xmlStrcat(*buf, BAD_CAST "'");
1777 }
1778 FREE_AND_NULL(str)
Daniel Veillarddee23482008-04-11 12:58:43 +00001779
David Kilzer502f6a62016-05-23 14:58:41 +08001780 return (xmlEscapeFormatString(buf));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001781}
1782
1783/**
1784 * xmlSchemaFormatFacetEnumSet:
1785 * @buf: the string buffer
1786 * @type: the type holding the enumeration facets
1787 *
1788 * Builds a string consisting of all enumeration elements.
1789 *
1790 * Returns a string of all enumeration elements.
1791 */
1792static const xmlChar *
1793xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1794 xmlChar **buf, xmlSchemaTypePtr type)
1795{
1796 xmlSchemaFacetPtr facet;
1797 xmlSchemaWhitespaceValueType ws;
1798 xmlChar *value = NULL;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001799 int res, found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001800
1801 if (*buf != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00001802 xmlFree(*buf);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001803 *buf = NULL;
1804
1805 do {
1806 /*
1807 * Use the whitespace type of the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +00001808 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001809 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1810 for (facet = type->facets; facet != NULL; facet = facet->next) {
1811 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1812 continue;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001813 found = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001814 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1815 ws, &value);
1816 if (res == -1) {
1817 xmlSchemaInternalErr(actxt,
1818 "xmlSchemaFormatFacetEnumSet",
1819 "compute the canonical lexical representation");
1820 if (*buf != NULL)
1821 xmlFree(*buf);
1822 *buf = NULL;
1823 return (NULL);
1824 }
1825 if (*buf == NULL)
1826 *buf = xmlStrdup(BAD_CAST "'");
1827 else
1828 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1829 *buf = xmlStrcat(*buf, BAD_CAST value);
1830 *buf = xmlStrcat(*buf, BAD_CAST "'");
1831 if (value != NULL) {
1832 xmlFree((xmlChar *)value);
1833 value = NULL;
1834 }
1835 }
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001836 /*
1837 * The enumeration facet of a type restricts the enumeration
1838 * facet of the ancestor type; i.e., such restricted enumerations
1839 * do not belong to the set of the given type. Thus we break
1840 * on the first found enumeration.
1841 */
1842 if (found)
1843 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001844 type = type->baseType;
1845 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1846
1847 return ((const xmlChar *) *buf);
1848}
1849
1850/************************************************************************
1851 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001852 * Error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853 * *
1854 ************************************************************************/
1855
1856#if 0
1857static void
1858xmlSchemaErrMemory(const char *msg)
1859{
1860 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1861 msg);
1862}
1863#endif
1864
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001865static void
1866xmlSchemaPSimpleErr(const char *msg)
1867{
1868 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1869 msg);
1870}
1871
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001872/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001873 * xmlSchemaPErrMemory:
1874 * @node: a context node
1875 * @extra: extra informations
1876 *
1877 * Handle an out of memory condition
1878 */
1879static void
1880xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1881 const char *extra, xmlNodePtr node)
1882{
1883 if (ctxt != NULL)
1884 ctxt->nberrors++;
1885 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1886 extra);
1887}
1888
1889/**
1890 * xmlSchemaPErr:
1891 * @ctxt: the parsing context
1892 * @node: the context node
1893 * @error: the error code
1894 * @msg: the error message
1895 * @str1: extra data
1896 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001897 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001898 * Handle a parser error
1899 */
David Kilzer4472c3a2016-05-13 15:13:17 +08001900static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001901xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1902 const char *msg, const xmlChar * str1, const xmlChar * str2)
1903{
1904 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001905 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001906 void *data = NULL;
1907
1908 if (ctxt != NULL) {
1909 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001910 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001911 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001912 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001913 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001915 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001916 error, XML_ERR_ERROR, NULL, 0,
1917 (const char *) str1, (const char *) str2, NULL, 0, 0,
1918 msg, str1, str2);
1919}
1920
1921/**
1922 * xmlSchemaPErr2:
1923 * @ctxt: the parsing context
1924 * @node: the context node
1925 * @node: the current child
1926 * @error: the error code
1927 * @msg: the error message
1928 * @str1: extra data
1929 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001930 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001931 * Handle a parser error
1932 */
David Kilzer4472c3a2016-05-13 15:13:17 +08001933static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001934xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1935 xmlNodePtr child, int error,
1936 const char *msg, const xmlChar * str1, const xmlChar * str2)
1937{
1938 if (child != NULL)
1939 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1940 else
1941 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1942}
1943
Daniel Veillard01fa6152004-06-29 17:04:39 +00001944
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001946 * xmlSchemaPErrExt:
1947 * @ctxt: the parsing context
1948 * @node: the context node
Daniel Veillarddee23482008-04-11 12:58:43 +00001949 * @error: the error code
Daniel Veillard3646d642004-06-02 19:19:14 +00001950 * @strData1: extra data
1951 * @strData2: extra data
1952 * @strData3: extra data
1953 * @msg: the message
1954 * @str1: extra parameter for the message display
1955 * @str2: extra parameter for the message display
1956 * @str3: extra parameter for the message display
1957 * @str4: extra parameter for the message display
1958 * @str5: extra parameter for the message display
Daniel Veillarddee23482008-04-11 12:58:43 +00001959 *
Daniel Veillard3646d642004-06-02 19:19:14 +00001960 * Handle a parser error
1961 */
David Kilzer4472c3a2016-05-13 15:13:17 +08001962static void LIBXML_ATTR_FORMAT(7,0)
Daniel Veillard3646d642004-06-02 19:19:14 +00001963xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
Daniel Veillarddee23482008-04-11 12:58:43 +00001964 const xmlChar * strData1, const xmlChar * strData2,
1965 const xmlChar * strData3, const char *msg, const xmlChar * str1,
Daniel Veillard3646d642004-06-02 19:19:14 +00001966 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1967 const xmlChar * str5)
1968{
1969
1970 xmlGenericErrorFunc channel = NULL;
1971 xmlStructuredErrorFunc schannel = NULL;
1972 void *data = NULL;
1973
1974 if (ctxt != NULL) {
1975 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001976 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00001977 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001978 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00001979 schannel = ctxt->serror;
1980 }
1981 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1982 error, XML_ERR_ERROR, NULL, 0,
Daniel Veillarddee23482008-04-11 12:58:43 +00001983 (const char *) strData1, (const char *) strData2,
1984 (const char *) strData3, 0, 0, msg, str1, str2,
William M. Brack803812b2004-06-03 02:11:24 +00001985 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001986}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001987
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001988/************************************************************************
1989 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001990 * Allround error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001991 * *
1992 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001993
1994/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001995 * xmlSchemaVTypeErrMemory:
1996 * @node: a context node
1997 * @extra: extra informations
1998 *
1999 * Handle an out of memory condition
2000 */
2001static void
2002xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2003 const char *extra, xmlNodePtr node)
2004{
2005 if (ctxt != NULL) {
2006 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002007 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002008 }
2009 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2010 extra);
2011}
2012
David Kilzer4472c3a2016-05-13 15:13:17 +08002013static void LIBXML_ATTR_FORMAT(2,0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002014xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2015 const char *msg, const xmlChar *str)
2016{
2017 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2018 msg, (const char *) str);
2019}
2020
2021#define WXS_ERROR_TYPE_ERROR 1
2022#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002023/**
David Kilzer4472c3a2016-05-13 15:13:17 +08002024 * xmlSchemaErr4Line:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002025 * @ctxt: the validation context
David Kilzer4472c3a2016-05-13 15:13:17 +08002026 * @errorLevel: the error level
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002027 * @error: the error code
David Kilzer4472c3a2016-05-13 15:13:17 +08002028 * @node: the context node
2029 * @line: the line number
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002030 * @msg: the error message
2031 * @str1: extra data
2032 * @str2: extra data
2033 * @str3: extra data
David Kilzer4472c3a2016-05-13 15:13:17 +08002034 * @str4: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002035 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002036 * Handle a validation error
2037 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002038static void LIBXML_ATTR_FORMAT(6,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002039xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002040 xmlErrorLevel errorLevel,
2041 int error, xmlNodePtr node, int line, const char *msg,
2042 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002043 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002044{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002045 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002046 xmlGenericErrorFunc channel = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002047 void *data = NULL;
2048
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002049 if (ctxt != NULL) {
2050 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2051 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002052 const char *file = NULL;
Juergen Keild201e712014-08-07 11:42:07 +08002053 int col = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002054 if (errorLevel != XML_ERR_WARNING) {
2055 vctxt->nberrors++;
2056 vctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002057 channel = vctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002058 } else {
2059 channel = vctxt->warning;
2060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002061 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002062 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002063
2064 /*
2065 * Error node. If we specify a line number, then
2066 * do not channel any node to the error function.
2067 */
2068 if (line == 0) {
2069 if ((node == NULL) &&
2070 (vctxt->depth >= 0) &&
2071 (vctxt->inode != NULL)) {
2072 node = vctxt->inode->node;
2073 }
2074 /*
2075 * Get filename and line if no node-tree.
2076 */
2077 if ((node == NULL) &&
2078 (vctxt->parserCtxt != NULL) &&
2079 (vctxt->parserCtxt->input != NULL)) {
2080 file = vctxt->parserCtxt->input->filename;
2081 line = vctxt->parserCtxt->input->line;
Juergen Keild201e712014-08-07 11:42:07 +08002082 col = vctxt->parserCtxt->input->col;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002083 }
2084 } else {
2085 /*
2086 * Override the given node's (if any) position
2087 * and channel only the given line number.
2088 */
2089 node = NULL;
2090 /*
2091 * Get filename.
2092 */
2093 if (vctxt->doc != NULL)
2094 file = (const char *) vctxt->doc->URL;
2095 else if ((vctxt->parserCtxt != NULL) &&
2096 (vctxt->parserCtxt->input != NULL))
2097 file = vctxt->parserCtxt->input->filename;
Daniel Veillarddee23482008-04-11 12:58:43 +00002098 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08002099 if (vctxt->locFunc != NULL) {
2100 if ((file == NULL) || (line == 0)) {
2101 unsigned long l;
2102 const char *f;
2103 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2104 if (file == NULL)
2105 file = f;
2106 if (line == 0)
2107 line = (int) l;
2108 }
2109 }
2110 if ((file == NULL) && (vctxt->filename != NULL))
2111 file = vctxt->filename;
2112
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002113 __xmlRaiseError(schannel, channel, data, ctxt,
2114 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002115 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002116 (const char *) str1, (const char *) str2,
Juergen Keild201e712014-08-07 11:42:07 +08002117 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002118
2119 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2120 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002121 if (errorLevel != XML_ERR_WARNING) {
2122 pctxt->nberrors++;
2123 pctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002124 channel = pctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002125 } else {
2126 channel = pctxt->warning;
2127 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002129 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002131 node, XML_FROM_SCHEMASP, error,
2132 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002133 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002134 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002135 } else {
2136 TODO
2137 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002138 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002139}
2140
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002141/**
2142 * xmlSchemaErr3:
2143 * @ctxt: the validation context
2144 * @node: the context node
2145 * @error: the error code
2146 * @msg: the error message
2147 * @str1: extra data
2148 * @str2: extra data
2149 * @str3: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002150 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002151 * Handle a validation error
2152 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002153static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00002154xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002155 int error, xmlNodePtr node, const char *msg,
2156 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2157{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002158 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2159 msg, str1, str2, str3, NULL);
2160}
2161
David Kilzer4472c3a2016-05-13 15:13:17 +08002162static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00002163xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002164 int error, xmlNodePtr node, const char *msg,
2165 const xmlChar *str1, const xmlChar *str2,
2166 const xmlChar *str3, const xmlChar *str4)
2167{
2168 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2169 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002170}
2171
David Kilzer4472c3a2016-05-13 15:13:17 +08002172static void LIBXML_ATTR_FORMAT(4,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002173xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2174 int error, xmlNodePtr node, const char *msg,
2175 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002176{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002177 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002178}
2179
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002180static xmlChar *
2181xmlSchemaFormatNodeForError(xmlChar ** msg,
2182 xmlSchemaAbstractCtxtPtr actxt,
2183 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002184{
2185 xmlChar *str = NULL;
2186
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002187 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002188 if ((node != NULL) &&
2189 (node->type != XML_ELEMENT_NODE) &&
2190 (node->type != XML_ATTRIBUTE_NODE))
2191 {
Daniel Veillarddee23482008-04-11 12:58:43 +00002192 /*
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002193 * Don't try to format other nodes than element and
2194 * attribute nodes.
David Kilzer4472c3a2016-05-13 15:13:17 +08002195 * Play safe and return an empty string.
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002196 */
2197 *msg = xmlStrdup(BAD_CAST "");
2198 return(*msg);
2199 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002200 if (node != NULL) {
2201 /*
2202 * Work on tree nodes.
2203 */
2204 if (node->type == XML_ATTRIBUTE_NODE) {
2205 xmlNodePtr elem = node->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00002206
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002207 *msg = xmlStrdup(BAD_CAST "Element '");
2208 if (elem->ns != NULL)
2209 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2210 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002211 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002212 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2213 NULL, elem->name));
2214 FREE_AND_NULL(str);
2215 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002216 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 } else {
2218 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002219 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 if (node->ns != NULL)
2221 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2222 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002223 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2225 NULL, node->name));
2226 FREE_AND_NULL(str);
2227 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2228 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2229 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2230 /*
2231 * Work on node infos.
Daniel Veillarddee23482008-04-11 12:58:43 +00002232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002233 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2234 xmlSchemaNodeInfoPtr ielem =
2235 vctxt->elemInfos[vctxt->depth];
2236
2237 *msg = xmlStrdup(BAD_CAST "Element '");
2238 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2239 ielem->nsName, ielem->localName));
2240 FREE_AND_NULL(str);
2241 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002242 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002243 } else {
2244 *msg = xmlStrdup(BAD_CAST "Element '");
2245 }
2246 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2247 vctxt->inode->nsName, vctxt->inode->localName));
2248 FREE_AND_NULL(str);
2249 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002250 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
Daniel Veillarddee23482008-04-11 12:58:43 +00002251 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002252 * Hmm, no node while parsing?
2253 * Return an empty string, in case NULL will break something.
2254 */
2255 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 } else {
2257 TODO
2258 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002259 }
David Kilzer502f6a62016-05-23 14:58:41 +08002260
2261 /*
2262 * xmlSchemaFormatItemForReport() also returns an escaped format
2263 * string, so do this before calling it below (in the future).
2264 */
2265 xmlEscapeFormatString(msg);
2266
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 /*
2268 * VAL TODO: The output of the given schema component is currently
2269 * disabled.
2270 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002271#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002272 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2273 *msg = xmlStrcat(*msg, BAD_CAST " [");
2274 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2275 NULL, type, NULL, 0));
2276 FREE_AND_NULL(str)
2277 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002278 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002279#endif
2280 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002281}
2282
David Kilzer4472c3a2016-05-13 15:13:17 +08002283static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002284xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002285 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002286 const char *message,
2287 const xmlChar *str1,
2288 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002289{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002290 xmlChar *msg = NULL;
2291
Daniel Veillard14b56432006-03-09 18:41:40 +00002292 if (actxt == NULL)
2293 return;
David Kilzer4472c3a2016-05-13 15:13:17 +08002294 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 msg = xmlStrcat(msg, BAD_CAST message);
2296 msg = xmlStrcat(msg, BAD_CAST ".\n");
2297
2298 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
David Kilzer4472c3a2016-05-13 15:13:17 +08002299 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2300 (const char *) msg, (const xmlChar *) funcName, str1, str2);
Daniel Veillarddee23482008-04-11 12:58:43 +00002301 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
David Kilzer4472c3a2016-05-13 15:13:17 +08002302 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2303 (const char *) msg, (const xmlChar *) funcName, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002304
2305 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306}
2307
David Kilzer4472c3a2016-05-13 15:13:17 +08002308static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002309xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2310 const char *funcName,
2311 const char *message)
2312{
2313 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2314}
2315
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002316#if 0
David Kilzer4472c3a2016-05-13 15:13:17 +08002317static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002318xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2319 const char *funcName,
2320 const char *message,
2321 const xmlChar *str1,
2322 const xmlChar *str2)
2323{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002324 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002325 str1, str2);
2326}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002327#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002328
David Kilzer4472c3a2016-05-13 15:13:17 +08002329static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002330xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2331 xmlParserErrors error,
2332 xmlNodePtr node,
2333 xmlSchemaBasicItemPtr item,
2334 const char *message,
2335 const xmlChar *str1, const xmlChar *str2,
2336 const xmlChar *str3, const xmlChar *str4)
2337{
2338 xmlChar *msg = NULL;
2339
2340 if ((node == NULL) && (item != NULL) &&
2341 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2342 node = WXS_ITEM_NODE(item);
2343 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2344 msg = xmlStrcat(msg, BAD_CAST ": ");
2345 } else
2346 xmlSchemaFormatNodeForError(&msg, actxt, node);
2347 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002348 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002349 xmlSchemaErr4(actxt, error, node,
2350 (const char *) msg, str1, str2, str3, str4);
2351 FREE_AND_NULL(msg)
2352}
2353
David Kilzer4472c3a2016-05-13 15:13:17 +08002354static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002355xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2356 xmlParserErrors error,
2357 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002358 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002359 const char *message,
2360 const xmlChar *str1,
2361 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002362{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002363 xmlSchemaCustomErr4(actxt, error, node, item,
Daniel Veillarddee23482008-04-11 12:58:43 +00002364 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002365}
2366
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002367
2368
David Kilzer4472c3a2016-05-13 15:13:17 +08002369static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002370xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2371 xmlParserErrors error,
2372 xmlNodePtr node,
2373 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2374 const char *message,
2375 const xmlChar *str1,
2376 const xmlChar *str2,
2377 const xmlChar *str3)
2378{
2379 xmlChar *msg = NULL;
2380
2381 xmlSchemaFormatNodeForError(&msg, actxt, node);
2382 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002383 msg = xmlStrcat(msg, BAD_CAST ".\n");
2384
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002385 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002386 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2387 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002388
2389 FREE_AND_NULL(msg)
2390}
2391
2392
2393
David Kilzer4472c3a2016-05-13 15:13:17 +08002394static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002395xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2396 xmlParserErrors error,
2397 xmlSchemaPSVIIDCNodePtr idcNode,
2398 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2399 const char *message,
2400 const xmlChar *str1,
2401 const xmlChar *str2)
2402{
2403 xmlChar *msg = NULL, *qname = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002404
2405 msg = xmlStrdup(BAD_CAST "Element '%s': ");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002406 msg = xmlStrcat(msg, (const xmlChar *) message);
2407 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002408 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002409 error, NULL, idcNode->nodeLine, (const char *) msg,
2410 xmlSchemaFormatQName(&qname,
2411 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
Daniel Veillarddee23482008-04-11 12:58:43 +00002412 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002413 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002414 FREE_AND_NULL(qname);
2415 FREE_AND_NULL(msg);
2416}
2417
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002418static int
2419xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2420 xmlNodePtr node)
2421{
2422 if (node != NULL)
2423 return (node->type);
2424 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2425 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2426 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2427 return (-1);
2428}
2429
2430static int
2431xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2432{
2433 switch (item->type) {
2434 case XML_SCHEMA_TYPE_COMPLEX:
2435 case XML_SCHEMA_TYPE_SIMPLE:
2436 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2437 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002438 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 case XML_SCHEMA_TYPE_GROUP:
2440 return (1);
2441 case XML_SCHEMA_TYPE_ELEMENT:
2442 if ( ((xmlSchemaElementPtr) item)->flags &
2443 XML_SCHEMAS_ELEM_GLOBAL)
2444 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002445 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002446 case XML_SCHEMA_TYPE_ATTRIBUTE:
2447 if ( ((xmlSchemaAttributePtr) item)->flags &
2448 XML_SCHEMAS_ATTR_GLOBAL)
2449 return(1);
2450 break;
2451 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002452 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002453 return(1);
2454 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002455 return (0);
2456}
2457
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458static void
2459xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2460 xmlParserErrors error,
2461 xmlNodePtr node,
2462 const xmlChar *value,
2463 xmlSchemaTypePtr type,
2464 int displayValue)
2465{
2466 xmlChar *msg = NULL;
2467
2468 xmlSchemaFormatNodeForError(&msg, actxt, node);
2469
2470 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2471 XML_ATTRIBUTE_NODE))
2472 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2473 else
2474 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2475 "value of ");
2476
2477 if (! xmlSchemaIsGlobalItem(type))
2478 msg = xmlStrcat(msg, BAD_CAST "the local ");
2479 else
2480 msg = xmlStrcat(msg, BAD_CAST "the ");
2481
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002482 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002483 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002484 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002486 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002487 msg = xmlStrcat(msg, BAD_CAST "union type");
2488
2489 if (xmlSchemaIsGlobalItem(type)) {
2490 xmlChar *str = NULL;
2491 msg = xmlStrcat(msg, BAD_CAST " '");
2492 if (type->builtInType != 0) {
2493 msg = xmlStrcat(msg, BAD_CAST "xs:");
David Kilzer502f6a62016-05-23 14:58:41 +08002494 str = xmlStrdup(type->name);
2495 } else {
2496 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2497 if (!str)
2498 str = xmlStrdup(qName);
2499 }
2500 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002501 msg = xmlStrcat(msg, BAD_CAST "'");
2502 FREE_AND_NULL(str);
2503 }
2504 msg = xmlStrcat(msg, BAD_CAST ".\n");
2505 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2506 XML_ATTRIBUTE_NODE))
2507 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2508 else
2509 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2510 FREE_AND_NULL(msg)
2511}
2512
Daniel Veillardc0826a72004-08-10 14:17:33 +00002513static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002514xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2515 xmlSchemaNodeInfoPtr ni,
2516 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002517{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002518 if (node != NULL) {
2519 if (node->ns != NULL)
2520 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2521 else
2522 return (xmlSchemaFormatQName(str, NULL, node->name));
2523 } else if (ni != NULL)
2524 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2525 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526}
2527
Daniel Veillardc0826a72004-08-10 14:17:33 +00002528static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002529xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2530 xmlParserErrors error,
2531 xmlSchemaAttrInfoPtr ni,
2532 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002533{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002534 xmlChar *msg = NULL, *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002535
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaFormatNodeForError(&msg, actxt, node);
2537 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2538 xmlSchemaErr(actxt, error, node, (const char *) msg,
2539 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
Daniel Veillarddee23482008-04-11 12:58:43 +00002540 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002541 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002542 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002543}
2544
David Kilzer4472c3a2016-05-13 15:13:17 +08002545static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002546xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2547 xmlParserErrors error,
2548 xmlNodePtr node,
2549 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002550 const char *message,
2551 int nbval,
2552 int nbneg,
2553 xmlChar **values)
2554{
2555 xmlChar *str = NULL, *msg = NULL;
2556 xmlChar *localName, *nsName;
2557 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002558 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00002559
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002560 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002561 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002562 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002563 /*
2564 * Note that is does not make sense to report that we have a
2565 * wildcard here, since the wildcard might be unfolded into
2566 * multiple transitions.
2567 */
2568 if (nbval + nbneg > 0) {
2569 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002570 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002571 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002572 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002573 nsName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002574
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002575 for (i = 0; i < nbval + nbneg; i++) {
2576 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002577 if (cur == NULL)
2578 continue;
2579 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2580 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002581 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002582 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002583 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002584 /*
2585 * Get the local name.
2586 */
2587 localName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002588
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002589 end = cur;
2590 if (*end == '*') {
2591 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002592 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002593 } else {
2594 while ((*end != 0) && (*end != '|'))
2595 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002596 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Daniel Veillarddee23482008-04-11 12:58:43 +00002597 }
2598 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002599 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002600 /*
2601 * Skip "*|*" if they come with negated expressions, since
2602 * they represent the same negated wildcard.
2603 */
2604 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2605 /*
2606 * Get the namespace name.
2607 */
2608 cur = end;
2609 if (*end == '*') {
2610 nsName = xmlStrdup(BAD_CAST "{*}");
2611 } else {
2612 while (*end != 0)
2613 end++;
Daniel Veillarddee23482008-04-11 12:58:43 +00002614
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002615 if (i >= nbval)
2616 nsName = xmlStrdup(BAD_CAST "{##other:");
2617 else
2618 nsName = xmlStrdup(BAD_CAST "{");
Daniel Veillarddee23482008-04-11 12:58:43 +00002619
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002620 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2621 nsName = xmlStrcat(nsName, BAD_CAST "}");
2622 }
2623 str = xmlStrcat(str, BAD_CAST nsName);
2624 FREE_AND_NULL(nsName)
2625 } else {
2626 FREE_AND_NULL(localName);
2627 continue;
2628 }
Daniel Veillarddee23482008-04-11 12:58:43 +00002629 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002630 str = xmlStrcat(str, BAD_CAST localName);
2631 FREE_AND_NULL(localName);
Daniel Veillarddee23482008-04-11 12:58:43 +00002632
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002633 if (i < nbval + nbneg -1)
2634 str = xmlStrcat(str, BAD_CAST ", ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002635 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002636 str = xmlStrcat(str, BAD_CAST " ).\n");
David Kilzer502f6a62016-05-23 14:58:41 +08002637 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002638 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002639 } else
2640 msg = xmlStrcat(msg, BAD_CAST "\n");
2641 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002642 xmlFree(msg);
2643}
2644
David Kilzer4472c3a2016-05-13 15:13:17 +08002645static void LIBXML_ATTR_FORMAT(8,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002646xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2647 xmlParserErrors error,
2648 xmlNodePtr node,
2649 const xmlChar *value,
2650 unsigned long length,
2651 xmlSchemaTypePtr type,
2652 xmlSchemaFacetPtr facet,
2653 const char *message,
2654 const xmlChar *str1,
2655 const xmlChar *str2)
2656{
2657 xmlChar *str = NULL, *msg = NULL;
2658 xmlSchemaTypeType facetType;
2659 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2660
2661 xmlSchemaFormatNodeForError(&msg, actxt, node);
2662 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2663 facetType = XML_SCHEMA_FACET_ENUMERATION;
2664 /*
2665 * If enumerations are validated, one must not expect the
2666 * facet to be given.
Daniel Veillarddee23482008-04-11 12:58:43 +00002667 */
2668 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002669 facetType = facet->type;
2670 msg = xmlStrcat(msg, BAD_CAST "[");
2671 msg = xmlStrcat(msg, BAD_CAST "facet '");
2672 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2673 msg = xmlStrcat(msg, BAD_CAST "'] ");
2674 if (message == NULL) {
2675 /*
2676 * Use a default message.
2677 */
2678 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2679 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2680 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2681
2682 char len[25], actLen[25];
2683
2684 /* FIXME, TODO: What is the max expected string length of the
2685 * this value?
2686 */
2687 if (nodeType == XML_ATTRIBUTE_NODE)
2688 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2689 else
2690 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2691
2692 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2693 snprintf(actLen, 24, "%lu", length);
2694
2695 if (facetType == XML_SCHEMA_FACET_LENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002696 msg = xmlStrcat(msg,
2697 BAD_CAST "this differs from the allowed length of '%s'.\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002698 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002699 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002700 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2701 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002702 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002703 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002704
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002705 if (nodeType == XML_ATTRIBUTE_NODE)
2706 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2707 value, (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002708 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002709 xmlSchemaErr(actxt, error, node, (const char *) msg,
2710 (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002711
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002712 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2713 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2714 "of the set {%s}.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002715 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002716 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2717 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2718 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2719 "by the pattern '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002720 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002721 facet->value);
2722 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2723 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2724 "minimum value allowed ('%s').\n");
2725 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2726 facet->value);
2727 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2728 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2729 "maximum value allowed ('%s').\n");
2730 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2731 facet->value);
2732 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002733 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002734 "'%s'.\n");
2735 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2736 facet->value);
2737 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002738 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002739 "'%s'.\n");
2740 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2741 facet->value);
2742 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2743 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2744 "digits than are allowed ('%s').\n");
2745 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2746 facet->value);
2747 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2748 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2749 "digits than are allowed ('%s').\n");
2750 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2751 facet->value);
Daniel Veillarddee23482008-04-11 12:58:43 +00002752 } else if (nodeType == XML_ATTRIBUTE_NODE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002753 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002754 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2755 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002756 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2757 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2758 }
2759 } else {
2760 msg = xmlStrcat(msg, (const xmlChar *) message);
2761 msg = xmlStrcat(msg, BAD_CAST ".\n");
2762 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
Daniel Veillarddee23482008-04-11 12:58:43 +00002763 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002764 FREE_AND_NULL(str)
2765 xmlFree(msg);
2766}
2767
2768#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002769 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002770
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002771#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002772
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002773#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2774#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775
2776#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2777
2778
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002779/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002780 * xmlSchemaPMissingAttrErr:
2781 * @ctxt: the schema validation context
2782 * @ownerDes: the designation of the owner
2783 * @ownerName: the name of the owner
2784 * @ownerItem: the owner as a schema object
2785 * @ownerElem: the owner as an element node
2786 * @node: the parent element node of the missing attribute node
2787 * @type: the corresponding type of the attribute node
2788 *
2789 * Reports an illegal attribute.
2790 */
2791static void
2792xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002794 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002795 xmlNodePtr ownerElem,
2796 const char *name,
2797 const char *message)
2798{
2799 xmlChar *des = NULL;
2800
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002801 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2802
Daniel Veillardc0826a72004-08-10 14:17:33 +00002803 if (message != NULL)
2804 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002805 else
2806 xmlSchemaPErr(ctxt, ownerElem, error,
2807 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002808 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002809 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002810}
2811
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002812
Daniel Veillardc0826a72004-08-10 14:17:33 +00002813/**
2814 * xmlSchemaPResCompAttrErr:
2815 * @ctxt: the schema validation context
2816 * @error: the error code
2817 * @ownerDes: the designation of the owner
2818 * @ownerItem: the owner as a schema object
2819 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002820 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002821 * @refName: the referenced local name
2822 * @refURI: the referenced namespace URI
2823 * @message: optional message
2824 *
2825 * Used to report QName attribute values that failed to resolve
2826 * to schema components.
2827 */
2828static void
2829xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002830 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002831 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002832 xmlNodePtr ownerElem,
2833 const char *name,
2834 const xmlChar *refName,
2835 const xmlChar *refURI,
2836 xmlSchemaTypeType refType,
2837 const char *refTypeStr)
2838{
2839 xmlChar *des = NULL, *strA = NULL;
2840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002841 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002842 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002843 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002844 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002845 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002846 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2847 "%s.\n", BAD_CAST des, BAD_CAST name,
2848 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002849 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002850 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002851 FREE_AND_NULL(strA)
2852}
2853
William M. Brack2f2a6632004-08-20 23:09:47 +00002854/**
2855 * xmlSchemaPCustomAttrErr:
2856 * @ctxt: the schema parser context
2857 * @error: the error code
2858 * @ownerDes: the designation of the owner
2859 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002860 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002861 *
2862 * Reports an illegal attribute during the parse.
2863 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002864static void
2865xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002866 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002867 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002868 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002869 xmlAttrPtr attr,
2870 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002871{
2872 xmlChar *des = NULL;
2873
2874 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002875 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002876 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002877 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002878 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002879 } else
2880 des = *ownerDes;
Daniel Veillard14b56432006-03-09 18:41:40 +00002881 if (attr == NULL) {
2882 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2883 "%s, attribute '%s': %s.\n",
Daniel Veillardaac7c682006-03-10 13:40:16 +00002884 BAD_CAST des, (const xmlChar *) "Unknown",
2885 (const xmlChar *) msg, NULL, NULL);
Daniel Veillard14b56432006-03-09 18:41:40 +00002886 } else {
2887 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2888 "%s, attribute '%s': %s.\n",
2889 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2890 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002891 if (ownerDes == NULL)
2892 FREE_AND_NULL(des);
2893}
2894
2895/**
2896 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002897 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002898 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002899 * @ownerDes: the designation of the attribute's owner
2900 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002901 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002902 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002903 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002904 */
2905static void
2906xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002907 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002908 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002909 xmlAttrPtr attr)
2910{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002911 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002912
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002913 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2914 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2915 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2916 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2917 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002918 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002919 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002920}
2921
William M. Brack2f2a6632004-08-20 23:09:47 +00002922/**
2923 * xmlSchemaPCustomErr:
2924 * @ctxt: the schema parser context
2925 * @error: the error code
2926 * @itemDes: the designation of the schema item
2927 * @item: the schema item
2928 * @itemElem: the node of the schema item
2929 * @message: the error message
2930 * @str1: an optional param for the error message
2931 * @str2: an optional param for the error message
2932 * @str3: an optional param for the error message
2933 *
2934 * Reports an error during parsing.
2935 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002936static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002937xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002938 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002939 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002940 xmlNodePtr itemElem,
2941 const char *message,
2942 const xmlChar *str1,
2943 const xmlChar *str2,
2944 const xmlChar *str3)
2945{
2946 xmlChar *des = NULL, *msg = NULL;
2947
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002948 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002949 msg = xmlStrdup(BAD_CAST "%s: ");
2950 msg = xmlStrcat(msg, (const xmlChar *) message);
2951 msg = xmlStrcat(msg, BAD_CAST ".\n");
2952 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002954 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002955 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002956 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002957 FREE_AND_NULL(msg);
2958}
2959
William M. Brack2f2a6632004-08-20 23:09:47 +00002960/**
2961 * xmlSchemaPCustomErr:
2962 * @ctxt: the schema parser context
2963 * @error: the error code
2964 * @itemDes: the designation of the schema item
2965 * @item: the schema item
2966 * @itemElem: the node of the schema item
2967 * @message: the error message
2968 * @str1: the optional param for the error message
2969 *
2970 * Reports an error during parsing.
2971 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002972static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002973xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002974 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002975 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002976 xmlNodePtr itemElem,
2977 const char *message,
2978 const xmlChar *str1)
2979{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002980 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002981 str1, NULL, NULL);
2982}
2983
William M. Brack2f2a6632004-08-20 23:09:47 +00002984/**
2985 * xmlSchemaPAttrUseErr:
2986 * @ctxt: the schema parser context
2987 * @error: the error code
2988 * @itemDes: the designation of the schema type
2989 * @item: the schema type
2990 * @itemElem: the node of the schema type
2991 * @attr: the invalid schema attribute
2992 * @message: the error message
2993 * @str1: the optional param for the error message
2994 *
2995 * Reports an attribute use error during parsing.
2996 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002997static void LIBXML_ATTR_FORMAT(6,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002998xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002999 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003000 xmlNodePtr node,
3001 xmlSchemaBasicItemPtr ownerItem,
3002 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003004 const xmlChar *str1, const xmlChar *str2,
3005 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003006{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003007 xmlChar *str = NULL, *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00003008
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003009 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003010 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003011 msg = xmlStrcat(msg,
3012 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003013 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003014 FREE_AND_NULL(str);
3015 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003016 msg = xmlStrcat(msg, (const xmlChar *) message);
3017 msg = xmlStrcat(msg, BAD_CAST ".\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00003018 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003019 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003020 xmlFree(msg);
3021}
3022
William M. Brack2f2a6632004-08-20 23:09:47 +00003023/**
3024 * xmlSchemaPIllegalFacetAtomicErr:
3025 * @ctxt: the schema parser context
3026 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003027 * @type: the schema type
3028 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00003029 * @facet: the illegal facet
3030 *
3031 * Reports an illegal facet for atomic simple types.
3032 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003033static void
3034xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003035 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003036 xmlSchemaTypePtr type,
3037 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003038 xmlSchemaFacetPtr facet)
3039{
3040 xmlChar *des = NULL, *strT = NULL;
3041
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003042 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3043 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003044 "%s: The facet '%s' is not allowed on types derived from the "
3045 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003046 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003047 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00003048 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003049 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003050 FREE_AND_NULL(strT);
3051}
3052
William M. Brack2f2a6632004-08-20 23:09:47 +00003053/**
3054 * xmlSchemaPIllegalFacetListUnionErr:
3055 * @ctxt: the schema parser context
3056 * @error: the error code
3057 * @itemDes: the designation of the schema item involved
3058 * @item: the schema item involved
3059 * @facet: the illegal facet
3060 *
3061 * Reports an illegal facet for <list> and <union>.
3062 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003063static void
3064xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003065 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003066 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003067 xmlSchemaFacetPtr facet)
3068{
Daniel Veillardb2947172006-03-27 09:45:01 +00003069 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003071 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3072 type->node);
3073 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003074 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003075 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003076 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003077}
3078
3079/**
3080 * xmlSchemaPMutualExclAttrErr:
3081 * @ctxt: the schema validation context
3082 * @error: the error code
3083 * @elemDes: the designation of the parent element node
3084 * @attr: the bad attribute node
3085 * @type: the corresponding type of the attribute node
3086 *
3087 * Reports an illegal attribute.
3088 */
3089static void
3090xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3091 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003092 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003093 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003094 const char *name1,
3095 const char *name2)
3096{
3097 xmlChar *des = NULL;
3098
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003099 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003100 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003101 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003102 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003103 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003104}
3105
3106/**
3107 * xmlSchemaPSimpleTypeErr:
3108 * @ctxt: the schema validation context
3109 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003110 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00003111 * @ownerDes: the designation of the owner
Daniel Veillarddee23482008-04-11 12:58:43 +00003112 * @ownerItem: the schema object if existent
Daniel Veillardc0826a72004-08-10 14:17:33 +00003113 * @node: the validated node
3114 * @value: the validated value
3115 *
3116 * Reports a simple type validation error.
3117 * TODO: Should this report the value of an element as well?
3118 */
David Kilzer4472c3a2016-05-13 15:13:17 +08003119static void LIBXML_ATTR_FORMAT(8,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00003120xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003121 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003122 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003123 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003124 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003126 const xmlChar *value,
3127 const char *message,
3128 const xmlChar *str1,
3129 const xmlChar *str2)
3130{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003131 xmlChar *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00003132
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003133 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003134 if (message == NULL) {
3135 /*
3136 * Use default messages.
Daniel Veillarddee23482008-04-11 12:58:43 +00003137 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003138 if (type != NULL) {
3139 if (node->type == XML_ATTRIBUTE_NODE)
3140 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3141 else
3142 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
Daniel Veillarddee23482008-04-11 12:58:43 +00003143 "valid value of ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003144 if (! xmlSchemaIsGlobalItem(type))
3145 msg = xmlStrcat(msg, BAD_CAST "the local ");
3146 else
3147 msg = xmlStrcat(msg, BAD_CAST "the ");
Daniel Veillarddee23482008-04-11 12:58:43 +00003148
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003149 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003150 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003151 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003152 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003153 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003154 msg = xmlStrcat(msg, BAD_CAST "union type");
Daniel Veillarddee23482008-04-11 12:58:43 +00003155
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003156 if (xmlSchemaIsGlobalItem(type)) {
3157 xmlChar *str = NULL;
3158 msg = xmlStrcat(msg, BAD_CAST " '");
3159 if (type->builtInType != 0) {
3160 msg = xmlStrcat(msg, BAD_CAST "xs:");
David Kilzer502f6a62016-05-23 14:58:41 +08003161 str = xmlStrdup(type->name);
3162 } else {
3163 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3164 if (!str)
3165 str = xmlStrdup(qName);
3166 }
3167 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003168 msg = xmlStrcat(msg, BAD_CAST "'.");
3169 FREE_AND_NULL(str);
3170 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003171 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003172 if (node->type == XML_ATTRIBUTE_NODE)
3173 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3174 else
3175 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3176 "valid.");
Daniel Veillarddee23482008-04-11 12:58:43 +00003177 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003178 if (expected) {
David Kilzer502f6a62016-05-23 14:58:41 +08003179 xmlChar *expectedEscaped = xmlCharStrdup(expected);
Chun-wei Fand77e5fc2016-05-31 21:04:50 +08003180 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
David Kilzer502f6a62016-05-23 14:58:41 +08003181 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3182 FREE_AND_NULL(expectedEscaped);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003183 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3184 } else
3185 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003186 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003187 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3188 else
3189 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3190 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003191 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003192 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003193 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003194 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003195 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003196 /* Cleanup. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003197 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003198}
3199
William M. Brack2f2a6632004-08-20 23:09:47 +00003200/**
3201 * xmlSchemaPContentErr:
3202 * @ctxt: the schema parser context
3203 * @error: the error code
3204 * @onwerDes: the designation of the holder of the content
3205 * @ownerItem: the owner item of the holder of the content
3206 * @ownerElem: the node of the holder of the content
3207 * @child: the invalid child node
3208 * @message: the optional error message
3209 * @content: the optional string describing the correct content
3210 *
3211 * Reports an error concerning the content of a schema element.
3212 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003213static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003214xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003215 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003216 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003217 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003218 xmlNodePtr child,
3219 const char *message,
3220 const char *content)
3221{
3222 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003223
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003224 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003225 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003226 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3227 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003228 BAD_CAST des, BAD_CAST message);
3229 else {
3230 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003231 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3232 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003233 BAD_CAST des, BAD_CAST content);
3234 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3236 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003237 BAD_CAST des, NULL);
3238 }
3239 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003240 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003241}
3242
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003243/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003244 * *
3245 * Streamable error functions *
3246 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003247 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003248
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003249
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003250
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003252/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003253 * *
3254 * Validation helper functions *
3255 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003256 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003257
Daniel Veillardc0826a72004-08-10 14:17:33 +00003258
Daniel Veillard4255d502002-04-16 15:50:10 +00003259/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003260 * *
3261 * Allocation functions *
3262 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003263 ************************************************************************/
3264
3265/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003266 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003267 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003268 *
3269 * Allocate a new Schema structure.
3270 *
3271 * Returns the newly allocated structure or NULL in case or error
3272 */
3273static xmlSchemaPtr
3274xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3275{
3276 xmlSchemaPtr ret;
3277
3278 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3279 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003280 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003281 return (NULL);
3282 }
3283 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003284 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003285 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003286
3287 return (ret);
3288}
3289
3290/**
3291 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003292 *
3293 * Allocate a new Facet structure.
3294 *
3295 * Returns the newly allocated structure or NULL in case or error
3296 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003297xmlSchemaFacetPtr
3298xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003299{
3300 xmlSchemaFacetPtr ret;
3301
3302 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3303 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003304 return (NULL);
3305 }
3306 memset(ret, 0, sizeof(xmlSchemaFacet));
3307
3308 return (ret);
3309}
3310
3311/**
3312 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003313 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 * @node: a node
3315 *
3316 * Allocate a new annotation structure.
3317 *
3318 * Returns the newly allocated structure or NULL in case or error
3319 */
3320static xmlSchemaAnnotPtr
3321xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3322{
3323 xmlSchemaAnnotPtr ret;
3324
3325 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3326 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003327 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003328 return (NULL);
3329 }
3330 memset(ret, 0, sizeof(xmlSchemaAnnot));
3331 ret->content = node;
3332 return (ret);
3333}
3334
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003335static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003336xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003337{
3338 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003339
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003340 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3341 if (ret == NULL) {
3342 xmlSchemaPErrMemory(NULL,
3343 "allocating an item list structure", NULL);
3344 return (NULL);
3345 }
3346 memset(ret, 0, sizeof(xmlSchemaItemList));
3347 return (ret);
3348}
3349
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003350static void
3351xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3352{
3353 if (list->items != NULL) {
3354 xmlFree(list->items);
3355 list->items = NULL;
3356 }
3357 list->nbItems = 0;
3358 list->sizeItems = 0;
3359}
3360
3361static int
3362xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3363{
3364 if (list->items == NULL) {
3365 list->items = (void **) xmlMalloc(
3366 20 * sizeof(void *));
3367 if (list->items == NULL) {
3368 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3369 return(-1);
3370 }
3371 list->sizeItems = 20;
3372 } else if (list->sizeItems <= list->nbItems) {
3373 list->sizeItems *= 2;
3374 list->items = (void **) xmlRealloc(list->items,
3375 list->sizeItems * sizeof(void *));
3376 if (list->items == NULL) {
3377 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3378 list->sizeItems = 0;
3379 return(-1);
3380 }
3381 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003382 list->items[list->nbItems++] = item;
3383 return(0);
3384}
3385
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003386static int
3387xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3388 int initialSize,
3389 void *item)
3390{
3391 if (list->items == NULL) {
3392 if (initialSize <= 0)
3393 initialSize = 1;
3394 list->items = (void **) xmlMalloc(
3395 initialSize * sizeof(void *));
3396 if (list->items == NULL) {
3397 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3398 return(-1);
3399 }
3400 list->sizeItems = initialSize;
3401 } else if (list->sizeItems <= list->nbItems) {
3402 list->sizeItems *= 2;
3403 list->items = (void **) xmlRealloc(list->items,
3404 list->sizeItems * sizeof(void *));
3405 if (list->items == NULL) {
3406 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3407 list->sizeItems = 0;
3408 return(-1);
3409 }
3410 }
3411 list->items[list->nbItems++] = item;
3412 return(0);
3413}
3414
3415static int
3416xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003417{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003418 if (list->items == NULL) {
3419 list->items = (void **) xmlMalloc(
3420 20 * sizeof(void *));
3421 if (list->items == NULL) {
3422 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423 return(-1);
3424 }
3425 list->sizeItems = 20;
3426 } else if (list->sizeItems <= list->nbItems) {
3427 list->sizeItems *= 2;
3428 list->items = (void **) xmlRealloc(list->items,
3429 list->sizeItems * sizeof(void *));
3430 if (list->items == NULL) {
3431 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432 list->sizeItems = 0;
3433 return(-1);
3434 }
3435 }
3436 /*
3437 * Just append if the index is greater/equal than the item count.
3438 */
3439 if (idx >= list->nbItems) {
3440 list->items[list->nbItems++] = item;
3441 } else {
3442 int i;
3443 for (i = list->nbItems; i > idx; i--)
3444 list->items[i] = list->items[i-1];
3445 list->items[idx] = item;
3446 list->nbItems++;
3447 }
3448 return(0);
3449}
3450
3451#if 0 /* enable if ever needed */
3452static int
3453xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3454 int initialSize,
3455 void *item,
3456 int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003457{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003458 if (list->items == NULL) {
3459 if (initialSize <= 0)
3460 initialSize = 1;
3461 list->items = (void **) xmlMalloc(
3462 initialSize * sizeof(void *));
3463 if (list->items == NULL) {
3464 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3465 return(-1);
3466 }
3467 list->sizeItems = initialSize;
3468 } else if (list->sizeItems <= list->nbItems) {
3469 list->sizeItems *= 2;
3470 list->items = (void **) xmlRealloc(list->items,
3471 list->sizeItems * sizeof(void *));
3472 if (list->items == NULL) {
3473 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3474 list->sizeItems = 0;
3475 return(-1);
3476 }
3477 }
3478 /*
3479 * Just append if the index is greater/equal than the item count.
3480 */
3481 if (idx >= list->nbItems) {
3482 list->items[list->nbItems++] = item;
3483 } else {
3484 int i;
3485 for (i = list->nbItems; i > idx; i--)
3486 list->items[i] = list->items[i-1];
3487 list->items[idx] = item;
3488 list->nbItems++;
3489 }
3490 return(0);
3491}
3492#endif
3493
3494static int
3495xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3496{
3497 int i;
3498 if ((list->items == NULL) || (idx >= list->nbItems)) {
3499 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3500 "index error.\n");
3501 return(-1);
3502 }
3503
3504 if (list->nbItems == 1) {
3505 /* TODO: Really free the list? */
3506 xmlFree(list->items);
3507 list->items = NULL;
3508 list->nbItems = 0;
3509 list->sizeItems = 0;
3510 } else if (list->nbItems -1 == idx) {
3511 list->nbItems--;
Daniel Veillarddee23482008-04-11 12:58:43 +00003512 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003513 for (i = idx; i < list->nbItems -1; i++)
3514 list->items[i] = list->items[i+1];
3515 list->nbItems--;
3516 }
3517 return(0);
3518}
3519
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003520/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003521 * xmlSchemaItemListFree:
3522 * @annot: a schema type structure
3523 *
3524 * Deallocate a annotation structure
3525 */
3526static void
3527xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3528{
3529 if (list == NULL)
3530 return;
3531 if (list->items != NULL)
3532 xmlFree(list->items);
3533 xmlFree(list);
3534}
3535
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003536static void
3537xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003538{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003539 if (bucket == NULL)
3540 return;
3541 if (bucket->globals != NULL) {
3542 xmlSchemaComponentListFree(bucket->globals);
3543 xmlSchemaItemListFree(bucket->globals);
3544 }
3545 if (bucket->locals != NULL) {
3546 xmlSchemaComponentListFree(bucket->locals);
Daniel Veillarddee23482008-04-11 12:58:43 +00003547 xmlSchemaItemListFree(bucket->locals);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003548 }
3549 if (bucket->relations != NULL) {
3550 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3551 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00003552 prev = cur;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003553 cur = cur->next;
3554 xmlFree(prev);
3555 } while (cur != NULL);
3556 }
3557 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3558 xmlFreeDoc(bucket->doc);
Daniel Veillarddee23482008-04-11 12:58:43 +00003559 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003560 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003561 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3562 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003563 }
3564 xmlFree(bucket);
3565}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003566
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003567static xmlSchemaBucketPtr
3568xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003569 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003570{
3571 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003572 int size;
3573 xmlSchemaPtr mainSchema;
3574
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003575 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576 PERROR_INT("xmlSchemaBucketCreate",
3577 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003578 return(NULL);
3579 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003580 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003581 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003582 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003583 size = sizeof(xmlSchemaInclude);
3584 else
3585 size = sizeof(xmlSchemaImport);
3586 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3587 if (ret == NULL) {
3588 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3589 return(NULL);
3590 }
3591 memset(ret, 0, size);
3592 ret->targetNamespace = targetNamespace;
3593 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003594 ret->globals = xmlSchemaItemListCreate();
3595 if (ret->globals == NULL) {
3596 xmlFree(ret);
3597 return(NULL);
3598 }
3599 ret->locals = xmlSchemaItemListCreate();
3600 if (ret->locals == NULL) {
3601 xmlFree(ret);
3602 return(NULL);
3603 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003604 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003605 * The following will assure that only the first bucket is marked as
3606 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3607 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003608 * An xmlSchema will be created for every distinct targetNamespace.
3609 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003610 */
3611 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003612 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003613 PERROR_INT("xmlSchemaBucketCreate",
3614 "first bucket but it's an include or redefine");
3615 xmlSchemaBucketFree(ret);
3616 return(NULL);
3617 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003618 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003619 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3620 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003621 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3622 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003623 /*
3624 * Ensure that the main schema gets a targetNamespace.
3625 */
3626 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003627 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +00003628 if (type == XML_SCHEMA_SCHEMA_MAIN) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003629 PERROR_INT("xmlSchemaBucketCreate",
3630 "main bucket but it's not the first one");
3631 xmlSchemaBucketFree(ret);
3632 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003633 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003634 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003635 * Create a schema for imports and assign the
3636 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003637 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003638 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3639 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003640 xmlSchemaBucketFree(ret);
3641 return(NULL);
3642 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003643 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003644 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003645 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003646 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003647 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003648 /*
3649 * Imports go into the "schemasImports" slot of the main *schema*.
3650 * Note that we create an import entry for the main schema as well; i.e.,
3651 * even if there's only one schema, we'll get an import.
3652 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003653 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003654 mainSchema->schemasImports = xmlHashCreateDict(5,
3655 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003656 if (mainSchema->schemasImports == NULL) {
3657 xmlSchemaBucketFree(ret);
3658 return(NULL);
3659 }
3660 }
3661 if (targetNamespace == NULL)
3662 res = xmlHashAddEntry(mainSchema->schemasImports,
3663 XML_SCHEMAS_NO_NAMESPACE, ret);
3664 else
3665 res = xmlHashAddEntry(mainSchema->schemasImports,
3666 targetNamespace, ret);
3667 if (res != 0) {
3668 PERROR_INT("xmlSchemaBucketCreate",
3669 "failed to add the schema bucket to the hash");
3670 xmlSchemaBucketFree(ret);
3671 return(NULL);
3672 }
3673 } else {
3674 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003675 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3676 WXS_INCBUCKET(ret)->ownerImport =
3677 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003678 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003679 WXS_INCBUCKET(ret)->ownerImport =
3680 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003681
3682 /* Includes got into the "includes" slot of the *main* schema. */
3683 if (mainSchema->includes == NULL) {
3684 mainSchema->includes = xmlSchemaItemListCreate();
3685 if (mainSchema->includes == NULL) {
3686 xmlSchemaBucketFree(ret);
3687 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003688 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003689 }
3690 xmlSchemaItemListAdd(mainSchema->includes, ret);
3691 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003692 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003693 * Add to list of all buckets; this is used for lookup
3694 * during schema construction time only.
3695 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003696 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003697 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003698 return(ret);
3699}
3700
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003701static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003702xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003703{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003704 if (*list == NULL) {
3705 *list = xmlSchemaItemListCreate();
3706 if (*list == NULL)
3707 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003708 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003709 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003710 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003711}
3712
3713/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003714 * xmlSchemaFreeAnnot:
3715 * @annot: a schema type structure
3716 *
3717 * Deallocate a annotation structure
3718 */
3719static void
3720xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3721{
3722 if (annot == NULL)
3723 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003724 if (annot->next == NULL) {
3725 xmlFree(annot);
3726 } else {
3727 xmlSchemaAnnotPtr prev;
3728
3729 do {
3730 prev = annot;
3731 annot = annot->next;
3732 xmlFree(prev);
3733 } while (annot != NULL);
3734 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003735}
3736
3737/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 * xmlSchemaFreeNotation:
3739 * @schema: a schema notation structure
3740 *
3741 * Deallocate a Schema Notation structure.
3742 */
3743static void
3744xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3745{
3746 if (nota == NULL)
3747 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003748 xmlFree(nota);
3749}
3750
3751/**
3752 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003753 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003754 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003755 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003756 */
3757static void
3758xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3759{
3760 if (attr == NULL)
3761 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003762 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003763 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003764 if (attr->defVal != NULL)
3765 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003766 xmlFree(attr);
3767}
3768
3769/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003770 * xmlSchemaFreeAttributeUse:
3771 * @use: an attribute use
3772 *
3773 * Deallocates an attribute use structure.
3774 */
3775static void
3776xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3777{
3778 if (use == NULL)
3779 return;
3780 if (use->annot != NULL)
3781 xmlSchemaFreeAnnot(use->annot);
3782 if (use->defVal != NULL)
3783 xmlSchemaFreeValue(use->defVal);
3784 xmlFree(use);
3785}
3786
3787/**
3788 * xmlSchemaFreeAttributeUseProhib:
3789 * @prohib: an attribute use prohibition
3790 *
3791 * Deallocates an attribute use structure.
3792 */
3793static void
3794xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3795{
3796 if (prohib == NULL)
3797 return;
3798 xmlFree(prohib);
3799}
3800
3801/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003802 * xmlSchemaFreeWildcardNsSet:
3803 * set: a schema wildcard namespace
3804 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003805 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003806 */
3807static void
3808xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3809{
3810 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003811
Daniel Veillard3646d642004-06-02 19:19:14 +00003812 while (set != NULL) {
3813 next = set->next;
3814 xmlFree(set);
3815 set = next;
3816 }
3817}
3818
3819/**
3820 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003821 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003822 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003823 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003824 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003825void
Daniel Veillard3646d642004-06-02 19:19:14 +00003826xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3827{
3828 if (wildcard == NULL)
3829 return;
3830 if (wildcard->annot != NULL)
3831 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003832 if (wildcard->nsSet != NULL)
3833 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3834 if (wildcard->negNsSet != NULL)
3835 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003836 xmlFree(wildcard);
3837}
3838
3839/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003840 * xmlSchemaFreeAttributeGroup:
3841 * @schema: a schema attribute group structure
3842 *
3843 * Deallocate a Schema Attribute Group structure.
3844 */
3845static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003846xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003847{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003848 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003849 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003850 if (attrGr->annot != NULL)
3851 xmlSchemaFreeAnnot(attrGr->annot);
3852 if (attrGr->attrUses != NULL)
3853 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3854 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003855}
3856
3857/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003858 * xmlSchemaFreeQNameRef:
3859 * @item: a QName reference structure
3860 *
3861 * Deallocatea a QName reference structure.
3862 */
3863static void
3864xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3865{
3866 xmlFree(item);
3867}
3868
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003869/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003870 * xmlSchemaFreeTypeLinkList:
3871 * @alink: a type link
3872 *
3873 * Deallocate a list of types.
3874 */
3875static void
3876xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3877{
3878 xmlSchemaTypeLinkPtr next;
3879
3880 while (link != NULL) {
3881 next = link->next;
3882 xmlFree(link);
3883 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003884 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003885}
3886
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003887static void
3888xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3889{
3890 xmlSchemaIDCStateObjPtr next;
3891 while (sto != NULL) {
3892 next = sto->next;
3893 if (sto->history != NULL)
3894 xmlFree(sto->history);
3895 if (sto->xpathCtxt != NULL)
3896 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3897 xmlFree(sto);
3898 sto = next;
3899 }
3900}
3901
3902/**
3903 * xmlSchemaFreeIDC:
3904 * @idc: a identity-constraint definition
3905 *
3906 * Deallocates an identity-constraint definition.
3907 */
3908static void
3909xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3910{
3911 xmlSchemaIDCSelectPtr cur, prev;
3912
3913 if (idcDef == NULL)
3914 return;
3915 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003916 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003917 /* Selector */
3918 if (idcDef->selector != NULL) {
3919 if (idcDef->selector->xpathComp != NULL)
3920 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3921 xmlFree(idcDef->selector);
3922 }
3923 /* Fields */
3924 if (idcDef->fields != NULL) {
3925 cur = idcDef->fields;
3926 do {
3927 prev = cur;
3928 cur = cur->next;
3929 if (prev->xpathComp != NULL)
3930 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003931 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003932 } while (cur != NULL);
3933 }
3934 xmlFree(idcDef);
3935}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003936
Daniel Veillard01fa6152004-06-29 17:04:39 +00003937/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003938 * xmlSchemaFreeElement:
3939 * @schema: a schema element structure
3940 *
3941 * Deallocate a Schema Element structure.
3942 */
3943static void
3944xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3945{
3946 if (elem == NULL)
3947 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003948 if (elem->annot != NULL)
3949 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003950 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003951 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003952 if (elem->defVal != NULL)
3953 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003954 xmlFree(elem);
3955}
3956
3957/**
3958 * xmlSchemaFreeFacet:
3959 * @facet: a schema facet structure
3960 *
3961 * Deallocate a Schema Facet structure.
3962 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003963void
Daniel Veillard4255d502002-04-16 15:50:10 +00003964xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3965{
3966 if (facet == NULL)
3967 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003969 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003970 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003971 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003972 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003974 xmlFree(facet);
3975}
3976
3977/**
3978 * xmlSchemaFreeType:
3979 * @type: a schema type structure
3980 *
3981 * Deallocate a Schema Type structure.
3982 */
3983void
3984xmlSchemaFreeType(xmlSchemaTypePtr type)
3985{
3986 if (type == NULL)
3987 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003988 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003989 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003990 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003991 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003992
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003993 facet = type->facets;
3994 while (facet != NULL) {
3995 next = facet->next;
3996 xmlSchemaFreeFacet(facet);
3997 facet = next;
3998 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003999 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004000 if (type->attrUses != NULL)
4001 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004002 if (type->memberTypes != NULL)
4003 xmlSchemaFreeTypeLinkList(type->memberTypes);
4004 if (type->facetSet != NULL) {
4005 xmlSchemaFacetLinkPtr next, link;
4006
4007 link = type->facetSet;
4008 do {
4009 next = link->next;
4010 xmlFree(link);
4011 link = next;
4012 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004013 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004014 if (type->contModel != NULL)
4015 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004016 xmlFree(type);
4017}
4018
4019/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004020 * xmlSchemaFreeModelGroupDef:
4021 * @item: a schema model group definition
4022 *
4023 * Deallocates a schema model group definition.
4024 */
4025static void
4026xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4027{
4028 if (item->annot != NULL)
4029 xmlSchemaFreeAnnot(item->annot);
4030 xmlFree(item);
4031}
4032
4033/**
4034 * xmlSchemaFreeModelGroup:
4035 * @item: a schema model group
4036 *
4037 * Deallocates a schema model group structure.
4038 */
4039static void
4040xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4041{
4042 if (item->annot != NULL)
4043 xmlSchemaFreeAnnot(item->annot);
4044 xmlFree(item);
4045}
4046
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004047static void
4048xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4049{
4050 if ((list == NULL) || (list->nbItems == 0))
4051 return;
4052 {
4053 xmlSchemaTreeItemPtr item;
4054 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4055 int i;
4056
4057 for (i = 0; i < list->nbItems; i++) {
4058 item = items[i];
4059 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004060 continue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004061 switch (item->type) {
4062 case XML_SCHEMA_TYPE_SIMPLE:
4063 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004064 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004065 break;
4066 case XML_SCHEMA_TYPE_ATTRIBUTE:
4067 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004068 break;
4069 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4070 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4071 break;
4072 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4073 xmlSchemaFreeAttributeUseProhib(
4074 (xmlSchemaAttributeUseProhibPtr) item);
4075 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004076 case XML_SCHEMA_TYPE_ELEMENT:
4077 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4078 break;
4079 case XML_SCHEMA_TYPE_PARTICLE:
4080 if (item->annot != NULL)
4081 xmlSchemaFreeAnnot(item->annot);
4082 xmlFree(item);
4083 break;
4084 case XML_SCHEMA_TYPE_SEQUENCE:
4085 case XML_SCHEMA_TYPE_CHOICE:
4086 case XML_SCHEMA_TYPE_ALL:
4087 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4088 break;
4089 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4090 xmlSchemaFreeAttributeGroup(
4091 (xmlSchemaAttributeGroupPtr) item);
4092 break;
4093 case XML_SCHEMA_TYPE_GROUP:
4094 xmlSchemaFreeModelGroupDef(
4095 (xmlSchemaModelGroupDefPtr) item);
4096 break;
4097 case XML_SCHEMA_TYPE_ANY:
4098 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4099 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4100 break;
4101 case XML_SCHEMA_TYPE_IDC_KEY:
4102 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4103 case XML_SCHEMA_TYPE_IDC_KEYREF:
4104 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4105 break;
4106 case XML_SCHEMA_TYPE_NOTATION:
4107 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4108 break;
4109 case XML_SCHEMA_EXTRA_QNAMEREF:
4110 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4111 break;
4112 default: {
4113 /* TODO: This should never be hit. */
4114 xmlSchemaPSimpleInternalErr(NULL,
4115 "Internal error: xmlSchemaComponentListFree, "
4116 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004117 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004118 }
4119 break;
4120 }
4121 }
4122 list->nbItems = 0;
4123 }
4124}
4125
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004126/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004127 * xmlSchemaFree:
4128 * @schema: a schema structure
4129 *
4130 * Deallocate a Schema structure.
4131 */
4132void
4133xmlSchemaFree(xmlSchemaPtr schema)
4134{
4135 if (schema == NULL)
4136 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004137 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004138 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004139 TODO
4140 /*
4141 * Note that those slots are not responsible for freeing
4142 * schema components anymore; this will now be done by
4143 * the schema buckets.
4144 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004145 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004146 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004147 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004148 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004149 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004150 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004151 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004152 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004153 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004154 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004155 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004156 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004157 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004158 xmlHashFree(schema->idcDef, NULL);
4159
Daniel Veillard1d913862003-11-21 00:28:39 +00004160 if (schema->schemasImports != NULL)
4161 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004162 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004163 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004164 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4165 int i;
4166 for (i = 0; i < list->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +00004167 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004168 }
4169 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004170 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004173 /* Never free the doc here, since this will be done by the buckets. */
4174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004175 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004176 xmlFree(schema);
4177}
4178
4179/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004180 * *
4181 * Debug functions *
4182 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004183 ************************************************************************/
4184
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004185#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004186
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004187static void
4188xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4189
Daniel Veillard4255d502002-04-16 15:50:10 +00004190/**
4191 * xmlSchemaElementDump:
4192 * @elem: an element
4193 * @output: the file output
4194 *
4195 * Dump the element
4196 */
4197static void
4198xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004200 const xmlChar * namespace ATTRIBUTE_UNUSED,
4201 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004202{
4203 if (elem == NULL)
4204 return;
4205
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004206
4207 fprintf(output, "Element");
4208 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4209 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004210 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004211 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004212 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004213 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004214#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004215 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004216 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 if (elem->maxOccurs >= UNBOUNDED)
4218 fprintf(output, "max: unbounded\n");
4219 else if (elem->maxOccurs != 1)
4220 fprintf(output, "max: %d\n", elem->maxOccurs);
4221 else
4222 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004224#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004225 /*
4226 * Misc other properties.
4227 */
4228 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4229 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4230 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004231 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004232 fprintf(output, " props: ");
4233 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4234 fprintf(output, "[fixed] ");
4235 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4236 fprintf(output, "[default] ");
4237 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4238 fprintf(output, "[abstract] ");
4239 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4240 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004241 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004243 /*
4244 * Default/fixed value.
4245 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004247 fprintf(output, " value: '%s'\n", elem->value);
4248 /*
4249 * Type.
4250 */
4251 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004252 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004253 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004254 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004255 else
4256 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004257 } else if (elem->subtypes != NULL) {
4258 /*
4259 * Dump local types.
4260 */
4261 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004262 }
4263 /*
4264 * Substitution group.
4265 */
4266 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004267 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004268 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004269 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004270 else
4271 fprintf(output, "\n");
4272 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004273}
4274
4275/**
4276 * xmlSchemaAnnotDump:
4277 * @output: the file output
4278 * @annot: a annotation
4279 *
4280 * Dump the annotation
4281 */
4282static void
4283xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4284{
4285 xmlChar *content;
4286
4287 if (annot == NULL)
4288 return;
4289
4290 content = xmlNodeGetContent(annot->content);
4291 if (content != NULL) {
4292 fprintf(output, " Annot: %s\n", content);
4293 xmlFree(content);
4294 } else
4295 fprintf(output, " Annot: empty\n");
4296}
4297
4298/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004299 * xmlSchemaContentModelDump:
4300 * @particle: the schema particle
4301 * @output: the file output
4302 * @depth: the depth used for intentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 *
4304 * Dump a SchemaType structure
4305 */
4306static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004307xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4308{
4309 xmlChar *str = NULL;
4310 xmlSchemaTreeItemPtr term;
4311 char shift[100];
4312 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004313
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004314 if (particle == NULL)
4315 return;
4316 for (i = 0;((i < depth) && (i < 25));i++)
4317 shift[2 * i] = shift[2 * i + 1] = ' ';
4318 shift[2 * i] = shift[2 * i + 1] = 0;
Daniel Veillardbccae2d2009-06-04 11:22:45 +02004319 fprintf(output, "%s", shift);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004320 if (particle->children == NULL) {
4321 fprintf(output, "MISSING particle term\n");
4322 return;
4323 }
4324 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004325 if (term == NULL) {
4326 fprintf(output, "(NULL)");
4327 } else {
4328 switch (term->type) {
4329 case XML_SCHEMA_TYPE_ELEMENT:
4330 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4331 ((xmlSchemaElementPtr)term)->targetNamespace,
4332 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004333 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004334 break;
4335 case XML_SCHEMA_TYPE_SEQUENCE:
4336 fprintf(output, "SEQUENCE");
4337 break;
4338 case XML_SCHEMA_TYPE_CHOICE:
4339 fprintf(output, "CHOICE");
4340 break;
4341 case XML_SCHEMA_TYPE_ALL:
4342 fprintf(output, "ALL");
4343 break;
4344 case XML_SCHEMA_TYPE_ANY:
4345 fprintf(output, "ANY");
4346 break;
4347 default:
4348 fprintf(output, "UNKNOWN\n");
4349 return;
4350 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004351 }
4352 if (particle->minOccurs != 1)
4353 fprintf(output, " min: %d", particle->minOccurs);
4354 if (particle->maxOccurs >= UNBOUNDED)
4355 fprintf(output, " max: unbounded");
4356 else if (particle->maxOccurs != 1)
4357 fprintf(output, " max: %d", particle->maxOccurs);
4358 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004359 if (term &&
4360 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4361 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4362 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4363 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004364 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4365 output, depth +1);
4366 }
4367 if (particle->next != NULL)
4368 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4369 output, depth);
4370}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004371
4372/**
4373 * xmlSchemaAttrUsesDump:
4374 * @uses: attribute uses list
Daniel Veillarddee23482008-04-11 12:58:43 +00004375 * @output: the file output
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004376 *
4377 * Dumps a list of attribute use components.
4378 */
4379static void
4380xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4381{
4382 xmlSchemaAttributeUsePtr use;
4383 xmlSchemaAttributeUseProhibPtr prohib;
4384 xmlSchemaQNameRefPtr ref;
4385 const xmlChar *name, *tns;
4386 xmlChar *str = NULL;
4387 int i;
4388
4389 if ((uses == NULL) || (uses->nbItems == 0))
4390 return;
4391
Daniel Veillarddee23482008-04-11 12:58:43 +00004392 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004393 for (i = 0; i < uses->nbItems; i++) {
4394 use = uses->items[i];
4395 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4396 fprintf(output, " [prohibition] ");
4397 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4398 name = prohib->name;
4399 tns = prohib->targetNamespace;
4400 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4401 fprintf(output, " [reference] ");
4402 ref = (xmlSchemaQNameRefPtr) use;
4403 name = ref->name;
4404 tns = ref->targetNamespace;
4405 } else {
4406 fprintf(output, " [use] ");
4407 name = WXS_ATTRUSE_DECL_NAME(use);
4408 tns = WXS_ATTRUSE_DECL_TNS(use);
4409 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004410 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004411 (const char *) xmlSchemaFormatQName(&str, tns, name));
4412 FREE_AND_NULL(str);
4413 }
4414}
4415
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004416/**
4417 * xmlSchemaTypeDump:
4418 * @output: the file output
4419 * @type: a type structure
4420 *
4421 * Dump a SchemaType structure
4422 */
4423static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004424xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4425{
4426 if (type == NULL) {
4427 fprintf(output, "Type: NULL\n");
4428 return;
4429 }
4430 fprintf(output, "Type: ");
4431 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004432 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004433 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004434 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004435 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004436 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004437 switch (type->type) {
4438 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004439 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 break;
4441 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004442 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 break;
4444 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004445 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 break;
4447 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004448 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 break;
4450 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004451 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 break;
4453 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004454 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004455 break;
4456 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004457 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 break;
4459 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004460 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 break;
4462 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004463 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 break;
4465 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004466 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004467 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004468 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004469 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004471 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004472 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 break;
4474 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004475 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004476 break;
4477 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004478 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004479 break;
4480 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004481 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004482 break;
4483 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004484 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 break;
4486 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004487 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488 break;
4489 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004490 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004491 break;
4492 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004493 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004495 }
4496 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004497 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004498 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004499 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004500 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004501 else
4502 fprintf(output, "\n");
4503 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004504 if (type->attrUses != NULL)
4505 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004506 if (type->annot != NULL)
4507 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004508#ifdef DUMP_CONTENT_MODEL
4509 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4510 (type->subtypes != NULL)) {
4511 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4512 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004513 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004514#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004515}
4516
4517/**
4518 * xmlSchemaDump:
4519 * @output: the file output
4520 * @schema: a schema structure
4521 *
4522 * Dump a Schema structure.
4523 */
4524void
4525xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4526{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004527 if (output == NULL)
4528 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 if (schema == NULL) {
4530 fprintf(output, "Schemas: NULL\n");
4531 return;
4532 }
4533 fprintf(output, "Schemas: ");
4534 if (schema->name != NULL)
4535 fprintf(output, "%s, ", schema->name);
4536 else
4537 fprintf(output, "no name, ");
4538 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004539 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 else
4541 fprintf(output, "no target namespace");
4542 fprintf(output, "\n");
4543 if (schema->annot != NULL)
4544 xmlSchemaAnnotDump(output, schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4546 output);
4547 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004548 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004549}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004550
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004551#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004552/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004553 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004554 * @vctxt: the WXS validation context
4555 *
4556 * Displays the current IDC table for debug purposes.
4557 */
4558static void
4559xmlSchemaDebugDumpIDCTable(FILE * output,
4560 const xmlChar *namespaceName,
4561 const xmlChar *localName,
4562 xmlSchemaPSVIIDCBindingPtr bind)
4563{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004564 xmlChar *str = NULL;
4565 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004566 xmlSchemaPSVIIDCNodePtr tab;
4567 xmlSchemaPSVIIDCKeyPtr key;
4568 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004569
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004570 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004571 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004572 FREE_AND_NULL(str)
4573
4574 if (bind == NULL)
4575 return;
4576 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004577 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Daniel Veillarddee23482008-04-11 12:58:43 +00004578 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004579 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004581 for (i = 0; i < bind->nbNodes; i++) {
4582 tab = bind->nodeTable[i];
4583 fprintf(output, " ( ");
4584 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004585 key = tab->keys[j];
4586 if ((key != NULL) && (key->val != NULL)) {
4587 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004588 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004589 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004590 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004591 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004592 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004593 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004594 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004595 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004596 else
4597 fprintf(output, "(key missing), ");
4598 }
4599 fprintf(output, ")\n");
4600 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004601 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004602 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004603 for (i = 0; i < bind->dupls->nbItems; i++) {
4604 tab = bind->dupls->items[i];
4605 fprintf(output, " ( ");
4606 for (j = 0; j < bind->definition->nbFields; j++) {
4607 key = tab->keys[j];
4608 if ((key != NULL) && (key->val != NULL)) {
4609 res = xmlSchemaGetCanonValue(key->val, &value);
4610 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004611 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004612 else
4613 fprintf(output, "CANON-VALUE-FAILED ");
4614 if (res == 0)
4615 FREE_AND_NULL(value)
4616 } else if (key != NULL)
4617 fprintf(output, "(no val), ");
4618 else
4619 fprintf(output, "(key missing), ");
4620 }
4621 fprintf(output, ")\n");
4622 }
4623 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004624 bind = bind->next;
4625 } while (bind != NULL);
4626}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004627#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004628#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004629
4630/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004631 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004632 * Utilities *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004633 * *
4634 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004635
Daniel Veillardc0826a72004-08-10 14:17:33 +00004636/**
4637 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004638 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004639 * @name: the name of the attribute
4640 *
4641 * Seeks an attribute with a name of @name in
4642 * no namespace.
4643 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004644 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004645 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004646static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004647xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004648{
4649 xmlAttrPtr prop;
4650
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004651 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004652 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004653 prop = node->properties;
4654 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004655 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004656 return(prop);
4657 prop = prop->next;
4658 }
4659 return (NULL);
4660}
4661
4662/**
4663 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004664 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004665 * @uri: the uri
4666 * @name: the name of the attribute
4667 *
4668 * Seeks an attribute with a local name of @name and
4669 * a namespace URI of @uri.
4670 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004671 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004672 */
4673static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004674xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004675{
4676 xmlAttrPtr prop;
4677
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004678 if ((node == NULL) || (name == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00004679 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004680 prop = node->properties;
4681 while (prop != NULL) {
4682 if ((prop->ns != NULL) &&
4683 xmlStrEqual(prop->name, BAD_CAST name) &&
4684 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004685 return(prop);
4686 prop = prop->next;
4687 }
4688 return (NULL);
4689}
4690
4691static const xmlChar *
4692xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4693{
4694 xmlChar *val;
4695 const xmlChar *ret;
4696
4697 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004698 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004699 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004700 ret = xmlDictLookup(ctxt->dict, val, -1);
4701 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004702 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004703}
4704
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004705static const xmlChar *
4706xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4707{
4708 return((const xmlChar*) xmlNodeGetContent(node));
4709}
4710
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004711/**
4712 * xmlSchemaGetProp:
4713 * @ctxt: the parser context
4714 * @node: the node
4715 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004716 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004717 * Read a attribute value and internalize the string
4718 *
4719 * Returns the string or NULL if not present.
4720 */
4721static const xmlChar *
4722xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4723 const char *name)
4724{
4725 xmlChar *val;
4726 const xmlChar *ret;
4727
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004728 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004729 if (val == NULL)
4730 return(NULL);
4731 ret = xmlDictLookup(ctxt->dict, val, -1);
4732 xmlFree(val);
4733 return(ret);
4734}
4735
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004736/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004737 * *
4738 * Parsing functions *
4739 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004740 ************************************************************************/
4741
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004742#define WXS_FIND_GLOBAL_ITEM(slot) \
4743 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4744 ret = xmlHashLookup(schema->slot, name); \
4745 if (ret != NULL) goto exit; \
4746 } \
4747 if (xmlHashSize(schema->schemasImports) > 1) { \
4748 xmlSchemaImportPtr import; \
4749 if (nsName == NULL) \
4750 import = xmlHashLookup(schema->schemasImports, \
4751 XML_SCHEMAS_NO_NAMESPACE); \
4752 else \
4753 import = xmlHashLookup(schema->schemasImports, nsName); \
4754 if (import == NULL) \
4755 goto exit; \
4756 ret = xmlHashLookup(import->schema->slot, name); \
4757 }
4758
Daniel Veillard4255d502002-04-16 15:50:10 +00004759/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004760 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004761 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004762 * @name: the element name
4763 * @ns: the element namespace
4764 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004765 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004766 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004767 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004768 */
4769static xmlSchemaElementPtr
4770xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004771 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004772{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004773 xmlSchemaElementPtr ret = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00004774
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004775 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004776 return(NULL);
4777 if (schema != NULL) {
4778 WXS_FIND_GLOBAL_ITEM(elemDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004779 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004780exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004781#ifdef DEBUG
4782 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004783 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004784 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004785 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004786 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004787 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004788 }
4789#endif
4790 return (ret);
4791}
4792
4793/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004795 * @schema: the main schema
4796 * @name: the type's name
4797 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004798 *
4799 * Lookup a type in the schemas or the predefined types
4800 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004801 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 */
4803static xmlSchemaTypePtr
4804xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004805 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004806{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004807 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004808
4809 if (name == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004810 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004811 /* First try the built-in types. */
Daniel Veillarddee23482008-04-11 12:58:43 +00004812 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004813 ret = xmlSchemaGetPredefinedType(name, nsName);
4814 if (ret != NULL)
4815 goto exit;
4816 /*
4817 * Note that we try the parsed schemas as well here
4818 * since one might have parsed the S4S, which contain more
4819 * than the built-in types.
4820 * TODO: Can we optimize this?
4821 */
4822 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004823 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004824 WXS_FIND_GLOBAL_ITEM(typeDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004825 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004826exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004827
Daniel Veillard4255d502002-04-16 15:50:10 +00004828#ifdef DEBUG
4829 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004830 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 fprintf(stderr, "Unable to lookup type %s", name);
4832 else
4833 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004834 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004835 }
4836#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004837 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004838}
4839
Daniel Veillard3646d642004-06-02 19:19:14 +00004840/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004841 * xmlSchemaGetAttributeDecl:
4842 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004844 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 *
4846 * Lookup a an attribute in the schema or imported schemas
4847 *
4848 * Returns the attribute declaration or NULL if not found.
4849 */
4850static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004851xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004852 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004853{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004854 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004855
4856 if ((name == NULL) || (schema == NULL))
4857 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004858 if (schema != NULL) {
4859 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004860 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004861exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004862#ifdef DEBUG
4863 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004864 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 fprintf(stderr, "Unable to lookup attribute %s", name);
4866 else
4867 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004868 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004869 }
4870#endif
4871 return (ret);
4872}
4873
4874/**
4875 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004876 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004877 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004878 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004879 *
4880 * Lookup a an attribute group in the schema or imported schemas
4881 *
4882 * Returns the attribute group definition or NULL if not found.
4883 */
4884static xmlSchemaAttributeGroupPtr
4885xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004886 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004887{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004888 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004889
4890 if ((name == NULL) || (schema == NULL))
4891 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004892 if (schema != NULL) {
4893 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4894 }
4895exit:
4896 /* TODO:
4897 if ((ret != NULL) && (ret->redef != NULL)) {
4898 * Return the last redefinition. *
4899 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004900 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004901 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004902#ifdef DEBUG
4903 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004904 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004905 fprintf(stderr, "Unable to lookup attribute group %s", name);
4906 else
4907 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004908 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004909 }
4910#endif
4911 return (ret);
4912}
4913
4914/**
4915 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004916 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004917 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004918 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004919 *
4920 * Lookup a group in the schema or imported schemas
4921 *
4922 * Returns the group definition or NULL if not found.
4923 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004924static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004925xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004926 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004927{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004928 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004929
4930 if ((name == NULL) || (schema == NULL))
4931 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004932 if (schema != NULL) {
4933 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004934 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004935exit:
Daniel Veillarddee23482008-04-11 12:58:43 +00004936
Daniel Veillard3646d642004-06-02 19:19:14 +00004937#ifdef DEBUG
4938 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004939 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004940 fprintf(stderr, "Unable to lookup group %s", name);
4941 else
4942 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004943 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004944 }
4945#endif
4946 return (ret);
4947}
4948
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004949static xmlSchemaNotationPtr
4950xmlSchemaGetNotation(xmlSchemaPtr schema,
4951 const xmlChar *name,
4952 const xmlChar *nsName)
4953{
4954 xmlSchemaNotationPtr ret = NULL;
4955
4956 if ((name == NULL) || (schema == NULL))
4957 return (NULL);
4958 if (schema != NULL) {
4959 WXS_FIND_GLOBAL_ITEM(notaDecl)
4960 }
4961exit:
4962 return (ret);
4963}
4964
4965static xmlSchemaIDCPtr
4966xmlSchemaGetIDC(xmlSchemaPtr schema,
4967 const xmlChar *name,
4968 const xmlChar *nsName)
4969{
4970 xmlSchemaIDCPtr ret = NULL;
4971
4972 if ((name == NULL) || (schema == NULL))
4973 return (NULL);
4974 if (schema != NULL) {
4975 WXS_FIND_GLOBAL_ITEM(idcDef)
4976 }
4977exit:
4978 return (ret);
4979}
4980
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004981/**
4982 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004983 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004984 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004985 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004986 *
4987 * Lookup a group in the schema or imported schemas
4988 *
4989 * Returns the group definition or NULL if not found.
4990 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004991static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004992xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4993 xmlSchemaTypeType itemType,
4994 const xmlChar *name,
4995 const xmlChar *targetNs)
4996{
4997 switch (itemType) {
4998 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004999 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005000 name, targetNs));
5001 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005002 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005003 name, targetNs));
5004 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005005 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005006 return (NULL);
5007 }
5008}
5009
Daniel Veillard4255d502002-04-16 15:50:10 +00005010/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005011 * *
5012 * Parsing functions *
5013 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 ************************************************************************/
5015
5016#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005017 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00005018
5019/**
5020 * xmlSchemaIsBlank:
5021 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005022 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00005023 *
5024 * Check if a string is ignorable
5025 *
5026 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5027 */
5028static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005029xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030{
Daniel Veillard4255d502002-04-16 15:50:10 +00005031 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005033 if (len < 0) {
5034 while (*str != 0) {
5035 if (!(IS_BLANK_CH(*str)))
5036 return (0);
5037 str++;
5038 }
5039 } else while ((*str != 0) && (len != 0)) {
5040 if (!(IS_BLANK_CH(*str)))
5041 return (0);
5042 str++;
5043 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00005044 }
Daniel Veillarddee23482008-04-11 12:58:43 +00005045
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005047}
5048
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005049#define WXS_COMP_NAME(c, t) ((t) (c))->name
5050#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5051/*
5052* xmlSchemaFindRedefCompInGraph:
5053* ATTENTION TODO: This uses pointer comp. for strings.
5054*/
5055static xmlSchemaBasicItemPtr
5056xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5057 xmlSchemaTypeType type,
5058 const xmlChar *name,
5059 const xmlChar *nsName)
5060{
5061 xmlSchemaBasicItemPtr ret;
5062 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005063
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005064 if ((bucket == NULL) || (name == NULL))
5065 return(NULL);
5066 if ((bucket->globals == NULL) ||
5067 (bucket->globals->nbItems == 0))
5068 goto subschemas;
5069 /*
5070 * Search in global components.
5071 */
5072 for (i = 0; i < bucket->globals->nbItems; i++) {
5073 ret = bucket->globals->items[i];
5074 if (ret->type == type) {
5075 switch (type) {
5076 case XML_SCHEMA_TYPE_COMPLEX:
5077 case XML_SCHEMA_TYPE_SIMPLE:
5078 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5079 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5080 nsName))
5081 {
5082 return(ret);
5083 }
5084 break;
5085 case XML_SCHEMA_TYPE_GROUP:
5086 if ((WXS_COMP_NAME(ret,
5087 xmlSchemaModelGroupDefPtr) == name) &&
5088 (WXS_COMP_TNS(ret,
5089 xmlSchemaModelGroupDefPtr) == nsName))
5090 {
5091 return(ret);
5092 }
5093 break;
5094 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5095 if ((WXS_COMP_NAME(ret,
5096 xmlSchemaAttributeGroupPtr) == name) &&
5097 (WXS_COMP_TNS(ret,
5098 xmlSchemaAttributeGroupPtr) == nsName))
5099 {
5100 return(ret);
5101 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005102 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005103 default:
5104 /* Should not be hit. */
5105 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005106 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005107 }
5108 }
5109subschemas:
5110 /*
5111 * Process imported/included schemas.
5112 */
5113 if (bucket->relations != NULL) {
5114 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5115
5116 /*
5117 * TODO: Marking the bucket will not avoid multiple searches
5118 * in the same schema, but avoids at least circularity.
5119 */
5120 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5121 do {
5122 if ((rel->bucket != NULL) &&
5123 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5124 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5125 type, name, nsName);
5126 if (ret != NULL)
5127 return(ret);
5128 }
5129 rel = rel->next;
5130 } while (rel != NULL);
5131 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5132 }
5133 return(NULL);
5134}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005135
5136/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005137 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005138 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005139 * @schema: the schema being built
5140 * @name: the item name
5141 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005142 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005143 * *WARNING* this interface is highly subject to change
5144 *
5145 * Returns the new struture or NULL in case of error
5146 */
5147static xmlSchemaNotationPtr
5148xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005149 const xmlChar *name, const xmlChar *nsName,
5150 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005151{
5152 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005153
5154 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5155 return (NULL);
5156
Daniel Veillard4255d502002-04-16 15:50:10 +00005157 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5158 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 return (NULL);
5161 }
5162 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005163 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005164 ret->name = name;
5165 ret->targetNamespace = nsName;
5166 /* TODO: do we need the node to be set?
5167 * ret->node = node;*/
5168 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005169 return (ret);
5170}
5171
Daniel Veillard4255d502002-04-16 15:50:10 +00005172/**
5173 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005174 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005175 * @schema: the schema being built
5176 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005177 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005178 *
5179 * Add an XML schema Attrribute declaration
5180 * *WARNING* this interface is highly subject to change
5181 *
5182 * Returns the new struture or NULL in case of error
5183 */
5184static xmlSchemaAttributePtr
5185xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005186 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005187 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005188{
5189 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005190
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005191 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005192 return (NULL);
5193
5194 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5195 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005196 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005197 return (NULL);
5198 }
5199 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005200 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5201 ret->node = node;
5202 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005203 ret->targetNamespace = nsName;
5204
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005205 if (topLevel)
5206 WXS_ADD_GLOBAL(ctxt, ret);
5207 else
5208 WXS_ADD_LOCAL(ctxt, ret);
5209 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005210 return (ret);
5211}
5212
5213/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005214 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005215 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 * @schema: the schema being built
5217 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005218 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005219 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005220 * Add an XML schema Attrribute declaration
5221 * *WARNING* this interface is highly subject to change
5222 *
5223 * Returns the new struture or NULL in case of error
5224 */
5225static xmlSchemaAttributeUsePtr
5226xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5227 xmlNodePtr node)
5228{
5229 xmlSchemaAttributeUsePtr ret = NULL;
5230
5231 if (pctxt == NULL)
5232 return (NULL);
5233
5234 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5235 if (ret == NULL) {
5236 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5237 return (NULL);
5238 }
5239 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5240 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5241 ret->node = node;
5242
5243 WXS_ADD_LOCAL(pctxt, ret);
5244 return (ret);
5245}
5246
5247/*
5248* xmlSchemaAddRedef:
5249*
5250* Adds a redefinition information. This is used at a later stage to:
5251* resolve references to the redefined components and to check constraints.
5252*/
5253static xmlSchemaRedefPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00005254xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005255 xmlSchemaBucketPtr targetBucket,
5256 void *item,
5257 const xmlChar *refName,
5258 const xmlChar *refTargetNs)
5259{
5260 xmlSchemaRedefPtr ret;
5261
5262 ret = (xmlSchemaRedefPtr)
5263 xmlMalloc(sizeof(xmlSchemaRedef));
5264 if (ret == NULL) {
5265 xmlSchemaPErrMemory(pctxt,
5266 "allocating redefinition info", NULL);
5267 return (NULL);
5268 }
5269 memset(ret, 0, sizeof(xmlSchemaRedef));
5270 ret->item = item;
5271 ret->targetBucket = targetBucket;
5272 ret->refName = refName;
5273 ret->refTargetNs = refTargetNs;
5274 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5275 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5276 else
5277 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5278 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5279
5280 return (ret);
5281}
5282
5283/**
5284 * xmlSchemaAddAttributeGroupDefinition:
5285 * @ctxt: a schema parser context
5286 * @schema: the schema being built
5287 * @name: the item name
5288 * @nsName: the target namespace
5289 * @node: the corresponding node
5290 *
5291 * Add an XML schema Attrribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005292 *
5293 * Returns the new struture or NULL in case of error
5294 */
5295static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005296xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5297 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5298 const xmlChar *name,
5299 const xmlChar *nsName,
5300 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005301{
5302 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005303
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005304 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005305 return (NULL);
5306
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005307 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005308 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005309 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005310 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005311 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005312 }
5313 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005314 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005315 ret->name = name;
5316 ret->targetNamespace = nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +00005317 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005318
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005319 /* TODO: Remove the flag. */
5320 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5321 if (pctxt->isRedefine) {
5322 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5323 ret, name, nsName);
5324 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005325 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005326 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005327 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005328 pctxt->redefCounter = 0;
5329 }
5330 WXS_ADD_GLOBAL(pctxt, ret);
5331 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005332 return (ret);
5333}
5334
5335/**
5336 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005337 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 * @schema: the schema being built
5339 * @name: the type name
5340 * @namespace: the type namespace
5341 *
5342 * Add an XML schema Element declaration
5343 * *WARNING* this interface is highly subject to change
5344 *
5345 * Returns the new struture or NULL in case of error
5346 */
5347static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005348xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005349 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005350 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005351{
5352 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005353
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005354 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005355 return (NULL);
5356
Daniel Veillard4255d502002-04-16 15:50:10 +00005357 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5358 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005359 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005360 return (NULL);
5361 }
5362 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005363 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5364 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005365 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005366 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005367
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005368 if (topLevel)
5369 WXS_ADD_GLOBAL(ctxt, ret);
5370 else
5371 WXS_ADD_LOCAL(ctxt, ret);
5372 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 return (ret);
5374}
5375
5376/**
5377 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005378 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005379 * @schema: the schema being built
5380 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005381 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005382 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005383 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 * *WARNING* this interface is highly subject to change
5385 *
5386 * Returns the new struture or NULL in case of error
5387 */
5388static xmlSchemaTypePtr
5389xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005390 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005391 const xmlChar * name, const xmlChar * nsName,
5392 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005393{
5394 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005395
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005396 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 return (NULL);
5398
5399 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5400 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005401 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005402 return (NULL);
5403 }
5404 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005405 ret->type = type;
5406 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005407 ret->targetNamespace = nsName;
5408 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005409 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005410 if (ctxt->isRedefine) {
5411 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5412 ret, name, nsName);
5413 if (ctxt->redef == NULL) {
5414 xmlFree(ret);
5415 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005416 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005417 ctxt->redefCounter = 0;
5418 }
5419 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005420 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005421 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005422 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005423 return (ret);
5424}
5425
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005426static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005427xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005428 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005429 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005430 const xmlChar *refNs)
5431{
5432 xmlSchemaQNameRefPtr ret;
5433
5434 ret = (xmlSchemaQNameRefPtr)
5435 xmlMalloc(sizeof(xmlSchemaQNameRef));
5436 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005437 xmlSchemaPErrMemory(pctxt,
5438 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005439 return (NULL);
5440 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005441 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005442 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5443 ret->name = refName;
5444 ret->targetNamespace = refNs;
5445 ret->item = NULL;
5446 ret->itemType = refType;
5447 /*
5448 * Store the reference item in the schema.
5449 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005450 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005451 return (ret);
5452}
5453
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005454static xmlSchemaAttributeUseProhibPtr
5455xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5456{
5457 xmlSchemaAttributeUseProhibPtr ret;
5458
5459 ret = (xmlSchemaAttributeUseProhibPtr)
5460 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5461 if (ret == NULL) {
5462 xmlSchemaPErrMemory(pctxt,
5463 "allocating attribute use prohibition", NULL);
5464 return (NULL);
5465 }
5466 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5467 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5468 WXS_ADD_LOCAL(pctxt, ret);
5469 return (ret);
5470}
5471
5472
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005473/**
5474 * xmlSchemaAddModelGroup:
5475 * @ctxt: a schema parser context
5476 * @schema: the schema being built
5477 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005478 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005479 *
5480 * Adds a schema model group
5481 * *WARNING* this interface is highly subject to change
5482 *
5483 * Returns the new struture or NULL in case of error
5484 */
5485static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005486xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5487 xmlSchemaPtr schema,
5488 xmlSchemaTypeType type,
5489 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005490{
5491 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005492
5493 if ((ctxt == NULL) || (schema == NULL))
5494 return (NULL);
5495
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005496 ret = (xmlSchemaModelGroupPtr)
5497 xmlMalloc(sizeof(xmlSchemaModelGroup));
5498 if (ret == NULL) {
5499 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5500 NULL);
5501 return (NULL);
5502 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005503 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005504 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005505 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005506 WXS_ADD_LOCAL(ctxt, ret);
5507 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5508 (type == XML_SCHEMA_TYPE_CHOICE))
5509 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005510 return (ret);
5511}
5512
5513
5514/**
5515 * xmlSchemaAddParticle:
5516 * @ctxt: a schema parser context
5517 * @schema: the schema being built
5518 * @node: the corresponding node in the schema doc
5519 * @min: the minOccurs
5520 * @max: the maxOccurs
5521 *
5522 * Adds an XML schema particle component.
5523 * *WARNING* this interface is highly subject to change
5524 *
5525 * Returns the new struture or NULL in case of error
5526 */
5527static xmlSchemaParticlePtr
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005528xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005529 xmlNodePtr node, int min, int max)
5530{
5531 xmlSchemaParticlePtr ret = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005532 if (ctxt == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005533 return (NULL);
5534
5535#ifdef DEBUG
5536 fprintf(stderr, "Adding particle component\n");
5537#endif
5538 ret = (xmlSchemaParticlePtr)
5539 xmlMalloc(sizeof(xmlSchemaParticle));
5540 if (ret == NULL) {
5541 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5542 NULL);
5543 return (NULL);
5544 }
5545 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5546 ret->annot = NULL;
5547 ret->node = node;
5548 ret->minOccurs = min;
5549 ret->maxOccurs = max;
5550 ret->next = NULL;
5551 ret->children = NULL;
5552
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005553 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005554 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005555 * Note that addition to pending components will be done locally
5556 * to the specific parsing function, since the most particles
5557 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005558 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005559 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005560 return (ret);
5561}
5562
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005563/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005564 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005565 * @ctxt: a schema validation context
5566 * @schema: the schema being built
5567 * @name: the group name
5568 *
5569 * Add an XML schema Group definition
5570 *
5571 * Returns the new struture or NULL in case of error
5572 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005573static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005574xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5575 xmlSchemaPtr schema,
5576 const xmlChar *name,
5577 const xmlChar *nsName,
5578 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005579{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005581
5582 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5583 return (NULL);
5584
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005585 ret = (xmlSchemaModelGroupDefPtr)
5586 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005587 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005588 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005589 return (NULL);
5590 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005591 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005592 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005593 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005594 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005595 ret->targetNamespace = nsName;
5596
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005597 if (ctxt->isRedefine) {
5598 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5599 ret, name, nsName);
5600 if (ctxt->redef == NULL) {
5601 xmlFree(ret);
5602 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005603 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005604 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005605 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005606 WXS_ADD_GLOBAL(ctxt, ret);
5607 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005608 return (ret);
5609}
5610
Daniel Veillard3646d642004-06-02 19:19:14 +00005611/**
5612 * xmlSchemaNewWildcardNs:
5613 * @ctxt: a schema validation context
5614 *
5615 * Creates a new wildcard namespace constraint.
5616 *
5617 * Returns the new struture or NULL in case of error
5618 */
5619static xmlSchemaWildcardNsPtr
5620xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5621{
5622 xmlSchemaWildcardNsPtr ret;
5623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005624 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005625 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5626 if (ret == NULL) {
5627 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005628 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005629 }
5630 ret->value = NULL;
5631 ret->next = NULL;
5632 return (ret);
5633}
5634
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005635static xmlSchemaIDCPtr
5636xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637 const xmlChar *name, const xmlChar *nsName,
5638 int category, xmlNodePtr node)
5639{
Daniel Veillarddee23482008-04-11 12:58:43 +00005640 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005641
5642 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5643 return (NULL);
5644
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005645 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5646 if (ret == NULL) {
5647 xmlSchemaPErrMemory(ctxt,
5648 "allocating an identity-constraint definition", NULL);
5649 return (NULL);
5650 }
5651 memset(ret, 0, sizeof(xmlSchemaIDC));
5652 /* The target namespace of the parent element declaration. */
5653 ret->targetNamespace = nsName;
5654 ret->name = name;
5655 ret->type = category;
Daniel Veillarddee23482008-04-11 12:58:43 +00005656 ret->node = node;
5657
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005658 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005659 /*
5660 * Only keyrefs need to be fixup up.
5661 */
5662 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005663 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005664 return (ret);
5665}
5666
Daniel Veillard3646d642004-06-02 19:19:14 +00005667/**
5668 * xmlSchemaAddWildcard:
5669 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005670 * @schema: a schema
5671 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005672 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005673 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005674 *
5675 * Returns the new struture or NULL in case of error
5676 */
5677static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005678xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5679 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005680{
5681 xmlSchemaWildcardPtr ret = NULL;
5682
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005683 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005684 return (NULL);
5685
5686 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5687 if (ret == NULL) {
5688 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5689 return (NULL);
5690 }
5691 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005692 ret->type = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00005693 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005694 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005695 return (ret);
5696}
5697
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005698static void
5699xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5700{
5701 if (group == NULL)
5702 return;
5703 if (group->members != NULL)
5704 xmlSchemaItemListFree(group->members);
5705 xmlFree(group);
5706}
5707
5708static xmlSchemaSubstGroupPtr
5709xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5710 xmlSchemaElementPtr head)
5711{
5712 xmlSchemaSubstGroupPtr ret;
5713
5714 /* Init subst group hash. */
5715 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5716 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5717 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5718 return(NULL);
5719 }
5720 /* Create a new substitution group. */
5721 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5722 if (ret == NULL) {
5723 xmlSchemaPErrMemory(NULL,
5724 "allocating a substitution group container", NULL);
5725 return(NULL);
5726 }
5727 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5728 ret->head = head;
5729 /* Create list of members. */
5730 ret->members = xmlSchemaItemListCreate();
5731 if (ret->members == NULL) {
5732 xmlSchemaSubstGroupFree(ret);
5733 return(NULL);
5734 }
5735 /* Add subst group to hash. */
5736 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5737 head->name, head->targetNamespace, ret) != 0) {
5738 PERROR_INT("xmlSchemaSubstGroupAdd",
5739 "failed to add a new substitution container");
5740 xmlSchemaSubstGroupFree(ret);
5741 return(NULL);
5742 }
5743 return(ret);
5744}
5745
5746static xmlSchemaSubstGroupPtr
5747xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5748 xmlSchemaElementPtr head)
Daniel Veillarddee23482008-04-11 12:58:43 +00005749{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005750 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5751 return(NULL);
5752 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5753 head->name, head->targetNamespace));
5754
5755}
5756
5757/**
5758 * xmlSchemaAddElementSubstitutionMember:
5759 * @pctxt: a schema parser context
5760 * @head: the head of the substitution group
5761 * @member: the new member of the substitution group
5762 *
5763 * Allocate a new annotation structure.
5764 *
5765 * Returns the newly allocated structure or NULL in case or error
5766 */
5767static int
5768xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5769 xmlSchemaElementPtr head,
5770 xmlSchemaElementPtr member)
5771{
5772 xmlSchemaSubstGroupPtr substGroup = NULL;
5773
5774 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5775 return (-1);
5776
5777 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5778 if (substGroup == NULL)
5779 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5780 if (substGroup == NULL)
5781 return(-1);
5782 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5783 return(-1);
5784 return(0);
5785}
5786
Daniel Veillard4255d502002-04-16 15:50:10 +00005787/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005788 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005789 * Utilities for parsing *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005790 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005791 ************************************************************************/
5792
Daniel Veillard4255d502002-04-16 15:50:10 +00005793/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005794 * xmlSchemaPValAttrNodeQNameValue:
5795 * @ctxt: a schema parser context
5796 * @schema: the schema context
5797 * @ownerDes: the designation of the parent element
5798 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005799 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005800 * @local: the resulting local part if found, the attribute value otherwise
5801 * @uri: the resulting namespace URI if found
5802 *
5803 * Extracts the local name and the URI of a QName value and validates it.
5804 * This one is intended to be used on attribute values that
5805 * should resolve to schema components.
5806 *
5807 * Returns 0, in case the QName is valid, a positive error code
5808 * if not valid and -1 if an internal error occurs.
5809 */
5810static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005811xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005812 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005813 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005814 xmlAttrPtr attr,
5815 const xmlChar *value,
5816 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 const xmlChar **local)
5818{
5819 const xmlChar *pref;
5820 xmlNsPtr ns;
5821 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005822
Daniel Veillardc0826a72004-08-10 14:17:33 +00005823 *uri = NULL;
5824 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005825 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005826 if (ret > 0) {
5827 xmlSchemaPSimpleTypeErr(ctxt,
5828 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5829 ownerItem, (xmlNodePtr) attr,
5830 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5831 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005832 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005833 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005834 } else if (ret < 0)
5835 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005836
5837 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005838 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005839 if (ns)
5840 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5841 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005842 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5843 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844 /*
5845 * This one takes care of included schemas with no
5846 * target namespace.
5847 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005848 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005849 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005850 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005851 return (0);
5852 }
5853 /*
5854 * At this point xmlSplitQName3 has to return a local name.
5855 */
5856 *local = xmlSplitQName3(value, &len);
5857 *local = xmlDictLookup(ctxt->dict, *local, -1);
5858 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005859 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5860 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005861 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005862 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005863 ownerItem, (xmlNodePtr) attr,
5864 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5865 "The value '%s' of simple type 'xs:QName' has no "
5866 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005867 return (ctxt->err);
5868 } else {
5869 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005870 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005871 return (0);
5872}
5873
5874/**
5875 * xmlSchemaPValAttrNodeQName:
5876 * @ctxt: a schema parser context
5877 * @schema: the schema context
5878 * @ownerDes: the designation of the owner element
5879 * @ownerItem: the owner as a schema object
5880 * @attr: the attribute node
5881 * @local: the resulting local part if found, the attribute value otherwise
5882 * @uri: the resulting namespace URI if found
5883 *
5884 * Extracts and validates the QName of an attribute value.
5885 * This one is intended to be used on attribute values that
5886 * should resolve to schema components.
5887 *
5888 * Returns 0, in case the QName is valid, a positive error code
5889 * if not valid and -1 if an internal error occurs.
5890 */
5891static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005892xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005893 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005894 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 xmlAttrPtr attr,
5896 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005897 const xmlChar **local)
5898{
5899 const xmlChar *value;
5900
5901 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005902 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005903 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005904}
5905
5906/**
5907 * xmlSchemaPValAttrQName:
5908 * @ctxt: a schema parser context
5909 * @schema: the schema context
5910 * @ownerDes: the designation of the parent element
5911 * @ownerItem: the owner as a schema object
5912 * @ownerElem: the parent node of the attribute
5913 * @name: the name of the attribute
5914 * @local: the resulting local part if found, the attribute value otherwise
5915 * @uri: the resulting namespace URI if found
5916 *
5917 * Extracts and validates the QName of an attribute value.
5918 *
5919 * Returns 0, in case the QName is valid, a positive error code
5920 * if not valid and -1 if an internal error occurs.
5921 */
5922static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005923xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5924 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005925 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005926 xmlNodePtr ownerElem,
5927 const char *name,
5928 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005929 const xmlChar **local)
5930{
5931 xmlAttrPtr attr;
5932
5933 attr = xmlSchemaGetPropNode(ownerElem, name);
5934 if (attr == NULL) {
5935 *local = NULL;
5936 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005938 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005939 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005940 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941}
5942
5943/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005944 * xmlSchemaPValAttrID:
5945 * @ctxt: a schema parser context
5946 * @schema: the schema context
5947 * @ownerDes: the designation of the parent element
5948 * @ownerItem: the owner as a schema object
5949 * @ownerElem: the parent node of the attribute
5950 * @name: the name of the attribute
5951 *
5952 * Extracts and validates the ID of an attribute value.
5953 *
5954 * Returns 0, in case the ID is valid, a positive error code
5955 * if not valid and -1 if an internal error occurs.
5956 */
5957static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005958xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005959{
5960 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005961 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005962
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005963 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005964 return(0);
5965 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5966 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005967 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005968 /*
5969 * NOTE: the IDness might have already be declared in the DTD
5970 */
5971 if (attr->atype != XML_ATTRIBUTE_ID) {
5972 xmlIDPtr res;
5973 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005974
5975 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005976 * TODO: Use xmlSchemaStrip here; it's not exported at this
5977 * moment.
5978 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005979 strip = xmlSchemaCollapseString(value);
5980 if (strip != NULL) {
5981 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005982 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005983 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005984 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005985 if (res == NULL) {
5986 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005987 xmlSchemaPSimpleTypeErr(ctxt,
5988 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005989 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005990 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5991 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005992 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005993 } else
5994 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005995 }
5996 } else if (ret > 0) {
5997 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005998 xmlSchemaPSimpleTypeErr(ctxt,
5999 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006000 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006001 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6002 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6003 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006004 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006005 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006006 if (value != NULL)
6007 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006008
6009 return (ret);
6010}
6011
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006012static int
6013xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6014 xmlNodePtr ownerElem,
6015 const xmlChar *name)
6016{
6017 xmlAttrPtr attr;
6018
6019 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6020 if (attr == NULL)
6021 return(0);
6022 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6023
6024}
6025
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006026/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006027 * xmlGetMaxOccurs:
6028 * @ctxt: a schema validation context
6029 * @node: a subtree containing XML Schema informations
6030 *
6031 * Get the maxOccurs property
6032 *
6033 * Returns the default if not found, or the value
6034 */
6035static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006036xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6037 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006039 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006040 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006041 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006042
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006043 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6044 if (attr == NULL)
6045 return (def);
6046 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006047
6048 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006049 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006050 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006051 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6052 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006053 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006054 val, NULL, NULL, NULL);
6055 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006056 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00006058 }
6059
6060 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006061 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006063 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006064 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006065 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6066 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006067 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006068 val, NULL, NULL, NULL);
6069 return (def);
6070 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006072 ret = ret * 10 + (*cur - '0');
6073 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006074 }
William M. Brack76e95df2003-10-18 16:20:14 +00006075 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006076 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006077 /*
6078 * TODO: Restrict the maximal value to Integer.
6079 */
6080 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006081 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006082 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6083 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006084 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006085 val, NULL, NULL, NULL);
6086 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006089}
6090
6091/**
6092 * xmlGetMinOccurs:
6093 * @ctxt: a schema validation context
6094 * @node: a subtree containing XML Schema informations
6095 *
6096 * Get the minOccurs property
6097 *
6098 * Returns the default if not found, or the value
6099 */
6100static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006101xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006102 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006103{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006104 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006105 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006106 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006107
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006108 attr = xmlSchemaGetPropNode(node, "minOccurs");
6109 if (attr == NULL)
6110 return (def);
6111 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006112 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006113 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006114 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006115 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006116 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006117 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6118 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006119 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006120 val, NULL, NULL, NULL);
6121 return (def);
6122 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006123 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006124 ret = ret * 10 + (*cur - '0');
6125 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006126 }
William M. Brack76e95df2003-10-18 16:20:14 +00006127 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006128 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006129 /*
6130 * TODO: Restrict the maximal value to Integer.
6131 */
6132 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006133 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006134 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6135 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006136 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006137 val, NULL, NULL, NULL);
6138 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006139 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006141}
6142
6143/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006144 * xmlSchemaPGetBoolNodeValue:
6145 * @ctxt: a schema validation context
6146 * @ownerDes: owner designation
6147 * @ownerItem: the owner as a schema item
6148 * @node: the node holding the value
6149 *
6150 * Converts a boolean string value into 1 or 0.
6151 *
6152 * Returns 0 or 1.
6153 */
6154static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006155xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006156 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006157 xmlNodePtr node)
6158{
6159 xmlChar *value = NULL;
6160 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006161
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006162 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006163 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006164 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006165 * An instance of a datatype that is defined as `boolean`
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006166 * can have the following legal literals {true, false, 1, 0}.
6167 */
6168 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6169 res = 1;
6170 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6171 res = 0;
6172 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6173 res = 1;
6174 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006175 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006176 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006177 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006178 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 ownerItem, node,
6180 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6181 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006182 NULL, NULL, NULL);
6183 }
6184 if (value != NULL)
6185 xmlFree(value);
6186 return (res);
6187}
6188
6189/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006190 * xmlGetBooleanProp:
6191 * @ctxt: a schema validation context
6192 * @node: a subtree containing XML Schema informations
6193 * @name: the attribute name
6194 * @def: the default value
6195 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006196 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006197 *
6198 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006199 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006200 */
6201static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006202xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006204 const char *name, int def)
6205{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006206 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006207
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006208 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006209 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006210 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006211 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006212 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006213 * An instance of a datatype that is defined as `boolean`
Daniel Veillardc0826a72004-08-10 14:17:33 +00006214 * can have the following legal literals {true, false, 1, 0}.
6215 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006216 if (xmlStrEqual(val, BAD_CAST "true"))
6217 def = 1;
6218 else if (xmlStrEqual(val, BAD_CAST "false"))
6219 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006220 else if (xmlStrEqual(val, BAD_CAST "1"))
6221 def = 1;
6222 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006223 def = 0;
6224 else {
6225 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006226 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006227 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006228 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006229 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6230 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006231 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006232 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006233}
6234
6235/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006236 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 * Shema extraction from an Infoset *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006238 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00006239 ************************************************************************/
6240static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6241 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006242 xmlNodePtr node,
6243 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006244static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6245 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006246 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006247 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006248 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006249static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6250 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006251 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006252 xmlNodePtr node,
6253 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006254static xmlSchemaBasicItemPtr
6255xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6256 xmlSchemaPtr schema,
6257 xmlNodePtr node,
6258 xmlSchemaItemListPtr uses,
6259 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006260static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6261 xmlSchemaPtr schema,
6262 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006263static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006264xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6265 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006266
6267/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006268 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00006270 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006271 * @ownerDes: the designation of the parent element
6272 * @ownerItem: the schema object owner if existent
6273 * @attr: the schema attribute node being validated
6274 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006275 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006276 *
6277 * Validates a value against the given built-in type.
6278 * This one is intended to be used internally for validation
6279 * of schema attribute values during parsing of the schema.
6280 *
6281 * Returns 0 if the value is valid, a positive error code
6282 * number otherwise and -1 in case of an internal or API error.
6283 */
6284static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006285xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006286 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006287 xmlAttrPtr attr,
6288 const xmlChar *value,
6289 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006290{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006291
6292 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006293
6294 /*
6295 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6296 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006297 */
6298 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006299 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006300 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6301 PERROR_INT("xmlSchemaPValAttrNodeValue",
6302 "the given type is not a built-in type");
6303 return (-1);
6304 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006305 switch (type->builtInType) {
6306 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006307 case XML_SCHEMAS_QNAME:
6308 case XML_SCHEMAS_ANYURI:
6309 case XML_SCHEMAS_TOKEN:
6310 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006311 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6312 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006313 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006314 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006316 "validation using the given type is not supported while "
6317 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006318 return (-1);
6319 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006320 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006321 /*
6322 * TODO: Should we use the S4S error codes instead?
6323 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006324 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 PERROR_INT("xmlSchemaPValAttrNodeValue",
6326 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006327 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006328 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006329 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006330 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6331 else
6332 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +00006333 xmlSchemaPSimpleTypeErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 ret, ownerItem, (xmlNodePtr) attr,
6335 type, NULL, value, NULL, NULL, NULL);
6336 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006337 return (ret);
6338}
6339
6340/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006341 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006343 * @ctxt: a schema parser context
6344 * @ownerDes: the designation of the parent element
6345 * @ownerItem: the schema object owner if existent
6346 * @attr: the schema attribute node being validated
6347 * @type: the built-in type to be validated against
6348 * @value: the resulting value if any
6349 *
6350 * Extracts and validates a value against the given built-in type.
6351 * This one is intended to be used internally for validation
6352 * of schema attribute values during parsing of the schema.
6353 *
6354 * Returns 0 if the value is valid, a positive error code
6355 * number otherwise and -1 in case of an internal or API error.
6356 */
6357static int
6358xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006359 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006360 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006361 xmlSchemaTypePtr type,
6362 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006363{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006364 const xmlChar *val;
6365
6366 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 return (-1);
6368
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6370 if (value != NULL)
6371 *value = val;
6372
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006373 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375}
6376
6377/**
6378 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006379 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006380 * @ctxt: a schema parser context
6381 * @node: the element node of the attribute
6382 * @ownerDes: the designation of the parent element
6383 * @ownerItem: the schema object owner if existent
6384 * @ownerElem: the owner element node
6385 * @name: the name of the schema attribute node
6386 * @type: the built-in type to be validated against
6387 * @value: the resulting value if any
6388 *
6389 * Extracts and validates a value against the given built-in type.
6390 * This one is intended to be used internally for validation
6391 * of schema attribute values during parsing of the schema.
6392 *
6393 * Returns 0 if the value is valid, a positive error code
6394 * number otherwise and -1 in case of an internal or API error.
6395 */
6396static int
Daniel Veillarddee23482008-04-11 12:58:43 +00006397xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006398 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399 xmlNodePtr ownerElem,
6400 const char *name,
6401 xmlSchemaTypePtr type,
6402 const xmlChar **value)
6403{
6404 xmlAttrPtr attr;
6405
6406 if ((ctxt == NULL) || (type == NULL)) {
6407 if (value != NULL)
6408 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006409 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006410 }
6411 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6412 if (value != NULL)
6413 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006414 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006415 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006416 "Internal error: xmlSchemaPValAttr, the given "
6417 "type '%s' is not a built-in type.\n",
6418 type->name, NULL);
6419 return (-1);
6420 }
6421 attr = xmlSchemaGetPropNode(ownerElem, name);
6422 if (attr == NULL) {
6423 if (value != NULL)
6424 *value = NULL;
6425 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006427 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006428 type, value));
6429}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006430
6431static int
6432xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006433 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006434 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006435 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006436 const xmlChar *namespaceName)
6437{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006438 /* TODO: Pointer comparison instead? */
6439 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006440 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006441 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006442 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006443 /*
6444 * Check if the referenced namespace was <import>ed.
6445 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006446 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006447 xmlSchemaSchemaRelationPtr rel;
6448
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006449 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006450 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006451 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006452 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006453 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006454 rel = rel->next;
6455 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006456 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006457 /*
6458 * No matching <import>ed namespace found.
6459 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006460 {
6461 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6462
6463 if (namespaceName == NULL)
6464 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6465 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6466 "References from this schema to components in no "
6467 "namespace are not allowed, since not indicated by an "
6468 "import statement", NULL, NULL);
6469 else
6470 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6471 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6472 "References from this schema to components in the "
6473 "namespace '%s' are not allowed, since not indicated by an "
6474 "import statement", namespaceName, NULL);
6475 }
6476 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006477}
6478
Daniel Veillardc0826a72004-08-10 14:17:33 +00006479/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006480 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006481 * @ctxt: a schema validation context
6482 * @schema: the schema being built
6483 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006484 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006485 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006486 * Parses attribute uses and attribute declarations and
Daniel Veillarddee23482008-04-11 12:58:43 +00006487 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006488 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006489static int
6490xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6491 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6492 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006493{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006494 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006495
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006496 while ((IS_SCHEMA((*child), "attribute")) ||
6497 (IS_SCHEMA((*child), "attributeGroup"))) {
6498 if (IS_SCHEMA((*child), "attribute")) {
6499 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6500 *list, parentType);
6501 } else {
6502 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6503 if ((item != NULL) && (hasRefs != NULL))
6504 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006505 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006506 if (item != NULL) {
6507 if (*list == NULL) {
6508 /* TODO: Customize grow factor. */
6509 *list = xmlSchemaItemListCreate();
6510 if (*list == NULL)
6511 return(-1);
6512 }
6513 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6514 return(-1);
6515 }
6516 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006517 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006518 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006519}
6520
6521/**
6522 * xmlSchemaParseAnnotation:
6523 * @ctxt: a schema validation context
6524 * @schema: the schema being built
6525 * @node: a subtree containing XML Schema informations
6526 *
6527 * parse a XML schema Attrribute declaration
6528 * *WARNING* this interface is highly subject to change
6529 *
William M. Bracke7091952004-05-11 15:09:58 +00006530 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006531 * 1 in case of success.
6532 */
6533static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006534xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006535{
6536 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 xmlNodePtr child = NULL;
6538 xmlAttrPtr attr;
6539 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006540
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 /*
6542 * INFO: S4S completed.
6543 */
6544 /*
6545 * id = ID
6546 * {any attributes with non-schema namespace . . .}>
6547 * Content: (appinfo | documentation)*
6548 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006549 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006551 if (needed)
6552 ret = xmlSchemaNewAnnot(ctxt, node);
6553 else
6554 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006555 attr = node->properties;
6556 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006557 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006558 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006559 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006561
6562 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006563 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 }
6565 attr = attr->next;
6566 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006567 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 /*
6569 * And now for the children...
6570 */
6571 child = node->children;
6572 while (child != NULL) {
6573 if (IS_SCHEMA(child, "appinfo")) {
6574 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006575 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006576 * source = anyURI
6577 * {any attributes with non-schema namespace . . .}>
6578 * Content: ({any})*
6579 */
6580 attr = child->properties;
6581 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006582 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006583 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006584 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006585 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006586
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006587 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006588 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589 }
6590 attr = attr->next;
6591 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006592 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006593 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006594 child = child->next;
6595 } else if (IS_SCHEMA(child, "documentation")) {
6596 /* TODO: make available the content of "documentation". */
6597 /*
6598 * source = anyURI
6599 * {any attributes with non-schema namespace . . .}>
6600 * Content: ({any})*
6601 */
6602 attr = child->properties;
6603 while (attr != NULL) {
6604 if (attr->ns == NULL) {
6605 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006606 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006607 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 }
6609 } else {
6610 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6611 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6612 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006613
6614 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006616 }
6617 }
6618 attr = attr->next;
6619 }
6620 /*
6621 * Attribute "xml:lang".
6622 */
6623 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6624 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006625 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006626 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006627 child = child->next;
6628 } else {
6629 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006630 xmlSchemaPContentErr(ctxt,
6631 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006632 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006633 barked = 1;
6634 child = child->next;
6635 }
6636 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 return (ret);
6639}
6640
6641/**
6642 * xmlSchemaParseFacet:
6643 * @ctxt: a schema validation context
6644 * @schema: the schema being built
6645 * @node: a subtree containing XML Schema informations
6646 *
6647 * parse a XML schema Facet declaration
6648 * *WARNING* this interface is highly subject to change
6649 *
6650 * Returns the new type structure or NULL in case of error
6651 */
6652static xmlSchemaFacetPtr
6653xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006654 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006655{
6656 xmlSchemaFacetPtr facet;
6657 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006658 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006659
6660 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6661 return (NULL);
6662
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006663 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006664 if (facet == NULL) {
6665 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6666 return (NULL);
6667 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006668 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006669 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006670 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006671 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6672 "Facet %s has no value\n", node->name, NULL);
6673 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006674 return (NULL);
6675 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006676 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006677 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006678 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006679 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006680 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006681 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006682 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006683 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006684 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006685 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006686 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006687 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006688 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006689 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006690 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006691 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006692 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006694 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006695 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006696 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6698 } else if (IS_SCHEMA(node, "minLength")) {
6699 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6700 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006701 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6702 "Unknown facet type %s\n", node->name, NULL);
6703 xmlSchemaFreeFacet(facet);
6704 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006706 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006707 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006708 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6709 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6710 const xmlChar *fixed;
6711
6712 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6713 if (fixed != NULL) {
6714 if (xmlStrEqual(fixed, BAD_CAST "true"))
6715 facet->fixed = 1;
6716 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006717 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006718 child = node->children;
6719
6720 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006721 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006722 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006723 }
6724 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006725 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6726 "Facet %s has unexpected child content\n",
6727 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006728 }
6729 return (facet);
6730}
6731
6732/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 * xmlSchemaParseWildcardNs:
6734 * @ctxt: a schema parser context
6735 * @wildc: the wildcard, already created
6736 * @node: a subtree containing XML Schema informations
6737 *
6738 * Parses the attribute "processContents" and "namespace"
6739 * of a xsd:anyAttribute and xsd:any.
6740 * *WARNING* this interface is highly subject to change
6741 *
6742 * Returns 0 if everything goes fine, a positive error code
6743 * if something is not valid and -1 if an internal error occurs.
6744 */
6745static int
6746xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006747 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 xmlSchemaWildcardPtr wildc,
6749 xmlNodePtr node)
6750{
6751 const xmlChar *pc, *ns, *dictnsItem;
6752 int ret = 0;
6753 xmlChar *nsItem;
6754 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6755 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6758 if ((pc == NULL)
6759 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6760 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6761 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6762 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6763 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6764 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6765 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006767 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006768 NULL, node,
6769 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006770 NULL, NULL, NULL);
6771 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006772 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 }
6774 /*
6775 * Build the namespace constraints.
6776 */
6777 attr = xmlSchemaGetPropNode(node, "namespace");
6778 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006779 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 wildc->any = 1;
6781 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6782 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 return (-1);
6785 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006786 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006788 const xmlChar *end, *cur;
6789
6790 cur = ns;
6791 do {
6792 while (IS_BLANK_CH(*cur))
6793 cur++;
6794 end = cur;
6795 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6796 end++;
6797 if (end == cur)
6798 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006800 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6801 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 NULL, (xmlNodePtr) attr,
6805 NULL,
6806 "((##any | ##other) | List of (xs:anyURI | "
6807 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006808 nsItem, NULL, NULL, NULL);
6809 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6810 } else {
6811 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006812 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006813 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6814 dictnsItem = NULL;
6815 } else {
6816 /*
6817 * Validate the item (anyURI).
6818 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006819 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006820 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6821 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6822 }
6823 /*
6824 * Avoid dublicate namespaces.
6825 */
6826 tmp = wildc->nsSet;
6827 while (tmp != NULL) {
6828 if (dictnsItem == tmp->value)
6829 break;
6830 tmp = tmp->next;
6831 }
6832 if (tmp == NULL) {
6833 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6834 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006835 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006836 return (-1);
6837 }
6838 tmp->value = dictnsItem;
6839 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 wildc->nsSet = tmp;
Daniel Veillard76d36452009-09-07 11:19:33 +02006842 else if (lastNs != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006843 lastNs->next = tmp;
6844 lastNs = tmp;
6845 }
6846
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006848 xmlFree(nsItem);
6849 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 }
6852 return (ret);
6853}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006854
6855static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006856xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6857 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006858 xmlNodePtr node,
6859 int minOccurs,
6860 int maxOccurs) {
6861
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006862 if ((maxOccurs == 0) && ( minOccurs == 0))
6863 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006864 if (maxOccurs != UNBOUNDED) {
6865 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 * TODO: Maybe we should better not create the particle,
6867 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006868 * content model.
6869 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006870 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006871 * 3.9.6 Schema Component Constraint: Particle Correct
6872 *
6873 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006874 if (maxOccurs < 1) {
6875 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006876 * 2.2 {max occurs} must be greater than or equal to 1.
6877 */
6878 xmlSchemaPCustomAttrErr(ctxt,
6879 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006880 NULL, NULL,
6881 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006882 "The value must be greater than or equal to 1");
6883 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6884 } else if (minOccurs > maxOccurs) {
6885 /*
6886 * 2.1 {min occurs} must not be greater than {max occurs}.
6887 */
6888 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006889 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006890 NULL, NULL,
6891 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006892 "The value must not be greater than the value of 'maxOccurs'");
6893 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6894 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006895 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006896 return (0);
6897}
6898
Daniel Veillardc0826a72004-08-10 14:17:33 +00006899/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006900 * xmlSchemaParseAny:
6901 * @ctxt: a schema validation context
6902 * @schema: the schema being built
6903 * @node: a subtree containing XML Schema informations
6904 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006905 * Parsea a XML schema <any> element. A particle and wildcard
6906 * will be created (except if minOccurs==maxOccurs==0, in this case
6907 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006908 * *WARNING* this interface is highly subject to change
6909 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006910 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006911 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006912static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006913xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6914 xmlNodePtr node)
6915{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006917 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006918 xmlSchemaWildcardPtr wild;
6919 int min, max;
6920 xmlAttrPtr attr;
6921 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006922
6923 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6924 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006925 /*
6926 * Check for illegal attributes.
6927 */
6928 attr = node->properties;
6929 while (attr != NULL) {
6930 if (attr->ns == NULL) {
6931 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6932 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6933 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6934 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6935 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006936 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006937 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006938 }
6939 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006940 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006941 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006942 }
6943 attr = attr->next;
6944 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006945 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006946 /*
6947 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006948 */
6949 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6950 "(xs:nonNegativeInteger | unbounded)");
6951 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6952 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006953 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6954 /*
6955 * Create & parse the wildcard.
6956 */
6957 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6958 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006959 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006960 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006961 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006962 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006964 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006965 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006966 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006967 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006968 }
6969 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006970 xmlSchemaPContentErr(ctxt,
6971 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006972 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006973 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006974 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006975 /*
6976 * No component if minOccurs==maxOccurs==0.
6977 */
6978 if ((min == 0) && (max == 0)) {
6979 /* Don't free the wildcard, since it's already on the list. */
6980 return (NULL);
6981 }
6982 /*
6983 * Create the particle.
6984 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00006985 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006986 if (particle == NULL)
6987 return (NULL);
6988 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006989 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006991 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006992}
6993
6994/**
6995 * xmlSchemaParseNotation:
6996 * @ctxt: a schema validation context
6997 * @schema: the schema being built
6998 * @node: a subtree containing XML Schema informations
6999 *
7000 * parse a XML schema Notation declaration
7001 *
7002 * Returns the new structure or NULL in case of error
7003 */
7004static xmlSchemaNotationPtr
7005xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007006 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007007{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007008 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007009 xmlSchemaNotationPtr ret;
7010 xmlNodePtr child = NULL;
7011
7012 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7013 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007014 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007015 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007016 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7017 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007018 return (NULL);
7019 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007020 ret = xmlSchemaAddNotation(ctxt, schema, name,
7021 ctxt->targetNamespace, node);
7022 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00007023 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007024 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007025
Daniel Veillard4255d502002-04-16 15:50:10 +00007026 child = node->children;
7027 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007028 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007030 }
7031 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007032 xmlSchemaPContentErr(ctxt,
7033 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007034 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007035 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 }
7037
7038 return (ret);
7039}
7040
7041/**
7042 * xmlSchemaParseAnyAttribute:
7043 * @ctxt: a schema validation context
7044 * @schema: the schema being built
7045 * @node: a subtree containing XML Schema informations
7046 *
7047 * parse a XML schema AnyAttrribute declaration
7048 * *WARNING* this interface is highly subject to change
7049 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007050 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00007051 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007052static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7054 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007055{
Daniel Veillard3646d642004-06-02 19:19:14 +00007056 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007057 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007058 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007059
7060 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7061 return (NULL);
7062
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007063 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7064 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007065 if (ret == NULL) {
7066 return (NULL);
7067 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007068 /*
7069 * Check for illegal attributes.
7070 */
7071 attr = node->properties;
7072 while (attr != NULL) {
7073 if (attr->ns == NULL) {
7074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7075 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7076 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007077 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007078 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007079 }
7080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007081 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007083 }
7084 attr = attr->next;
7085 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007086 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007087 /*
7088 * Parse the namespace list.
7089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007090 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007091 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007092 /*
7093 * And now for the children...
7094 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007095 child = node->children;
7096 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007097 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007099 }
7100 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007101 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007102 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007103 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007104 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007105 }
7106
7107 return (ret);
7108}
7109
7110
7111/**
7112 * xmlSchemaParseAttribute:
7113 * @ctxt: a schema validation context
7114 * @schema: the schema being built
7115 * @node: a subtree containing XML Schema informations
7116 *
7117 * parse a XML schema Attrribute declaration
7118 * *WARNING* this interface is highly subject to change
7119 *
William M. Bracke7091952004-05-11 15:09:58 +00007120 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007121 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007122static xmlSchemaBasicItemPtr
7123xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7124 xmlSchemaPtr schema,
7125 xmlNodePtr node,
7126 xmlSchemaItemListPtr uses,
7127 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007128{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007129 const xmlChar *attrValue, *name = NULL, *ns = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007130 xmlSchemaAttributeUsePtr use = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007131 xmlNodePtr child = NULL;
7132 xmlAttrPtr attr;
7133 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7134 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7135 int nberrors, hasForm = 0, defValueType = 0;
7136
7137#define WXS_ATTR_DEF_VAL_DEFAULT 1
7138#define WXS_ATTR_DEF_VAL_FIXED 2
7139
7140 /*
7141 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7142 */
7143
7144 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7145 return (NULL);
7146 attr = xmlSchemaGetPropNode(node, "ref");
7147 if (attr != NULL) {
7148 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7149 NULL, attr, &tmpNs, &tmpName) != 0) {
7150 return (NULL);
7151 }
7152 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7153 return(NULL);
7154 isRef = 1;
7155 }
7156 nberrors = pctxt->nberrors;
7157 /*
7158 * Check for illegal attributes.
7159 */
7160 attr = node->properties;
7161 while (attr != NULL) {
7162 if (attr->ns == NULL) {
7163 if (isRef) {
7164 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7165 xmlSchemaPValAttrNodeID(pctxt, attr);
7166 goto attr_next;
7167 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7168 goto attr_next;
7169 }
7170 } else {
7171 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7172 goto attr_next;
7173 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7174 xmlSchemaPValAttrNodeID(pctxt, attr);
7175 goto attr_next;
7176 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7177 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7178 attr, &tmpNs, &tmpName);
7179 goto attr_next;
7180 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7181 /*
7182 * Evaluate the target namespace
7183 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007184 hasForm = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007185 attrValue = xmlSchemaGetNodeContent(pctxt,
7186 (xmlNodePtr) attr);
7187 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7188 ns = pctxt->targetNamespace;
7189 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7190 {
7191 xmlSchemaPSimpleTypeErr(pctxt,
7192 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7193 NULL, (xmlNodePtr) attr,
7194 NULL, "(qualified | unqualified)",
7195 attrValue, NULL, NULL, NULL);
7196 }
7197 goto attr_next;
7198 }
7199 }
7200 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7201
7202 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7203 /* TODO: Maybe we need to normalize the value beforehand. */
7204 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7205 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7206 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7207 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7208 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7209 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7210 else {
7211 xmlSchemaPSimpleTypeErr(pctxt,
7212 XML_SCHEMAP_INVALID_ATTR_USE,
7213 NULL, (xmlNodePtr) attr,
7214 NULL, "(optional | prohibited | required)",
7215 attrValue, NULL, NULL, NULL);
7216 }
7217 goto attr_next;
7218 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7219 /*
7220 * 3.2.3 : 1
7221 * default and fixed must not both be present.
7222 */
7223 if (defValue) {
7224 xmlSchemaPMutualExclAttrErr(pctxt,
7225 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7226 NULL, attr, "default", "fixed");
7227 } else {
7228 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7229 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7230 }
7231 goto attr_next;
7232 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7233 /*
7234 * 3.2.3 : 1
7235 * default and fixed must not both be present.
7236 */
7237 if (defValue) {
7238 xmlSchemaPMutualExclAttrErr(pctxt,
7239 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7240 NULL, attr, "default", "fixed");
7241 } else {
7242 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7243 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7244 }
7245 goto attr_next;
7246 }
7247 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7248 goto attr_next;
7249
7250 xmlSchemaPIllegalAttrErr(pctxt,
7251 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7252
7253attr_next:
7254 attr = attr->next;
Daniel Veillarddee23482008-04-11 12:58:43 +00007255 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007256 /*
7257 * 3.2.3 : 2
7258 * If default and use are both present, use must have
7259 * the actual value optional.
7260 */
7261 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7262 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7263 xmlSchemaPSimpleTypeErr(pctxt,
7264 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7265 NULL, node, NULL,
7266 "(optional | prohibited | required)", NULL,
7267 "The value of the attribute 'use' must be 'optional' "
7268 "if the attribute 'default' is present",
7269 NULL, NULL);
7270 }
7271 /*
7272 * We want correct attributes.
7273 */
7274 if (nberrors != pctxt->nberrors)
7275 return(NULL);
7276 if (! isRef) {
7277 xmlSchemaAttributePtr attrDecl;
7278
7279 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7280 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
Daniel Veillarddee23482008-04-11 12:58:43 +00007281 ns = pctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007282 /*
7283 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7284 * TODO: Move this to the component layer.
7285 */
7286 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7287 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7288 XML_SCHEMAP_NO_XSI,
7289 node, NULL,
7290 "The target namespace must not match '%s'",
7291 xmlSchemaInstanceNs, NULL);
7292 }
7293 attr = xmlSchemaGetPropNode(node, "name");
7294 if (attr == NULL) {
7295 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7296 NULL, node, "name", NULL);
7297 return (NULL);
7298 }
7299 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7300 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7301 return (NULL);
7302 }
7303 /*
7304 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7305 * TODO: Move this to the component layer.
7306 */
7307 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7308 xmlSchemaPSimpleTypeErr(pctxt,
7309 XML_SCHEMAP_NO_XMLNS,
7310 NULL, (xmlNodePtr) attr,
7311 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7312 "The value of the attribute must not match 'xmlns'",
7313 NULL, NULL);
7314 return (NULL);
7315 }
7316 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7317 goto check_children;
7318 /*
7319 * Create the attribute use component.
7320 */
7321 use = xmlSchemaAddAttributeUse(pctxt, node);
7322 if (use == NULL)
7323 return(NULL);
7324 use->occurs = occurs;
7325 /*
7326 * Create the attribute declaration.
7327 */
7328 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7329 if (attrDecl == NULL)
7330 return (NULL);
7331 if (tmpName != NULL) {
7332 attrDecl->typeName = tmpName;
7333 attrDecl->typeNs = tmpNs;
7334 }
7335 use->attrDecl = attrDecl;
7336 /*
7337 * Value constraint.
Daniel Veillarddee23482008-04-11 12:58:43 +00007338 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007339 if (defValue != NULL) {
7340 attrDecl->defValue = defValue;
7341 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7342 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7343 }
7344 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7345 xmlSchemaQNameRefPtr ref;
7346
7347 /*
7348 * Create the attribute use component.
7349 */
7350 use = xmlSchemaAddAttributeUse(pctxt, node);
7351 if (use == NULL)
7352 return(NULL);
7353 /*
7354 * We need to resolve the reference at later stage.
7355 */
7356 WXS_ADD_PENDING(pctxt, use);
7357 use->occurs = occurs;
7358 /*
7359 * Create a QName reference to the attribute declaration.
7360 */
7361 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7362 tmpName, tmpNs);
7363 if (ref == NULL)
7364 return(NULL);
7365 /*
7366 * Assign the reference. This will be substituted for the
7367 * referenced attribute declaration when the QName is resolved.
7368 */
7369 use->attrDecl = WXS_ATTR_CAST ref;
7370 /*
7371 * Value constraint.
7372 */
7373 if (defValue != NULL)
7374 use->defValue = defValue;
7375 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7376 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7377 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007378
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007379check_children:
7380 /*
7381 * And now for the children...
7382 */
7383 child = node->children;
7384 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007385 xmlSchemaAttributeUseProhibPtr prohib;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007386
7387 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007388 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007389 child = child->next;
7390 }
7391 if (child != NULL) {
7392 xmlSchemaPContentErr(pctxt,
7393 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7394 NULL, node, child, NULL,
7395 "(annotation?)");
7396 }
7397 /*
7398 * Check for pointlessness of attribute prohibitions.
7399 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007400 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007401 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7402 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7403 node, NULL,
7404 "Skipping attribute use prohibition, since it is "
7405 "pointless inside an <attributeGroup>",
7406 NULL, NULL, NULL);
7407 return(NULL);
7408 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7409 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7410 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7411 node, NULL,
7412 "Skipping attribute use prohibition, since it is "
7413 "pointless when extending a type",
7414 NULL, NULL, NULL);
7415 return(NULL);
7416 }
7417 if (! isRef) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007418 tmpName = name;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007419 tmpNs = ns;
7420 }
7421 /*
7422 * Check for duplicate attribute prohibitions.
7423 */
7424 if (uses) {
7425 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00007426
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007427 for (i = 0; i < uses->nbItems; i++) {
7428 use = uses->items[i];
7429 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7430 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7431 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7432 {
7433 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007434
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007435 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7436 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7437 node, NULL,
7438 "Skipping duplicate attribute use prohibition '%s'",
7439 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7440 NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007441 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007442 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007443 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007444 }
7445 }
7446 /*
7447 * Create the attribute prohibition helper component.
7448 */
7449 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7450 if (prohib == NULL)
7451 return(NULL);
7452 prohib->node = node;
7453 prohib->name = tmpName;
7454 prohib->targetNamespace = tmpNs;
7455 if (isRef) {
7456 /*
7457 * We need at least to resolve to the attribute declaration.
7458 */
7459 WXS_ADD_PENDING(pctxt, prohib);
7460 }
7461 return(WXS_BASIC_CAST prohib);
Daniel Veillarddee23482008-04-11 12:58:43 +00007462 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007463 if (IS_SCHEMA(child, "annotation")) {
7464 /*
7465 * TODO: Should this go into the attr decl?
7466 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007467 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007468 child = child->next;
7469 }
7470 if (isRef) {
7471 if (child != NULL) {
7472 if (IS_SCHEMA(child, "simpleType"))
7473 /*
7474 * 3.2.3 : 3.2
7475 * If ref is present, then all of <simpleType>,
7476 * form and type must be absent.
7477 */
7478 xmlSchemaPContentErr(pctxt,
7479 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7480 NULL, node, child, NULL,
7481 "(annotation?)");
7482 else
7483 xmlSchemaPContentErr(pctxt,
7484 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7485 NULL, node, child, NULL,
7486 "(annotation?)");
7487 }
7488 } else {
7489 if (IS_SCHEMA(child, "simpleType")) {
7490 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7491 /*
7492 * 3.2.3 : 4
7493 * type and <simpleType> must not both be present.
7494 */
7495 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7496 NULL, node, child,
7497 "The attribute 'type' and the <simpleType> child "
7498 "are mutually exclusive", NULL);
7499 } else
7500 WXS_ATTRUSE_TYPEDEF(use) =
7501 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7502 child = child->next;
7503 }
7504 if (child != NULL)
7505 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7506 NULL, node, child, NULL,
7507 "(annotation?, simpleType?)");
7508 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007509 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007510 return (WXS_BASIC_CAST use);
7511}
7512
7513
7514static xmlSchemaAttributePtr
7515xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7516 xmlSchemaPtr schema,
7517 xmlNodePtr node)
7518{
7519 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007520 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007521 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007522 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007523
7524 /*
7525 * Note that the w3c spec assumes the schema to be validated with schema
7526 * for schemas beforehand.
7527 *
7528 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007529 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007530 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00007531 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007532 /*
7533 * 3.2.3 : 3.1
7534 * One of ref or name must be present, but not both
7535 */
7536 attr = xmlSchemaGetPropNode(node, "name");
7537 if (attr == NULL) {
7538 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7539 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 return (NULL);
7541 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007542 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7543 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7544 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007545 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007546 /*
7547 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7548 * TODO: Move this to the component layer.
7549 */
7550 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7551 xmlSchemaPSimpleTypeErr(pctxt,
7552 XML_SCHEMAP_NO_XMLNS,
7553 NULL, (xmlNodePtr) attr,
7554 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7555 "The value of the attribute must not match 'xmlns'",
7556 NULL, NULL);
7557 return (NULL);
7558 }
7559 /*
7560 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7561 * TODO: Move this to the component layer.
7562 * Or better leave it here and add it to the component layer
7563 * if we have a schema construction API.
7564 */
7565 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7566 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7567 XML_SCHEMAP_NO_XSI, node, NULL,
7568 "The target namespace must not match '%s'",
7569 xmlSchemaInstanceNs, NULL);
7570 }
7571
7572 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7573 pctxt->targetNamespace, node, 1);
7574 if (ret == NULL)
7575 return (NULL);
7576 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007577
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007578 /*
7579 * Check for illegal attributes.
7580 */
7581 attr = node->properties;
7582 while (attr != NULL) {
7583 if (attr->ns == NULL) {
7584 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7585 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7586 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7587 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7588 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7589 {
7590 xmlSchemaPIllegalAttrErr(pctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00007591 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007592 }
7593 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7594 xmlSchemaPIllegalAttrErr(pctxt,
7595 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7596 }
7597 attr = attr->next;
7598 }
7599 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7600 node, "type", &ret->typeNs, &ret->typeName);
Daniel Veillarddee23482008-04-11 12:58:43 +00007601
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007602 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007603 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007605 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007606 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007607 if (ret->defValue != NULL)
7608 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 * Attribute "default".
7611 */
7612 attr = xmlSchemaGetPropNode(node, "default");
7613 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007615 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007616 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007617 */
7618 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007619 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7620 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007622 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007623 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007624 /*
7625 * And now for the children...
7626 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007627 child = node->children;
7628 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007629 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007630 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007632 if (IS_SCHEMA(child, "simpleType")) {
7633 if (ret->typeName != NULL) {
7634 /*
7635 * 3.2.3 : 4
7636 * type and <simpleType> must not both be present.
7637 */
7638 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7639 NULL, node, child,
7640 "The attribute 'type' and the <simpleType> child "
7641 "are mutually exclusive", NULL);
7642 } else
7643 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7644 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007645 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007646 if (child != NULL)
7647 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7648 NULL, node, child, NULL,
7649 "(annotation?, simpleType?)");
7650
Daniel Veillard4255d502002-04-16 15:50:10 +00007651 return (ret);
7652}
7653
7654/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007655 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007656 * @ctxt: a schema validation context
7657 * @schema: the schema being built
7658 * @node: a subtree containing XML Schema informations
7659 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007660 * Parse an attribute group definition reference.
7661 * Note that a reference to an attribute group does not
7662 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007663 * *WARNING* this interface is highly subject to change
7664 *
7665 * Returns the attribute group or NULL in case of error.
7666 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007667static xmlSchemaQNameRefPtr
7668xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7669 xmlSchemaPtr schema,
7670 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007671{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007672 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007673 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007674 xmlAttrPtr attr;
7675 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007676
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007677 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007678 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007679
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007680 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007681 if (attr == NULL) {
7682 xmlSchemaPMissingAttrErr(pctxt,
7683 XML_SCHEMAP_S4S_ATTR_MISSING,
7684 NULL, node, "ref", NULL);
7685 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007686 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007687 xmlSchemaPValAttrNodeQName(pctxt, schema,
7688 NULL, attr, &refNs, &ref);
7689 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7690 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007691
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007692 /*
7693 * Check for illegal attributes.
7694 */
7695 attr = node->properties;
7696 while (attr != NULL) {
7697 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007698 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007699 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007700 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007701 xmlSchemaPIllegalAttrErr(pctxt,
7702 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007703 }
7704 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007705 xmlSchemaPIllegalAttrErr(pctxt,
7706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007707 }
7708 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007709 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007710 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007711 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7712
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007713 /*
7714 * And now for the children...
7715 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007716 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007717 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007718 /*
7719 * TODO: We do not have a place to store the annotation, do we?
7720 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007721 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007722 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007723 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007724 if (child != NULL) {
7725 xmlSchemaPContentErr(pctxt,
7726 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7727 NULL, node, child, NULL,
7728 "(annotation?)");
7729 }
7730
7731 /*
7732 * Handle attribute group redefinitions.
7733 */
7734 if (pctxt->isRedefine && pctxt->redef &&
7735 (pctxt->redef->item->type ==
7736 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7737 (ref == pctxt->redef->refName) &&
7738 (refNs == pctxt->redef->refTargetNs))
7739 {
7740 /*
7741 * SPEC src-redefine:
7742 * (7.1) "If it has an <attributeGroup> among its contents
Jan Pokorný761c9e92013-11-29 23:26:27 +01007743 * the `actual value` of whose ref [attribute] is the same
7744 * as the `actual value` of its own name attribute plus
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007745 * target namespace, then it must have exactly one such group."
7746 */
7747 if (pctxt->redefCounter != 0) {
7748 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007749
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007750 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7751 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7752 "The redefining attribute group definition "
7753 "'%s' must not contain more than one "
7754 "reference to the redefined definition",
7755 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7756 FREE_AND_NULL(str);
7757 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007758 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007759 pctxt->redefCounter++;
7760 /*
7761 * URGENT TODO: How to ensure that the reference will not be
7762 * handled by the normal component resolution mechanism?
7763 */
7764 ret = xmlSchemaNewQNameRef(pctxt,
7765 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7766 if (ret == NULL)
7767 return(NULL);
7768 ret->node = node;
7769 pctxt->redef->reference = WXS_BASIC_CAST ret;
7770 } else {
7771 /*
7772 * Create a QName-reference helper component. We will substitute this
7773 * component for the attribute uses of the referenced attribute group
7774 * definition.
7775 */
7776 ret = xmlSchemaNewQNameRef(pctxt,
7777 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7778 if (ret == NULL)
7779 return(NULL);
7780 ret->node = node;
7781 /* Add to pending items, to be able to resolve the reference. */
7782 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00007783 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007784 return (ret);
7785}
7786
7787/**
7788 * xmlSchemaParseAttributeGroupDefinition:
7789 * @pctxt: a schema validation context
7790 * @schema: the schema being built
7791 * @node: a subtree containing XML Schema informations
7792 *
7793 * parse a XML schema Attribute Group declaration
7794 * *WARNING* this interface is highly subject to change
7795 *
7796 * Returns the attribute group definition or NULL in case of error.
7797 */
7798static xmlSchemaAttributeGroupPtr
7799xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7800 xmlSchemaPtr schema,
7801 xmlNodePtr node)
7802{
7803 const xmlChar *name;
7804 xmlSchemaAttributeGroupPtr ret;
7805 xmlNodePtr child = NULL;
7806 xmlAttrPtr attr;
7807 int hasRefs = 0;
7808
7809 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7810 return (NULL);
7811
7812 attr = xmlSchemaGetPropNode(node, "name");
7813 if (attr == NULL) {
7814 xmlSchemaPMissingAttrErr(pctxt,
7815 XML_SCHEMAP_S4S_ATTR_MISSING,
7816 NULL, node, "name", NULL);
7817 return (NULL);
7818 }
7819 /*
7820 * The name is crucial, exit if invalid.
7821 */
7822 if (xmlSchemaPValAttrNode(pctxt,
7823 NULL, attr,
7824 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7825 return (NULL);
7826 }
7827 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7828 name, pctxt->targetNamespace, node);
7829 if (ret == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00007830 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007831 /*
7832 * Check for illegal attributes.
7833 */
7834 attr = node->properties;
7835 while (attr != NULL) {
7836 if (attr->ns == NULL) {
7837 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7838 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7839 {
7840 xmlSchemaPIllegalAttrErr(pctxt,
7841 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7842 }
7843 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7844 xmlSchemaPIllegalAttrErr(pctxt,
7845 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7846 }
7847 attr = attr->next;
7848 }
7849 /* Attribute ID */
7850 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7851 /*
7852 * And now for the children...
7853 */
7854 child = node->children;
7855 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007856 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007857 child = child->next;
7858 }
7859 /*
7860 * Parse contained attribute decls/refs.
7861 */
7862 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7863 (xmlSchemaItemListPtr *) &(ret->attrUses),
7864 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7865 return(NULL);
7866 if (hasRefs)
7867 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7868 /*
7869 * Parse the attribute wildcard.
7870 */
7871 if (IS_SCHEMA(child, "anyAttribute")) {
7872 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7873 schema, child);
7874 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007875 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007876 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007877 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007878 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007879 NULL, node, child, NULL,
7880 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007881 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007882 return (ret);
7883}
7884
7885/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007886 * xmlSchemaPValAttrFormDefault:
7887 * @value: the value
7888 * @flags: the flags to be modified
7889 * @flagQualified: the specific flag for "qualified"
7890 *
7891 * Returns 0 if the value is valid, 1 otherwise.
7892 */
7893static int
7894xmlSchemaPValAttrFormDefault(const xmlChar *value,
7895 int *flags,
7896 int flagQualified)
7897{
7898 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7899 if ((*flags & flagQualified) == 0)
7900 *flags |= flagQualified;
7901 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007902 return (1);
7903
William M. Brack2f2a6632004-08-20 23:09:47 +00007904 return (0);
7905}
7906
7907/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 * xmlSchemaPValAttrBlockFinal:
7909 * @value: the value
7910 * @flags: the flags to be modified
7911 * @flagAll: the specific flag for "#all"
7912 * @flagExtension: the specific flag for "extension"
7913 * @flagRestriction: the specific flag for "restriction"
7914 * @flagSubstitution: the specific flag for "substitution"
7915 * @flagList: the specific flag for "list"
7916 * @flagUnion: the specific flag for "union"
7917 *
7918 * Validates the value of the attribute "final" and "block". The value
7919 * is converted into the specified flag values and returned in @flags.
7920 *
7921 * Returns 0 if the value is valid, 1 otherwise.
7922 */
7923
7924static int
7925xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007926 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007927 int flagAll,
7928 int flagExtension,
7929 int flagRestriction,
7930 int flagSubstitution,
7931 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007933{
7934 int ret = 0;
7935
7936 /*
7937 * TODO: This does not check for dublicate entries.
7938 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007939 if ((flags == NULL) || (value == NULL))
7940 return (-1);
7941 if (value[0] == 0)
7942 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007943 if (xmlStrEqual(value, BAD_CAST "#all")) {
7944 if (flagAll != -1)
7945 *flags |= flagAll;
7946 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007947 if (flagExtension != -1)
7948 *flags |= flagExtension;
7949 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007950 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007951 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007952 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007953 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007954 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007955 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007956 *flags |= flagUnion;
7957 }
7958 } else {
7959 const xmlChar *end, *cur = value;
7960 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961
Daniel Veillardc0826a72004-08-10 14:17:33 +00007962 do {
7963 while (IS_BLANK_CH(*cur))
7964 cur++;
7965 end = cur;
7966 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7967 end++;
7968 if (end == cur)
7969 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007970 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007971 if (xmlStrEqual(item, BAD_CAST "extension")) {
7972 if (flagExtension != -1) {
7973 if ((*flags & flagExtension) == 0)
7974 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007975 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007976 ret = 1;
7977 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7978 if (flagRestriction != -1) {
7979 if ((*flags & flagRestriction) == 0)
7980 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007982 ret = 1;
7983 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7984 if (flagSubstitution != -1) {
7985 if ((*flags & flagSubstitution) == 0)
7986 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007987 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007988 ret = 1;
7989 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7990 if (flagList != -1) {
7991 if ((*flags & flagList) == 0)
7992 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007993 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007994 ret = 1;
7995 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7996 if (flagUnion != -1) {
7997 if ((*flags & flagUnion) == 0)
7998 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007999 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008000 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008001 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008002 ret = 1;
8003 if (item != NULL)
8004 xmlFree(item);
8005 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 } while ((ret == 0) && (*cur != 0));
8007 }
8008
Daniel Veillardc0826a72004-08-10 14:17:33 +00008009 return (ret);
8010}
8011
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008012static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008014 xmlSchemaIDCPtr idc,
8015 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008016 xmlAttrPtr attr,
8017 int isField)
8018{
8019 xmlNodePtr node;
8020
8021 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008023 * Schema Component Constraint: Selector Value OK
8024 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008025 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008026 * in [XPath].
8027 */
8028 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008029 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008030 XML_SCHEMAP_INTERNAL,
8031 "Internal error: xmlSchemaCheckCSelectorXPath, "
8032 "the selector is not specified.\n", NULL, NULL);
8033 return (-1);
8034 }
8035 if (attr == NULL)
8036 node = idc->node;
8037 else
8038 node = (xmlNodePtr) attr;
8039 if (selector->xpath == NULL) {
8040 xmlSchemaPCustomErr(ctxt,
8041 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008042 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008043 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008044 "The XPath expression of the selector is not valid", NULL);
8045 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8046 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008047 const xmlChar **nsArray = NULL;
8048 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008049 /*
8050 * Compile the XPath expression.
8051 */
8052 /*
8053 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008054 * TODO: Call xmlPatterncompile with different options for selector/
8055 * field.
8056 */
Daniel Veillard14b56432006-03-09 18:41:40 +00008057 if (attr == NULL)
Daniel Veillardaac7c682006-03-10 13:40:16 +00008058 nsList = NULL;
Daniel Veillard14b56432006-03-09 18:41:40 +00008059 else
8060 nsList = xmlGetNsList(attr->doc, attr->parent);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008061 /*
8062 * Build an array of prefixes and namespaces.
8063 */
8064 if (nsList != NULL) {
8065 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008066
8067 for (i = 0; nsList[i] != NULL; i++)
8068 count++;
8069
8070 nsArray = (const xmlChar **) xmlMalloc(
8071 (count * 2 + 1) * sizeof(const xmlChar *));
8072 if (nsArray == NULL) {
8073 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8074 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008075 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008076 return (-1);
8077 }
8078 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008079 nsArray[2 * i] = nsList[i]->href;
8080 nsArray[2 * i + 1] = nsList[i]->prefix;
8081 }
8082 nsArray[count * 2] = NULL;
8083 xmlFree(nsList);
8084 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008085 /*
8086 * TODO: Differentiate between "selector" and "field".
8087 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008088 if (isField)
8089 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008090 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008091 else
8092 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008093 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008094 if (nsArray != NULL)
8095 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008096
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008097 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008098 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008099 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008100 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008101 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008102 "The XPath expression '%s' could not be "
8103 "compiled", selector->xpath);
8104 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008105 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008106 }
8107 return (0);
8108}
8109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008110#define ADD_ANNOTATION(annot) \
8111 xmlSchemaAnnotPtr cur = item->annot; \
8112 if (item->annot == NULL) { \
8113 item->annot = annot; \
8114 return (annot); \
8115 } \
8116 cur = item->annot; \
8117 if (cur->next != NULL) { \
8118 cur = cur->next; \
8119 } \
8120 cur->next = annot;
8121
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008122/**
8123 * xmlSchemaAssignAnnotation:
8124 * @item: the schema component
8125 * @annot: the annotation
8126 *
8127 * Adds the annotation to the given schema component.
8128 *
8129 * Returns the given annotaion.
8130 */
8131static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008132xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8133 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008135 if ((annItem == NULL) || (annot == NULL))
8136 return (NULL);
8137 switch (annItem->type) {
8138 case XML_SCHEMA_TYPE_ELEMENT: {
8139 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8140 ADD_ANNOTATION(annot)
8141 }
8142 break;
8143 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8144 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8145 ADD_ANNOTATION(annot)
8146 }
8147 break;
8148 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8149 case XML_SCHEMA_TYPE_ANY: {
8150 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8151 ADD_ANNOTATION(annot)
8152 }
8153 break;
8154 case XML_SCHEMA_TYPE_PARTICLE:
8155 case XML_SCHEMA_TYPE_IDC_KEY:
8156 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008157 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008158 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8159 ADD_ANNOTATION(annot)
8160 }
8161 break;
8162 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8163 xmlSchemaAttributeGroupPtr item =
8164 (xmlSchemaAttributeGroupPtr) annItem;
8165 ADD_ANNOTATION(annot)
8166 }
8167 break;
8168 case XML_SCHEMA_TYPE_NOTATION: {
8169 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8170 ADD_ANNOTATION(annot)
8171 }
8172 break;
8173 case XML_SCHEMA_FACET_MININCLUSIVE:
8174 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8175 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8176 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8177 case XML_SCHEMA_FACET_TOTALDIGITS:
8178 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8179 case XML_SCHEMA_FACET_PATTERN:
8180 case XML_SCHEMA_FACET_ENUMERATION:
8181 case XML_SCHEMA_FACET_WHITESPACE:
8182 case XML_SCHEMA_FACET_LENGTH:
8183 case XML_SCHEMA_FACET_MAXLENGTH:
8184 case XML_SCHEMA_FACET_MINLENGTH: {
8185 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8186 ADD_ANNOTATION(annot)
8187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008189 case XML_SCHEMA_TYPE_SIMPLE:
8190 case XML_SCHEMA_TYPE_COMPLEX: {
8191 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8192 ADD_ANNOTATION(annot)
8193 }
8194 break;
8195 case XML_SCHEMA_TYPE_GROUP: {
8196 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8197 ADD_ANNOTATION(annot)
8198 }
8199 break;
8200 case XML_SCHEMA_TYPE_SEQUENCE:
8201 case XML_SCHEMA_TYPE_CHOICE:
8202 case XML_SCHEMA_TYPE_ALL: {
8203 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8204 ADD_ANNOTATION(annot)
8205 }
8206 break;
8207 default:
8208 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008209 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008210 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008211 "Internal error: xmlSchemaAddAnnotation, "
8212 "The item is not a annotated schema component", NULL);
8213 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008214 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008215 return (annot);
8216}
8217
8218/**
8219 * xmlSchemaParseIDCSelectorAndField:
8220 * @ctxt: a schema validation context
8221 * @schema: the schema being built
8222 * @node: a subtree containing XML Schema informations
8223 *
8224 * Parses a XML Schema identity-contraint definition's
8225 * <selector> and <field> elements.
8226 *
8227 * Returns the parsed identity-constraint definition.
8228 */
8229static xmlSchemaIDCSelectPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00008230xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008231 xmlSchemaIDCPtr idc,
8232 xmlNodePtr node,
8233 int isField)
8234{
8235 xmlSchemaIDCSelectPtr item;
8236 xmlNodePtr child = NULL;
8237 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008238
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008239 /*
8240 * Check for illegal attributes.
8241 */
8242 attr = node->properties;
8243 while (attr != NULL) {
8244 if (attr->ns == NULL) {
8245 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8246 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008249 }
8250 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008253 }
8254 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008255 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008256 /*
8257 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008258 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008259 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8260 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPErrMemory(ctxt,
8262 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008263 NULL);
8264 return (NULL);
8265 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008267 /*
8268 * Attribute "xpath" (mandatory).
8269 */
8270 attr = xmlSchemaGetPropNode(node, "xpath");
8271 if (attr == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08008272 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 XML_SCHEMAP_S4S_ATTR_MISSING,
8274 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008275 "name", NULL);
8276 } else {
8277 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8278 /*
8279 * URGENT TODO: "field"s have an other syntax than "selector"s.
8280 */
8281
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008282 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8283 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008284 xmlSchemaPErr(ctxt,
8285 (xmlNodePtr) attr,
8286 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008287 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008288 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008289 NULL, NULL);
8290 }
8291
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008292 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008293 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008294 /*
8295 * And now for the children...
8296 */
8297 child = node->children;
8298 if (IS_SCHEMA(child, "annotation")) {
8299 /*
8300 * Add the annotation to the parent IDC.
8301 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008302 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008303 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008304 child = child->next;
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?)");
8311 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008312
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008313 return (item);
8314}
8315
8316/**
8317 * xmlSchemaParseIDC:
8318 * @ctxt: a schema validation context
8319 * @schema: the schema being built
8320 * @node: a subtree containing XML Schema informations
8321 *
8322 * Parses a XML Schema identity-contraint definition.
8323 *
8324 * Returns the parsed identity-constraint definition.
8325 */
8326static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008327xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008328 xmlSchemaPtr schema,
8329 xmlNodePtr node,
8330 xmlSchemaTypeType idcCategory,
8331 const xmlChar *targetNamespace)
8332{
8333 xmlSchemaIDCPtr item = NULL;
8334 xmlNodePtr child = NULL;
8335 xmlAttrPtr attr;
8336 const xmlChar *name = NULL;
8337 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008338
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008339 /*
8340 * Check for illegal attributes.
8341 */
8342 attr = node->properties;
8343 while (attr != NULL) {
8344 if (attr->ns == NULL) {
8345 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8346 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8347 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8348 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008351 }
8352 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008353 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008355 }
8356 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008358 /*
8359 * Attribute "name" (mandatory).
8360 */
8361 attr = xmlSchemaGetPropNode(node, "name");
8362 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 xmlSchemaPMissingAttrErr(ctxt,
8364 XML_SCHEMAP_S4S_ATTR_MISSING,
8365 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008366 "name", NULL);
8367 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008368 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008369 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008370 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8371 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008372 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008373 /* Create the component. */
8374 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8375 idcCategory, node);
8376 if (item == NULL)
8377 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008378
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008379 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008380 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8381 /*
8382 * Attribute "refer" (mandatory).
8383 */
8384 attr = xmlSchemaGetPropNode(node, "refer");
8385 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386 xmlSchemaPMissingAttrErr(ctxt,
8387 XML_SCHEMAP_S4S_ATTR_MISSING,
8388 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008389 "refer", NULL);
8390 } else {
8391 /*
8392 * Create a reference item.
8393 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008394 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 NULL, NULL);
8396 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008397 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008398 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008399 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008400 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008401 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008402 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008403 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008404 }
8405 }
8406 /*
8407 * And now for the children...
8408 */
8409 child = node->children;
8410 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008411 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008412 child = child->next;
8413 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008414 if (child == NULL) {
8415 xmlSchemaPContentErr(ctxt,
8416 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008417 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008418 "A child element is missing",
8419 "(annotation?, (selector, field+))");
8420 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008421 /*
8422 * Child element <selector>.
8423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008424 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008425 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008426 item, child, 0);
8427 child = child->next;
8428 /*
8429 * Child elements <field>.
8430 */
8431 if (IS_SCHEMA(child, "field")) {
8432 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008433 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008434 item, child, 1);
8435 if (field != NULL) {
8436 field->index = item->nbFields;
8437 item->nbFields++;
8438 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008439 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008440 else
8441 item->fields = field;
8442 lastField = field;
8443 }
8444 child = child->next;
8445 } while (IS_SCHEMA(child, "field"));
8446 } else {
8447 xmlSchemaPContentErr(ctxt,
8448 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008449 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008450 NULL, "(annotation?, (selector, field+))");
8451 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008452 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008453 if (child != NULL) {
8454 xmlSchemaPContentErr(ctxt,
8455 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008456 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008457 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008458 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008459
8460 return (item);
8461}
8462
Daniel Veillardc0826a72004-08-10 14:17:33 +00008463/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008464 * xmlSchemaParseElement:
8465 * @ctxt: a schema validation context
8466 * @schema: the schema being built
8467 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008468 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008469 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008470 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008471 * *WARNING* this interface is highly subject to change
8472 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008473 * Returns the element declaration or a particle; NULL in case
8474 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008475 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008476static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008477xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008478 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008479{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008480 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008482 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008483 xmlNodePtr child = NULL;
8484 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008485 int min, max, isRef = 0;
8486 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008487
8488 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8489 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008490
Daniel Veillard4255d502002-04-16 15:50:10 +00008491 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008492 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008493
8494 if (isElemRef != NULL)
8495 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008496 /*
8497 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008498 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008499 * robust.
8500 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008501 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008502 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008503 if ((topLevel) || (attr == NULL)) {
8504 if (nameAttr == NULL) {
8505 xmlSchemaPMissingAttrErr(ctxt,
8506 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008507 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008508 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008509 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008510 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008511 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008512
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008513 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008514 child = node->children;
8515 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008516 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008517 child = child->next;
8518 }
8519 /*
8520 * Skip particle part if a global declaration.
8521 */
8522 if (topLevel)
8523 goto declaration_part;
8524 /*
8525 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008526 */
8527 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8528 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8529 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00008530 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 if (particle == NULL)
8532 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008533
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008534 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8535
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008536 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008537 const xmlChar *refNs = NULL, *ref = NULL;
8538 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008539 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008540 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008541 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008542 if (isElemRef != NULL)
8543 *isElemRef = 1;
8544
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008546 NULL, attr, &refNs, &ref);
8547 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008548 /*
8549 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008550 */
8551 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008552 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008553 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008554 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008555 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008556 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008557 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008558 attr = node->properties;
8559 while (attr != NULL) {
8560 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008561 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8562 xmlStrEqual(attr->name, BAD_CAST "name") ||
8563 xmlStrEqual(attr->name, BAD_CAST "id") ||
8564 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8565 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8566 {
8567 attr = attr->next;
8568 continue;
8569 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008570 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008572 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008573 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008574 "Only the attributes 'minOccurs', 'maxOccurs' and "
8575 "'id' are allowed in addition to 'ref'");
8576 break;
8577 }
8578 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8579 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008580 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008581 }
8582 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008583 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008584 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008585 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008586 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008587 if (child != NULL) {
8588 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008589 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008590 }
8591 if ((min == 0) && (max == 0))
8592 goto return_null;
8593 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008594 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008595 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008596 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008597 ref, refNs);
8598 if (refer == NULL)
8599 goto return_null;
8600 particle->children = (xmlSchemaTreeItemPtr) refer;
8601 particle->annot = annot;
8602 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008603 * Add the particle to pending components, since the reference
8604 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008605 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008606 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008607 return ((xmlSchemaBasicItemPtr) particle);
8608 }
8609 /*
8610 * The declaration part ===============================================
8611 */
8612declaration_part:
8613 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008614 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008615 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8616
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008617 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008618 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008619 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008621 * Evaluate the target namespace.
8622 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008623 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008624 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008625 } else {
8626 attr = xmlSchemaGetPropNode(node, "form");
8627 if (attr != NULL) {
8628 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8629 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008630 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008631 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008632 xmlSchemaPSimpleTypeErr(ctxt,
8633 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8634 NULL, (xmlNodePtr) attr,
8635 NULL, "(qualified | unqualified)",
8636 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008637 }
8638 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008639 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008640 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008641 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008642 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008643 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008644 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008645 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008646 * Check for illegal attributes.
8647 */
William M. Bracke7091952004-05-11 15:09:58 +00008648 attr = node->properties;
8649 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008650 if (attr->ns == NULL) {
8651 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8652 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008653 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008655 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008656 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008657 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8658 {
8659 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008660 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008661 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008662 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008663 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008664 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008665 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008667 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8668 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008669 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8670
8671 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008672 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008673 }
8674 }
8675 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008676
Daniel Veillardc0826a72004-08-10 14:17:33 +00008677 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008678 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008679 }
8680 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008681 }
William M. Bracke7091952004-05-11 15:09:58 +00008682 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008683 * Extract/validate attributes.
8684 */
8685 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008686 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008687 * Process top attributes of global element declarations here.
8688 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008689 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8690 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008691 xmlSchemaPValAttrQName(ctxt, schema,
8692 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008693 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008694 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008695 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008696 /*
8697 * Attribute "final".
8698 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008699 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008700 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008701 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8702 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8703 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8704 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008705 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008706 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8707 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008708 -1,
8709 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8710 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008711 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008712 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008713 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008714 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008715 attrValue, NULL, NULL, NULL);
8716 }
8717 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008718 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008719 /*
8720 * Attribute "block".
8721 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008722 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008723 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008724 /*
8725 * Apply default "block" values.
8726 */
8727 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8728 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8729 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8730 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8731 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8732 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008733 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008734 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8735 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008736 -1,
8737 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008739 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8740 xmlSchemaPSimpleTypeErr(ctxt,
8741 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008742 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008743 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 "restriction | substitution))", attrValue,
8745 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008746 }
8747 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008748 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008749 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008750
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008751 attr = xmlSchemaGetPropNode(node, "type");
8752 if (attr != NULL) {
8753 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008754 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008755 &(decl->namedTypeNs), &(decl->namedType));
8756 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008757 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008758 }
8759 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8760 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008761 if (attr != NULL) {
8762 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008763 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008764 /*
8765 * 3.3.3 : 1
8766 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008767 */
8768 xmlSchemaPMutualExclAttrErr(ctxt,
8769 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008770 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008771 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008772 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8773 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008774 }
William M. Bracke7091952004-05-11 15:09:58 +00008775 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008776 /*
8777 * And now for the children...
8778 */
William M. Bracke7091952004-05-11 15:09:58 +00008779 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008780 /*
8781 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008782 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008783 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008784 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008785 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008786 xmlSchemaPContentErr(ctxt,
8787 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008788 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008789 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008790 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008791 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008792 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008793 child = child->next;
8794 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008795 /*
8796 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008797 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008798 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008799 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008800 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008801 xmlSchemaPContentErr(ctxt,
8802 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008803 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008804 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008805 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008806 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008807 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008808 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008809 }
William M. Bracke7091952004-05-11 15:09:58 +00008810 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008811 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008812 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008813 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008814 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008815 } else if (IS_SCHEMA(child, "key")) {
8816 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008817 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008818 } else if (IS_SCHEMA(child, "keyref")) {
8819 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008820 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008821 }
8822 if (lastIDC != NULL)
8823 lastIDC->next = curIDC;
8824 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008825 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008826 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008827 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008828 }
8829 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008830 xmlSchemaPContentErr(ctxt,
8831 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008832 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008833 NULL, "(annotation?, ((simpleType | complexType)?, "
8834 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008835 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008836 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008837 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008838 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008839 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008840 * different layer.
8841 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008842 FREE_AND_NULL(des)
8843 if (topLevel)
8844 return ((xmlSchemaBasicItemPtr) decl);
8845 else {
8846 particle->children = (xmlSchemaTreeItemPtr) decl;
8847 return ((xmlSchemaBasicItemPtr) particle);
8848 }
8849
8850return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008851 FREE_AND_NULL(des);
8852 if (annot != NULL) {
8853 if (particle != NULL)
8854 particle->annot = NULL;
8855 if (decl != NULL)
8856 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008857 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008858 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008859 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008860}
8861
8862/**
8863 * xmlSchemaParseUnion:
8864 * @ctxt: a schema validation context
8865 * @schema: the schema being built
8866 * @node: a subtree containing XML Schema informations
8867 *
8868 * parse a XML schema Union definition
8869 * *WARNING* this interface is highly subject to change
8870 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008871 * Returns -1 in case of internal error, 0 in case of success and a positive
8872 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008873 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008874static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008875xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008876 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008877{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008878 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008879 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008880 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008881 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008882
8883 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008884 return (-1);
8885 /* Not a component, don't create it. */
8886 type = ctxt->ctxtType;
8887 /*
8888 * Mark the simple type as being of variety "union".
8889 */
8890 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008891 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008892 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01008893 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008894 */
8895 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008896 /*
8897 * Check for illegal attributes.
8898 */
8899 attr = node->properties;
8900 while (attr != NULL) {
8901 if (attr->ns == NULL) {
8902 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8903 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008904 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008905 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008906 }
8907 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008908 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008910 }
8911 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008913 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008914 /*
8915 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008916 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008917 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008918 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008919 if (attr != NULL) {
8920 const xmlChar *end;
8921 xmlChar *tmp;
8922 const xmlChar *localName, *nsName;
8923 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8924 xmlSchemaQNameRefPtr ref;
8925
8926 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008927 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008928 do {
8929 while (IS_BLANK_CH(*cur))
8930 cur++;
8931 end = cur;
8932 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8933 end++;
8934 if (end == cur)
8935 break;
8936 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008937 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008939 /*
8940 * Create the member type link.
8941 */
8942 link = (xmlSchemaTypeLinkPtr)
8943 xmlMalloc(sizeof(xmlSchemaTypeLink));
8944 if (link == NULL) {
8945 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8946 "allocating a type link", NULL);
8947 return (-1);
8948 }
8949 link->type = NULL;
8950 link->next = NULL;
8951 if (lastLink == NULL)
8952 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008953 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008954 lastLink->next = link;
8955 lastLink = link;
8956 /*
8957 * Create a reference item.
8958 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008959 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008960 localName, nsName);
8961 if (ref == NULL) {
8962 FREE_AND_NULL(tmp)
8963 return (-1);
8964 }
8965 /*
8966 * Assign the reference to the link, it will be resolved
8967 * later during fixup of the union simple type.
8968 */
8969 link->type = (xmlSchemaTypePtr) ref;
8970 }
8971 FREE_AND_NULL(tmp)
8972 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008973 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008974
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008976 /*
8977 * And now for the children...
8978 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008979 child = node->children;
8980 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008981 /*
8982 * Add the annotation to the simple type ancestor.
8983 */
8984 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008985 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008986 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008987 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008988 if (IS_SCHEMA(child, "simpleType")) {
8989 xmlSchemaTypePtr subtype, last = NULL;
8990
8991 /*
8992 * Anchor the member types in the "subtypes" field of the
8993 * simple type.
8994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008996 subtype = (xmlSchemaTypePtr)
8997 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8998 if (subtype != NULL) {
8999 if (last == NULL) {
9000 type->subtypes = subtype;
9001 last = subtype;
9002 } else {
9003 last->next = subtype;
9004 last = subtype;
9005 }
9006 last->next = NULL;
9007 }
9008 child = child->next;
9009 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009010 }
9011 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009012 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009013 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009014 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009015 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009016 if ((attr == NULL) && (type->subtypes == NULL)) {
9017 /*
9018 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009019 * Either the memberTypes [attribute] of the <union> element must
9020 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009021 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009022 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009023 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009024 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009025 "Either the attribute 'memberTypes' or "
9026 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009027 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009028 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009029}
9030
9031/**
9032 * xmlSchemaParseList:
9033 * @ctxt: a schema validation context
9034 * @schema: the schema being built
9035 * @node: a subtree containing XML Schema informations
9036 *
9037 * parse a XML schema List definition
9038 * *WARNING* this interface is highly subject to change
9039 *
William M. Bracke7091952004-05-11 15:09:58 +00009040 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009041 * 1 in case of success.
9042 */
9043static xmlSchemaTypePtr
9044xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009045 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009047 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009048 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009049 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009050
9051 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9052 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009053 /* Not a component, don't create it. */
9054 type = ctxt->ctxtType;
9055 /*
9056 * Mark the type as being of variety "list".
9057 */
9058 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009060 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009061 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009062 */
9063 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00009064 /*
9065 * Check for illegal attributes.
9066 */
9067 attr = node->properties;
9068 while (attr != NULL) {
9069 if (attr->ns == NULL) {
9070 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9071 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009072 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009073 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009074 }
9075 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009078 }
9079 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009080 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009081
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009082 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009083
William M. Brack2f2a6632004-08-20 23:09:47 +00009084 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009085 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9086 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009087 *
9088 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9089 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009090 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009091 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9092 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009093 /*
9094 * And now for the children...
9095 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009096 child = node->children;
9097 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009098 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009099 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009100 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009101 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009102 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009103 /*
9104 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009105 * Either the itemType [attribute] or the <simpleType> [child] of
9106 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009107 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009108 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009109 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009110 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009111 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009112 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009113 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009114 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009115 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009116 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009117 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009118 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009119 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009120 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009121 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009122 "Either the attribute 'itemType' or the <simpleType> child "
9123 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009124 }
9125 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009126 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009127 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009128 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009129 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009130 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009131 (type->subtypes == NULL) &&
9132 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009133 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009134 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009135 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009136 "Either the attribute 'itemType' or the <simpleType> child "
9137 "must be present", NULL);
9138 }
9139 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009140}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009141
Daniel Veillard4255d502002-04-16 15:50:10 +00009142/**
9143 * xmlSchemaParseSimpleType:
9144 * @ctxt: a schema validation context
9145 * @schema: the schema being built
9146 * @node: a subtree containing XML Schema informations
9147 *
9148 * parse a XML schema Simple Type definition
9149 * *WARNING* this interface is highly subject to change
9150 *
William M. Bracke7091952004-05-11 15:09:58 +00009151 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009152 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009153 */
9154static xmlSchemaTypePtr
9155xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009156 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009157{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009158 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009159 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009161 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009162 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009163
9164 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9165 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009166
Daniel Veillardc0826a72004-08-10 14:17:33 +00009167 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009168 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009170 xmlSchemaPMissingAttrErr(ctxt,
9171 XML_SCHEMAP_S4S_ATTR_MISSING,
9172 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009173 "name", NULL);
9174 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009175 } else {
9176 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009177 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009178 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9179 return (NULL);
9180 /*
9181 * Skip built-in types.
9182 */
9183 if (ctxt->isS4S) {
9184 xmlSchemaTypePtr biType;
9185
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009186 if (ctxt->isRedefine) {
9187 /*
9188 * REDEFINE: Disallow redefinition of built-in-types.
9189 * TODO: It seems that the spec does not say anything
9190 * about this case.
9191 */
9192 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009193 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009194 "Redefinition of built-in simple types is not "
9195 "supported", NULL);
9196 return(NULL);
9197 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009198 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9199 if (biType != NULL)
9200 return (biType);
9201 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009202 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009203 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009204 /*
9205 * TargetNamespace:
Jan Pokorný761c9e92013-11-29 23:26:27 +01009206 * SPEC "The `actual value` of the targetNamespace [attribute]
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009207 * of the <schema> ancestor element information item if present,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009208 * otherwise `absent`.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009209 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009210 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009211#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009212 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009213#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009214 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009215 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009216 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009217#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009218 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009219 type = xmlSchemaAddType(ctxt, schema,
9220 XML_SCHEMA_TYPE_SIMPLE,
9221 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009222 ctxt->targetNamespace, node, 0);
9223#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009224 type = xmlSchemaAddType(ctxt, schema,
9225 XML_SCHEMA_TYPE_SIMPLE,
9226 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009227#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009228 if (type == NULL)
9229 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009230 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009231 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009232 /*
9233 * Check for illegal attributes.
9234 */
9235 attr = node->properties;
9236 while (attr != NULL) {
9237 if (attr->ns == NULL) {
9238 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009239 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00009240 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009241 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009242 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009245 }
9246 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009247 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009248 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009249 /*
9250 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009251 *
9252 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009253 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009254 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9255 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009256 if (type == NULL)
9257 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009258 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009259 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009260 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9261 /*
9262 * Check for illegal attributes.
9263 */
9264 attr = node->properties;
9265 while (attr != NULL) {
9266 if (attr->ns == NULL) {
9267 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9268 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009269 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009270 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009271 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009272 }
9273 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009274 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009275 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009276 }
9277 attr = attr->next;
9278 }
9279 /*
9280 * Attribute "final".
9281 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009282 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009283 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009284 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9285 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9286 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9287 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9288 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9289 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009290 } else {
9291 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009292 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9293 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009294 XML_SCHEMAS_TYPE_FINAL_LIST,
9295 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9296
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009297 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009298 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009299 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009300 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009301 attrValue, NULL, NULL, NULL);
9302 }
9303 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009304 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009305 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009306 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009307 /*
9308 * And now for the children...
9309 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009310 oldCtxtType = ctxt->ctxtType;
Daniel Veillarddee23482008-04-11 12:58:43 +00009311
Daniel Veillardc0826a72004-08-10 14:17:33 +00009312 ctxt->ctxtType = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00009313
Daniel Veillard4255d502002-04-16 15:50:10 +00009314 child = node->children;
9315 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009316 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009317 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009318 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009319 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009321 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009322 "(annotation?, (restriction | list | union))");
Daniel Veillarddee23482008-04-11 12:58:43 +00009323 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009324 xmlSchemaParseRestriction(ctxt, schema, child,
Daniel Veillarddee23482008-04-11 12:58:43 +00009325 XML_SCHEMA_TYPE_SIMPLE);
9326 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009327 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009328 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009329 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009330 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009331 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009332 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009333 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009334 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009335 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009336 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009337 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009338 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009339 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009340 /*
9341 * REDEFINE: SPEC src-redefine (5)
9342 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +01009343 * <restriction> among its [children] ... the `actual value` of whose
9344 * base [attribute] must be the same as the `actual value` of its own
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009345 * name attribute plus target namespace;"
9346 */
9347 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9348 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009349 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009350 "<simpleType> must have a <restriction> child", NULL);
9351 }
Daniel Veillarddee23482008-04-11 12:58:43 +00009352
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009353 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009354 return (type);
9355}
9356
Daniel Veillard4255d502002-04-16 15:50:10 +00009357/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009358 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009359 * @ctxt: the parser context
9360 * @schema: the schema being built
9361 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009362 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009363 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009364 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009365 * We will return a particle component with a qname-component or
9366 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009367 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009368static xmlSchemaTreeItemPtr
9369xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9370 xmlSchemaPtr schema,
9371 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009372{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009373 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009374 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009375 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009376 const xmlChar *ref = NULL, *refNs = NULL;
9377 int min, max;
9378
9379 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009380 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009381
9382 attr = xmlSchemaGetPropNode(node, "ref");
9383 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009384 xmlSchemaPMissingAttrErr(ctxt,
9385 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009386 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009387 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009388 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009389 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009390 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009391 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009392 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009393 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009394 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009395 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009396 /*
9397 * Check for illegal attributes.
9398 */
9399 attr = node->properties;
9400 while (attr != NULL) {
9401 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009402 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009403 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9404 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9405 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009406 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009407 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009408 }
9409 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009410 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009411 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009412 }
9413 attr = attr->next;
9414 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009415 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00009416 item = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009417 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00009418 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009419 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009420 * Create a qname-reference and set as the term; it will be substituted
9421 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009422 */
9423 item->children = (xmlSchemaTreeItemPtr)
Daniel Veillarddee23482008-04-11 12:58:43 +00009424 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009425 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9426 /*
9427 * And now for the children...
9428 */
9429 child = node->children;
9430 /* TODO: Is annotation even allowed for a model group reference? */
9431 if (IS_SCHEMA(child, "annotation")) {
9432 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009433 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009434 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009435 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009436 child = child->next;
9437 }
9438 if (child != NULL) {
9439 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009441 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009442 "(annotation?)");
9443 }
9444 /*
9445 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9446 */
9447 if ((min == 0) && (max == 0))
9448 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009449
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009450 return ((xmlSchemaTreeItemPtr) item);
9451}
9452
9453/**
9454 * xmlSchemaParseModelGroupDefinition:
9455 * @ctxt: a schema validation context
9456 * @schema: the schema being built
9457 * @node: a subtree containing XML Schema informations
9458 *
9459 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009460 *
9461 * Note that the contraint src-redefine (6.2) can't be applied until
9462 * references have been resolved. So we will do this at the
9463 * component fixup level.
Daniel Veillarddee23482008-04-11 12:58:43 +00009464 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009465 * *WARNING* this interface is highly subject to change
9466 *
9467 * Returns -1 in case of error, 0 if the declaration is improper and
9468 * 1 in case of success.
9469 */
9470static xmlSchemaModelGroupDefPtr
9471xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9472 xmlSchemaPtr schema,
9473 xmlNodePtr node)
9474{
9475 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009476 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009477 xmlAttrPtr attr;
9478 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009479
9480 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009481 return (NULL);
9482
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009483 attr = xmlSchemaGetPropNode(node, "name");
9484 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009485 xmlSchemaPMissingAttrErr(ctxt,
9486 XML_SCHEMAP_S4S_ATTR_MISSING,
9487 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009488 "name", NULL);
9489 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009490 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009491 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9492 return (NULL);
9493 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009494 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9495 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009496 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009497 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009498 /*
9499 * Check for illegal attributes.
9500 */
9501 attr = node->properties;
9502 while (attr != NULL) {
9503 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009505 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009506 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009507 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009508 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009509 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009510 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009512 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009513 attr = attr->next;
9514 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009515 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009516 /*
9517 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009518 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009519 child = node->children;
9520 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009521 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009522 child = child->next;
9523 }
9524 if (IS_SCHEMA(child, "all")) {
9525 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9526 XML_SCHEMA_TYPE_ALL, 0);
9527 child = child->next;
9528 } else if (IS_SCHEMA(child, "choice")) {
9529 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9530 XML_SCHEMA_TYPE_CHOICE, 0);
9531 child = child->next;
9532 } else if (IS_SCHEMA(child, "sequence")) {
9533 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9534 XML_SCHEMA_TYPE_SEQUENCE, 0);
9535 child = child->next;
9536 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009537
Daniel Veillarddee23482008-04-11 12:58:43 +00009538
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009539
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009540 if (child != NULL) {
9541 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009542 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009543 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009544 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009545 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009546 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009547}
9548
9549/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009550 * xmlSchemaCleanupDoc:
9551 * @ctxt: a schema validation context
9552 * @node: the root of the document.
9553 *
9554 * removes unwanted nodes in a schemas document tree
9555 */
9556static void
9557xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9558{
9559 xmlNodePtr delete, cur;
9560
9561 if ((ctxt == NULL) || (root == NULL)) return;
9562
9563 /*
9564 * Remove all the blank text nodes
9565 */
9566 delete = NULL;
9567 cur = root;
9568 while (cur != NULL) {
9569 if (delete != NULL) {
9570 xmlUnlinkNode(delete);
9571 xmlFreeNode(delete);
9572 delete = NULL;
9573 }
9574 if (cur->type == XML_TEXT_NODE) {
9575 if (IS_BLANK_NODE(cur)) {
9576 if (xmlNodeGetSpacePreserve(cur) != 1) {
9577 delete = cur;
9578 }
9579 }
9580 } else if ((cur->type != XML_ELEMENT_NODE) &&
9581 (cur->type != XML_CDATA_SECTION_NODE)) {
9582 delete = cur;
9583 goto skip_children;
9584 }
9585
9586 /*
9587 * Skip to next node
9588 */
9589 if (cur->children != NULL) {
9590 if ((cur->children->type != XML_ENTITY_DECL) &&
9591 (cur->children->type != XML_ENTITY_REF_NODE) &&
9592 (cur->children->type != XML_ENTITY_NODE)) {
9593 cur = cur->children;
9594 continue;
9595 }
9596 }
9597 skip_children:
9598 if (cur->next != NULL) {
9599 cur = cur->next;
9600 continue;
9601 }
9602
9603 do {
9604 cur = cur->parent;
9605 if (cur == NULL)
9606 break;
9607 if (cur == root) {
9608 cur = NULL;
9609 break;
9610 }
9611 if (cur->next != NULL) {
9612 cur = cur->next;
9613 break;
9614 }
9615 } while (cur != NULL);
9616 }
9617 if (delete != NULL) {
9618 xmlUnlinkNode(delete);
9619 xmlFreeNode(delete);
9620 delete = NULL;
9621 }
9622}
9623
William M. Brack2f2a6632004-08-20 23:09:47 +00009624
William M. Brack2f2a6632004-08-20 23:09:47 +00009625static void
9626xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9627{
9628 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9629 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9630
9631 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9632 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9633
9634 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9635 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9636 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9637 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9638 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9639 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9640 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9641 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9642
9643 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9644 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9645 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9646 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9647 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9648 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9649}
9650
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009651static int
9652xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 xmlSchemaPtr schema,
9654 xmlNodePtr node)
9655{
9656 xmlAttrPtr attr;
9657 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009658 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009659
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009660 /*
9661 * Those flags should be moved to the parser context flags,
9662 * since they are not visible at the component level. I.e.
9663 * they are used if processing schema *documents* only.
9664 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009665 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009666 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009667
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009668 /*
9669 * Since the version is of type xs:token, we won't bother to
9670 * check it.
9671 */
9672 /* REMOVED:
9673 attr = xmlSchemaGetPropNode(node, "version");
9674 if (attr != NULL) {
9675 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillarddee23482008-04-11 12:58:43 +00009676 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009677 HFAILURE;
9678 }
9679 */
9680 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9681 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009682 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009683 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9684 HFAILURE;
9685 if (res != 0) {
9686 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9687 goto exit;
9688 }
9689 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009690 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009691 if (attr != NULL) {
9692 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009693 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9694 XML_SCHEMAS_QUALIF_ELEM);
9695 HFAILURE;
9696 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009697 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009698 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009699 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009700 "(qualified | unqualified)", val, NULL, NULL, NULL);
9701 }
9702 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009703 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009704 if (attr != NULL) {
9705 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009706 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9707 XML_SCHEMAS_QUALIF_ATTR);
9708 HFAILURE;
9709 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009710 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009711 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009712 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009713 "(qualified | unqualified)", val, NULL, NULL, NULL);
9714 }
9715 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009717 if (attr != NULL) {
9718 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009719 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009720 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9721 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9722 -1,
9723 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009724 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9725 HFAILURE;
9726 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009727 xmlSchemaPSimpleTypeErr(ctxt,
9728 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009729 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009730 "(#all | List of (extension | restriction | list | union))",
9731 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009732 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009733 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009734 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009735 if (attr != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00009736 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009737 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009738 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9739 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009740 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9741 HFAILURE;
9742 if (res != 0) {
9743 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009744 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009745 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009746 "(#all | List of (extension | restriction | substitution))",
9747 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009748 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009749 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009750
9751exit:
9752 if (oldErrs != ctxt->nberrors)
9753 res = ctxt->err;
9754 return(res);
9755exit_failure:
9756 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009757}
9758
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009759/**
9760 * xmlSchemaParseSchemaTopLevel:
9761 * @ctxt: a schema validation context
9762 * @schema: the schemas
9763 * @nodes: the list of top level nodes
9764 *
9765 * Returns the internal XML Schema structure built from the resource or
9766 * NULL in case of error
9767 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009768static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009769xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9770 xmlSchemaPtr schema, xmlNodePtr nodes)
9771{
9772 xmlNodePtr child;
9773 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009774 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009775
9776 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009777 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009778
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009779 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009780 child = nodes;
9781 while ((IS_SCHEMA(child, "include")) ||
9782 (IS_SCHEMA(child, "import")) ||
9783 (IS_SCHEMA(child, "redefine")) ||
9784 (IS_SCHEMA(child, "annotation"))) {
9785 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009786 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009787 if (schema->annot == NULL)
9788 schema->annot = annot;
9789 else
9790 xmlSchemaFreeAnnot(annot);
9791 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009792 tmpOldErrs = ctxt->nberrors;
9793 res = xmlSchemaParseImport(ctxt, schema, child);
9794 HFAILURE;
9795 HSTOP(ctxt);
9796 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009797 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009798 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009799 tmpOldErrs = ctxt->nberrors;
9800 res = xmlSchemaParseInclude(ctxt, schema, child);
9801 HFAILURE;
9802 HSTOP(ctxt);
9803 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009804 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009805 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009806 tmpOldErrs = ctxt->nberrors;
9807 res = xmlSchemaParseRedefine(ctxt, schema, child);
9808 HFAILURE;
9809 HSTOP(ctxt);
9810 if (tmpOldErrs != ctxt->nberrors)
9811 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009812 }
9813 child = child->next;
9814 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009815 /*
9816 * URGENT TODO: Change the functions to return int results.
9817 * We need especially to catch internal errors.
9818 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009819 while (child != NULL) {
9820 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009821 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009822 child = child->next;
9823 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009824 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009825 child = child->next;
9826 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009827 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009828 child = child->next;
9829 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009830 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009831 child = child->next;
9832 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009833 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009834 child = child->next;
9835 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009836 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009837 child = child->next;
9838 } else if (IS_SCHEMA(child, "notation")) {
9839 xmlSchemaParseNotation(ctxt, schema, child);
9840 child = child->next;
9841 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009842 xmlSchemaPContentErr(ctxt,
9843 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009844 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009845 NULL, "((include | import | redefine | annotation)*, "
9846 "(((simpleType | complexType | group | attributeGroup) "
9847 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009848 child = child->next;
9849 }
9850 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009851 /*
9852 * TODO: We should add all annotations.
9853 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009854 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009855 if (schema->annot == NULL)
9856 schema->annot = annot;
9857 else
9858 xmlSchemaFreeAnnot(annot);
9859 child = child->next;
9860 }
9861 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009862exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009863 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009864 if (oldErrs != ctxt->nberrors)
9865 res = ctxt->err;
9866 return(res);
9867exit_failure:
9868 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009869}
9870
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009871static xmlSchemaSchemaRelationPtr
9872xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009873{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009874 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009875
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009876 ret = (xmlSchemaSchemaRelationPtr)
9877 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009878 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009879 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009880 return(NULL);
9881 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009882 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009883 return(ret);
9884}
9885
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009886#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009887static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009888xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009889{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009890 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009891}
9892#endif
9893
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009894static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009895xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9896{
9897 xmlSchemaRedefPtr prev;
9898
9899 while (redef != NULL) {
9900 prev = redef;
9901 redef = redef->next;
9902 xmlFree(prev);
9903 }
9904}
9905
9906static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009907xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9908{
9909 /*
9910 * After the construction context has been freed, there will be
9911 * no schema graph available any more. Only the schema buckets
9912 * will stay alive, which are put into the "schemasImports" and
9913 * "includes" slots of the xmlSchema.
9914 */
9915 if (con->buckets != NULL)
9916 xmlSchemaItemListFree(con->buckets);
9917 if (con->pending != NULL)
9918 xmlSchemaItemListFree(con->pending);
9919 if (con->substGroups != NULL)
9920 xmlHashFree(con->substGroups,
9921 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009922 if (con->redefs != NULL)
9923 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009924 if (con->dict != NULL)
9925 xmlDictFree(con->dict);
9926 xmlFree(con);
9927}
9928
Daniel Veillarddee23482008-04-11 12:58:43 +00009929static xmlSchemaConstructionCtxtPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009930xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9931{
9932 xmlSchemaConstructionCtxtPtr ret;
9933
9934 ret = (xmlSchemaConstructionCtxtPtr)
9935 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9936 if (ret == NULL) {
9937 xmlSchemaPErrMemory(NULL,
9938 "allocating schema construction context", NULL);
9939 return (NULL);
9940 }
9941 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9942
9943 ret->buckets = xmlSchemaItemListCreate();
9944 if (ret->buckets == NULL) {
9945 xmlSchemaPErrMemory(NULL,
9946 "allocating list of schema buckets", NULL);
9947 xmlFree(ret);
9948 return (NULL);
9949 }
9950 ret->pending = xmlSchemaItemListCreate();
9951 if (ret->pending == NULL) {
9952 xmlSchemaPErrMemory(NULL,
9953 "allocating list of pending global components", NULL);
9954 xmlSchemaConstructionCtxtFree(ret);
9955 return (NULL);
9956 }
9957 ret->dict = dict;
9958 xmlDictReference(dict);
9959 return(ret);
9960}
9961
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009962static xmlSchemaParserCtxtPtr
9963xmlSchemaParserCtxtCreate(void)
9964{
9965 xmlSchemaParserCtxtPtr ret;
9966
9967 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9968 if (ret == NULL) {
9969 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9970 NULL);
9971 return (NULL);
9972 }
9973 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9974 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009975 ret->attrProhibs = xmlSchemaItemListCreate();
9976 if (ret->attrProhibs == NULL) {
9977 xmlFree(ret);
9978 return(NULL);
9979 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009980 return(ret);
9981}
9982
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009983/**
9984 * xmlSchemaNewParserCtxtUseDict:
9985 * @URL: the location of the schema
9986 * @dict: the dictionary to be used
9987 *
9988 * Create an XML Schemas parse context for that file/resource expected
9989 * to contain an XML Schemas file.
9990 *
9991 * Returns the parser context or NULL in case of error
9992 */
9993static xmlSchemaParserCtxtPtr
9994xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9995{
9996 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009997
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009998 ret = xmlSchemaParserCtxtCreate();
Daniel Veillarddee23482008-04-11 12:58:43 +00009999 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010000 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010001 ret->dict = dict;
Daniel Veillarddee23482008-04-11 12:58:43 +000010002 xmlDictReference(dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010003 if (URL != NULL)
10004 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010005 return (ret);
10006}
10007
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010008static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010009xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10010{
10011 if (vctxt->pctxt == NULL) {
10012 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010013 vctxt->pctxt =
10014 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010015 else
10016 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10017 if (vctxt->pctxt == NULL) {
10018 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10019 "failed to create a temp. parser context");
10020 return (-1);
10021 }
10022 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010023 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010024 vctxt->warning, vctxt->errCtxt);
10025 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10026 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010027 }
10028 return (0);
10029}
10030
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010031/**
10032 * xmlSchemaGetSchemaBucket:
10033 * @pctxt: the schema parser context
10034 * @schemaLocation: the URI of the schema document
10035 *
10036 * Returns a schema bucket if it was already parsed.
10037 *
10038 * Returns a schema bucket if it was already parsed from
10039 * @schemaLocation, NULL otherwise.
10040 */
10041static xmlSchemaBucketPtr
10042xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10043 const xmlChar *schemaLocation)
10044{
10045 xmlSchemaBucketPtr cur;
10046 xmlSchemaItemListPtr list;
10047
10048 list = pctxt->constructor->buckets;
10049 if (list->nbItems == 0)
10050 return(NULL);
10051 else {
10052 int i;
10053 for (i = 0; i < list->nbItems; i++) {
10054 cur = (xmlSchemaBucketPtr) list->items[i];
10055 /* Pointer comparison! */
10056 if (cur->schemaLocation == schemaLocation)
10057 return(cur);
10058 }
10059 }
10060 return(NULL);
10061}
10062
10063static xmlSchemaBucketPtr
10064xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10065 const xmlChar *schemaLocation,
10066 const xmlChar *targetNamespace)
10067{
10068 xmlSchemaBucketPtr cur;
10069 xmlSchemaItemListPtr list;
10070
10071 list = pctxt->constructor->buckets;
10072 if (list->nbItems == 0)
10073 return(NULL);
10074 else {
10075 int i;
10076 for (i = 0; i < list->nbItems; i++) {
10077 cur = (xmlSchemaBucketPtr) list->items[i];
10078 /* Pointer comparison! */
10079 if ((cur->origTargetNamespace == NULL) &&
10080 (cur->schemaLocation == schemaLocation) &&
10081 (cur->targetNamespace == targetNamespace))
10082 return(cur);
10083 }
10084 }
10085 return(NULL);
10086}
10087
10088
10089#define IS_BAD_SCHEMA_DOC(b) \
10090 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10091
10092static xmlSchemaBucketPtr
10093xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10094 const xmlChar *targetNamespace,
10095 int imported)
10096{
10097 xmlSchemaBucketPtr cur;
10098 xmlSchemaItemListPtr list;
10099
10100 list = pctxt->constructor->buckets;
10101 if (list->nbItems == 0)
10102 return(NULL);
10103 else {
10104 int i;
10105 for (i = 0; i < list->nbItems; i++) {
10106 cur = (xmlSchemaBucketPtr) list->items[i];
10107 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10108 (cur->origTargetNamespace == targetNamespace) &&
10109 ((imported && cur->imported) ||
10110 ((!imported) && (!cur->imported))))
10111 return(cur);
10112 }
10113 }
10114 return(NULL);
10115}
10116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010117static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010118xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10119 xmlSchemaPtr schema,
10120 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010121{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010122 int oldFlags;
10123 xmlDocPtr oldDoc;
10124 xmlNodePtr node;
10125 int ret, oldErrs;
10126 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000010127
10128 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010129 * Save old values; reset the *main* schema.
10130 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010131 * to the parser. Get rid of passing the main schema to the
10132 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010133 */
10134 oldFlags = schema->flags;
10135 oldDoc = schema->doc;
10136 if (schema->flags != 0)
10137 xmlSchemaClearSchemaDefaults(schema);
Daniel Veillarddee23482008-04-11 12:58:43 +000010138 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010139 pctxt->schema = schema;
Daniel Veillarddee23482008-04-11 12:58:43 +000010140 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010141 * Keep the current target namespace on the parser *not* on the
10142 * main schema.
10143 */
10144 pctxt->targetNamespace = bucket->targetNamespace;
10145 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010146
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010147 if ((bucket->targetNamespace != NULL) &&
10148 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010149 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010150 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010151 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010152 pctxt->isS4S = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000010153 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010154 /* Mark it as parsed, even if parsing fails. */
10155 bucket->parsed++;
10156 /* Compile the schema doc. */
10157 node = xmlDocGetRootElement(bucket->doc);
10158 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10159 if (ret != 0)
10160 goto exit;
10161 /* An empty schema; just get out. */
10162 if (node->children == NULL)
10163 goto exit;
10164 oldErrs = pctxt->nberrors;
10165 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10166 if (ret != 0)
10167 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010168 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010169 * TODO: Not nice, but I'm not 100% sure we will get always an error
10170 * as a result of the obove functions; so better rely on pctxt->err
10171 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010172 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010173 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10174 ret = pctxt->err;
10175 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010176 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010177
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010178exit:
10179 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10180 /* Restore schema values. */
10181 schema->doc = oldDoc;
10182 schema->flags = oldFlags;
10183 return(ret);
10184}
10185
10186static int
10187xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10188 xmlSchemaPtr schema,
10189 xmlSchemaBucketPtr bucket)
10190{
10191 xmlSchemaParserCtxtPtr newpctxt;
10192 int res = 0;
10193
10194 if (bucket == NULL)
10195 return(0);
10196 if (bucket->parsed) {
10197 PERROR_INT("xmlSchemaParseNewDoc",
10198 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010199 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010201 if (bucket->doc == NULL) {
10202 PERROR_INT("xmlSchemaParseNewDoc",
10203 "parsing a schema doc, but there's no doc");
10204 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010205 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010206 if (pctxt->constructor == NULL) {
10207 PERROR_INT("xmlSchemaParseNewDoc",
10208 "no constructor");
10209 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000010210 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010211 /* Create and init the temporary parser context. */
10212 newpctxt = xmlSchemaNewParserCtxtUseDict(
10213 (const char *) bucket->schemaLocation, pctxt->dict);
10214 if (newpctxt == NULL)
10215 return(-1);
10216 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010217 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000010218 * TODO: Can we avoid that the parser knows about the main schema?
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010219 * It would be better if he knows about the current schema bucket
10220 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010221 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010222 newpctxt->schema = schema;
10223 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010224 pctxt->errCtxt);
10225 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10226 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010227 newpctxt->counter = pctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010228
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010229
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010230 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
Daniel Veillarddee23482008-04-11 12:58:43 +000010231
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010232 /* Channel back errors and cleanup the temporary parser context. */
10233 if (res != 0)
10234 pctxt->err = res;
10235 pctxt->nberrors += newpctxt->nberrors;
10236 pctxt->counter = newpctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010237 newpctxt->constructor = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010238 /* Free the parser context. */
10239 xmlSchemaFreeParserCtxt(newpctxt);
10240 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010241}
William M. Brack2f2a6632004-08-20 23:09:47 +000010242
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010243static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010244xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10245 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010246{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010247 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010248
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010249 if (cur == NULL) {
10250 bucket->relations = rel;
10251 return;
10252 }
10253 while (cur->next != NULL)
10254 cur = cur->next;
10255 cur->next = rel;
10256}
10257
10258
10259static const xmlChar *
10260xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10261 xmlNodePtr ctxtNode)
Daniel Veillarddee23482008-04-11 12:58:43 +000010262{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010263 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010264 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010265 */
Daniel Veillarddee23482008-04-11 12:58:43 +000010266 if (location != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010267 if (ctxtNode == NULL)
10268 return(location);
10269 else {
10270 xmlChar *base, *URI;
10271 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010272
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010273 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10274 if (base == NULL) {
10275 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10276 } else {
10277 URI = xmlBuildURI(location, base);
10278 xmlFree(base);
10279 }
10280 if (URI != NULL) {
10281 ret = xmlDictLookup(dict, URI, -1);
10282 xmlFree(URI);
10283 return(ret);
10284 }
10285 }
10286 }
10287 return(NULL);
10288}
Daniel Veillarddee23482008-04-11 12:58:43 +000010289
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010290
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010291
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010292/**
10293 * xmlSchemaAddSchemaDoc:
10294 * @pctxt: a schema validation context
10295 * @schema: the schema being built
10296 * @node: a subtree containing XML Schema informations
10297 *
10298 * Parse an included (and to-be-redefined) XML schema document.
10299 *
10300 * Returns 0 on success, a positive error code on errors and
10301 * -1 in case of an internal or API error.
10302 */
10303
10304static int
10305xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10306 int type, /* import or include or redefine */
10307 const xmlChar *schemaLocation,
10308 xmlDocPtr schemaDoc,
10309 const char *schemaBuffer,
10310 int schemaBufferLen,
10311 xmlNodePtr invokingNode,
Daniel Veillarddee23482008-04-11 12:58:43 +000010312 const xmlChar *sourceTargetNamespace,
10313 const xmlChar *importNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010314 xmlSchemaBucketPtr *bucket)
10315{
10316 const xmlChar *targetNamespace = NULL;
10317 xmlSchemaSchemaRelationPtr relation = NULL;
10318 xmlDocPtr doc = NULL;
10319 int res = 0, err = 0, located = 0, preserveDoc = 0;
10320 xmlSchemaBucketPtr bkt = NULL;
10321
10322 if (bucket != NULL)
10323 *bucket = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010324
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010325 switch (type) {
10326 case XML_SCHEMA_SCHEMA_IMPORT:
10327 case XML_SCHEMA_SCHEMA_MAIN:
10328 err = XML_SCHEMAP_SRC_IMPORT;
10329 break;
10330 case XML_SCHEMA_SCHEMA_INCLUDE:
10331 err = XML_SCHEMAP_SRC_INCLUDE;
10332 break;
10333 case XML_SCHEMA_SCHEMA_REDEFINE:
10334 err = XML_SCHEMAP_SRC_REDEFINE;
10335 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000010336 }
10337
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010338
10339 /* Special handling for the main schema:
10340 * skip the location and relation logic and just parse the doc.
10341 * We need just a bucket to be returned in this case.
Daniel Veillarddee23482008-04-11 12:58:43 +000010342 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010343 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
Daniel Veillarddee23482008-04-11 12:58:43 +000010344 goto doc_load;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010345
Daniel Veillarddee23482008-04-11 12:58:43 +000010346 /* Note that we expect the location to be an absulute URI. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010347 if (schemaLocation != NULL) {
10348 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10349 if ((bkt != NULL) &&
10350 (pctxt->constructor->bucket == bkt)) {
10351 /* Report self-imports/inclusions/redefinitions. */
Daniel Veillarddee23482008-04-11 12:58:43 +000010352
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010353 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10354 invokingNode, NULL,
10355 "The schema must not import/include/redefine itself",
10356 NULL, NULL);
10357 goto exit;
10358 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010359 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010360 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010361 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010362 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010363 relation = xmlSchemaSchemaRelationCreate();
10364 if (relation == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010365 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010366 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10367 relation);
10368 relation->type = type;
10369
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010370 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010371 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010372 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010373 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010374 relation->importNamespace = importNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010375 if (schemaLocation == NULL) {
10376 /*
10377 * No location; this is just an import of the namespace.
10378 * Note that we don't assign a bucket to the relation
10379 * in this case.
10380 */
10381 goto exit;
10382 }
10383 targetNamespace = importNamespace;
10384 }
10385
10386 /* Did we already fetch the doc? */
Daniel Veillarddee23482008-04-11 12:58:43 +000010387 if (bkt != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010388 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010389 /*
10390 * We included/redefined and then try to import a schema,
10391 * but the new location provided for import was different.
10392 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010393 if (schemaLocation == NULL)
10394 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010395 if (!xmlStrEqual(schemaLocation,
10396 bkt->schemaLocation)) {
10397 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10398 invokingNode, NULL,
10399 "The schema document '%s' cannot be imported, since "
10400 "it was already included or redefined",
10401 schemaLocation, NULL);
10402 goto exit;
10403 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010404 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010405 /*
10406 * We imported and then try to include/redefine a schema,
10407 * but the new location provided for the include/redefine
10408 * was different.
10409 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010410 if (schemaLocation == NULL)
10411 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010412 if (!xmlStrEqual(schemaLocation,
10413 bkt->schemaLocation)) {
10414 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10415 invokingNode, NULL,
10416 "The schema document '%s' cannot be included or "
10417 "redefined, since it was already imported",
10418 schemaLocation, NULL);
10419 goto exit;
10420 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010421 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010422 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010423
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010424 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010425 /*
10426 * Given that the schemaLocation [attribute] is only a hint, it is open
10427 * to applications to ignore all but the first <import> for a given
Jan Pokorný761c9e92013-11-29 23:26:27 +010010428 * namespace, regardless of the `actual value` of schemaLocation, but
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010429 * such a strategy risks missing useful information when new
10430 * schemaLocations are offered.
10431 *
10432 * We will use the first <import> that comes with a location.
10433 * Further <import>s *with* a location, will result in an error.
10434 * TODO: Better would be to just report a warning here, but
10435 * we'll try it this way until someone complains.
10436 *
10437 * Schema Document Location Strategy:
10438 * 3 Based on the namespace name, identify an existing schema document,
10439 * either as a resource which is an XML document or a <schema> element
10440 * information item, in some local schema repository;
10441 * 5 Attempt to resolve the namespace name to locate such a resource.
10442 *
10443 * NOTE: (3) and (5) are not supported.
Daniel Veillarddee23482008-04-11 12:58:43 +000010444 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010445 if (bkt != NULL) {
10446 relation->bucket = bkt;
10447 goto exit;
10448 }
10449 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10450 importNamespace, 1);
10451
Daniel Veillarddee23482008-04-11 12:58:43 +000010452 if (bkt != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010453 relation->bucket = bkt;
10454 if (bkt->schemaLocation == NULL) {
10455 /* First given location of the schema; load the doc. */
10456 bkt->schemaLocation = schemaLocation;
10457 } else {
10458 if (!xmlStrEqual(schemaLocation,
10459 bkt->schemaLocation)) {
10460 /*
10461 * Additional location given; just skip it.
10462 * URGENT TODO: We should report a warning here.
10463 * res = XML_SCHEMAP_SRC_IMPORT;
10464 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010465 if (schemaLocation == NULL)
10466 schemaLocation = BAD_CAST "in_memory_buffer";
10467
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010468 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10469 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10470 invokingNode, NULL,
10471 "Skipping import of schema located at '%s' for the "
10472 "namespace '%s', since this namespace was already "
10473 "imported with the schema located at '%s'",
10474 schemaLocation, importNamespace, bkt->schemaLocation);
10475 }
10476 goto exit;
10477 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010478 }
10479 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010480 * No bucket + first location: load the doc and create a
10481 * bucket.
10482 */
10483 } else {
10484 /* <include> and <redefine> */
10485 if (bkt != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010486
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010487 if ((bkt->origTargetNamespace == NULL) &&
10488 (bkt->targetNamespace != sourceTargetNamespace)) {
10489 xmlSchemaBucketPtr chamel;
Daniel Veillarddee23482008-04-11 12:58:43 +000010490
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010491 /*
10492 * Chameleon include/redefine: skip loading only if it was
10493 * aleady build for the targetNamespace of the including
10494 * schema.
10495 */
10496 /*
10497 * URGENT TODO: If the schema is a chameleon-include then copy
10498 * the components into the including schema and modify the
10499 * targetNamespace of those components, do nothing otherwise.
10500 * NOTE: This is currently worked-around by compiling the
10501 * chameleon for every destinct including targetNamespace; thus
10502 * not performant at the moment.
10503 * TODO: Check when the namespace in wildcards for chameleons
10504 * needs to be converted: before we built wildcard intersections
10505 * or after.
10506 * Answer: after!
10507 */
10508 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10509 schemaLocation, sourceTargetNamespace);
10510 if (chamel != NULL) {
10511 /* A fitting chameleon was already parsed; NOP. */
10512 relation->bucket = chamel;
10513 goto exit;
10514 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010515 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010516 * We need to parse the chameleon again for a different
10517 * targetNamespace.
10518 * CHAMELEON TODO: Optimize this by only parsing the
10519 * chameleon once, and then copying the components to
10520 * the new targetNamespace.
10521 */
10522 bkt = NULL;
10523 } else {
10524 relation->bucket = bkt;
10525 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000010526 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010527 }
10528 }
10529 if ((bkt != NULL) && (bkt->doc != NULL)) {
10530 PERROR_INT("xmlSchemaAddSchemaDoc",
10531 "trying to load a schema doc, but a doc is already "
10532 "assigned to the schema bucket");
10533 goto exit_failure;
10534 }
10535
10536doc_load:
10537 /*
10538 * Load the document.
10539 */
10540 if (schemaDoc != NULL) {
10541 doc = schemaDoc;
10542 /* Don' free this one, since it was provided by the caller. */
10543 preserveDoc = 1;
10544 /* TODO: Does the context or the doc hold the location? */
10545 if (schemaDoc->URL != NULL)
10546 schemaLocation = xmlDictLookup(pctxt->dict,
10547 schemaDoc->URL, -1);
Daniel Veillard734e7662007-06-26 11:30:31 +000010548 else
10549 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010550 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10551 xmlParserCtxtPtr parserCtxt;
10552
10553 parserCtxt = xmlNewParserCtxt();
10554 if (parserCtxt == NULL) {
10555 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10556 "allocating a parser context", NULL);
10557 goto exit_failure;
10558 }
10559 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10560 /*
10561 * TODO: Do we have to burden the schema parser dict with all
10562 * the content of the schema doc?
10563 */
10564 xmlDictFree(parserCtxt->dict);
10565 parserCtxt->dict = pctxt->dict;
10566 xmlDictReference(parserCtxt->dict);
10567 }
10568 if (schemaLocation != NULL) {
10569 /* Parse from file. */
10570 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10571 NULL, SCHEMAS_PARSE_OPTIONS);
10572 } else if (schemaBuffer != NULL) {
10573 /* Parse from memory buffer. */
10574 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10575 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
Rob Richards410d2c42009-09-24 11:00:16 -040010576 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010577 if (doc != NULL)
Rob Richards410d2c42009-09-24 11:00:16 -040010578 doc->URL = xmlStrdup(schemaLocation);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010579 }
10580 /*
10581 * For <import>:
10582 * 2.1 The referent is (a fragment of) a resource which is an
10583 * XML document (see clause 1.1), which in turn corresponds to
10584 * a <schema> element information item in a well-formed information
10585 * set, which in turn corresponds to a valid schema.
10586 * TODO: (2.1) fragments of XML documents are not supported.
10587 *
10588 * 2.2 The referent is a <schema> element information item in
10589 * a well-formed information set, which in turn corresponds
10590 * to a valid schema.
10591 * TODO: (2.2) is not supported.
10592 */
10593 if (doc == NULL) {
10594 xmlErrorPtr lerr;
10595 lerr = xmlGetLastError();
10596 /*
10597 * Check if this a parser error, or if the document could
10598 * just not be located.
10599 * TODO: Try to find specific error codes to react only on
10600 * localisation failures.
10601 */
10602 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10603 /*
10604 * We assume a parser error here.
10605 */
10606 located = 1;
10607 /* TODO: Error code ?? */
10608 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10609 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10610 invokingNode, NULL,
10611 "Failed to parse the XML resource '%s'",
Daniel Veillard734e7662007-06-26 11:30:31 +000010612 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010613 }
10614 }
10615 xmlFreeParserCtxt(parserCtxt);
10616 if ((doc == NULL) && located)
10617 goto exit_error;
10618 } else {
10619 xmlSchemaPErr(pctxt, NULL,
10620 XML_SCHEMAP_NOTHING_TO_PARSE,
10621 "No information for parsing was provided with the "
10622 "given schema parser context.\n",
10623 NULL, NULL);
10624 goto exit_failure;
10625 }
10626 /*
10627 * Preprocess the document.
10628 */
10629 if (doc != NULL) {
10630 xmlNodePtr docElem = NULL;
10631
Daniel Veillarddee23482008-04-11 12:58:43 +000010632 located = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010633 docElem = xmlDocGetRootElement(doc);
10634 if (docElem == NULL) {
10635 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
Daniel Veillarddee23482008-04-11 12:58:43 +000010636 invokingNode, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010637 "The document '%s' has no document element",
10638 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010639 goto exit_error;
10640 }
10641 /*
10642 * Remove all the blank text nodes.
10643 */
10644 xmlSchemaCleanupDoc(pctxt, docElem);
10645 /*
10646 * Check the schema's top level element.
10647 */
10648 if (!IS_SCHEMA(docElem, "schema")) {
10649 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10650 invokingNode, NULL,
10651 "The XML document '%s' is not a schema document",
10652 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010653 goto exit_error;
10654 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010655 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010656 * Note that we don't apply a type check for the
10657 * targetNamespace value here.
10658 */
10659 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10660 "targetNamespace");
10661 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010662
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010663/* after_doc_loading: */
10664 if ((bkt == NULL) && located) {
10665 /* Only create a bucket if the schema was located. */
10666 bkt = xmlSchemaBucketCreate(pctxt, type,
10667 targetNamespace);
10668 if (bkt == NULL)
10669 goto exit_failure;
10670 }
10671 if (bkt != NULL) {
10672 bkt->schemaLocation = schemaLocation;
10673 bkt->located = located;
10674 if (doc != NULL) {
10675 bkt->doc = doc;
10676 bkt->targetNamespace = targetNamespace;
10677 bkt->origTargetNamespace = targetNamespace;
10678 if (preserveDoc)
10679 bkt->preserveDoc = 1;
10680 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010681 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010682 bkt->imported++;
10683 /*
10684 * Add it to the graph of schemas.
10685 */
10686 if (relation != NULL)
10687 relation->bucket = bkt;
10688 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010689
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010690exit:
10691 /*
10692 * Return the bucket explicitely; this is needed for the
10693 * main schema.
10694 */
10695 if (bucket != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010696 *bucket = bkt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010697 return (0);
10698
10699exit_error:
10700 if ((doc != NULL) && (! preserveDoc)) {
10701 xmlFreeDoc(doc);
10702 if (bkt != NULL)
10703 bkt->doc = NULL;
10704 }
10705 return(pctxt->err);
10706
10707exit_failure:
10708 if ((doc != NULL) && (! preserveDoc)) {
10709 xmlFreeDoc(doc);
10710 if (bkt != NULL)
10711 bkt->doc = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010712 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010713 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010714}
10715
William M. Brack2f2a6632004-08-20 23:09:47 +000010716/**
10717 * xmlSchemaParseImport:
10718 * @ctxt: a schema validation context
10719 * @schema: the schema being built
10720 * @node: a subtree containing XML Schema informations
10721 *
10722 * parse a XML schema Import definition
10723 * *WARNING* this interface is highly subject to change
10724 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010725 * Returns 0 in case of success, a positive error code if
10726 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010727 */
10728static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010729xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010730 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010731{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010732 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010733 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10734 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010735 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010736 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010737 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010738
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010739 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010740 return (-1);
10741
10742 /*
10743 * Check for illegal attributes.
10744 */
10745 attr = node->properties;
10746 while (attr != NULL) {
10747 if (attr->ns == NULL) {
10748 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10749 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10750 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010751 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010752 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010753 }
10754 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010755 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010756 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010757 }
10758 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010759 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010760 /*
10761 * Extract and validate attributes.
10762 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010763 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010764 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010765 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010766 xmlSchemaPSimpleTypeErr(pctxt,
10767 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010768 NULL, node,
10769 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010770 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010771 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010772 }
10773
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010774 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010775 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010776 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010777 xmlSchemaPSimpleTypeErr(pctxt,
10778 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010779 NULL, node,
10780 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Gauravf3d79412013-11-28 22:53:54 +080010781 NULL, schemaLocation, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010782 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010783 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010784 /*
10785 * And now for the children...
10786 */
10787 child = node->children;
10788 if (IS_SCHEMA(child, "annotation")) {
10789 /*
10790 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010791 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010792 */
10793 child = child->next;
10794 }
10795 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010796 xmlSchemaPContentErr(pctxt,
10797 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010798 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010799 "(annotation?)");
10800 }
10801 /*
10802 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010803 *
10804 * Note that it is important to use the original @targetNamespace
10805 * (or none at all), to rule out imports of schemas _with_ a
10806 * @targetNamespace if the importing schema is a chameleon schema
10807 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010808 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010809 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010810 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010811 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010010812 * 1.1 If the namespace [attribute] is present, then its `actual value`
10813 * must not match the `actual value` of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010814 * targetNamespace [attribute].
10815 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010816 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010817 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010818 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010819 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010820 "The value of the attribute 'namespace' must not match "
10821 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010822 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010823 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010824 }
10825 } else {
10826 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010827 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010828 * <schema> must have a targetNamespace [attribute].
10829 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010830 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010831 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010832 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010833 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010834 "The attribute 'namespace' must be existent if "
10835 "the importing schema has no target namespace",
10836 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010837 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010838 }
10839 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010840 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010841 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010842 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010843 if (schemaLocation != NULL)
10844 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10845 schemaLocation, node);
10846 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010847 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010848 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010849
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010850 if (ret != 0)
10851 return(ret);
10852
10853 /*
10854 * For <import>: "It is *not* an error for the application
10855 * schema reference strategy to fail."
10856 * So just don't parse if no schema document was found.
10857 * Note that we will get no bucket if the schema could not be
10858 * located or if there was no schemaLocation.
10859 */
10860 if ((bucket == NULL) && (schemaLocation != NULL)) {
10861 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10862 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10863 node, NULL,
10864 "Failed to locate a schema at location '%s'. "
10865 "Skipping the import", schemaLocation, NULL, NULL);
10866 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010867
10868 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010869 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10870 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010871
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010872 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010873}
10874
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010875static int
10876xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10877 xmlSchemaPtr schema,
10878 xmlNodePtr node,
10879 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010880 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010881{
10882 xmlAttrPtr attr;
10883
10884 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10885 (schemaLocation == NULL))
10886 return (-1);
10887
10888 *schemaLocation = NULL;
10889 /*
10890 * Check for illegal attributes.
10891 * Applies for both <include> and <redefine>.
10892 */
10893 attr = node->properties;
10894 while (attr != NULL) {
10895 if (attr->ns == NULL) {
10896 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10897 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10898 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900 }
10901 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10902 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010904 }
10905 attr = attr->next;
10906 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010907 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010908 /*
10909 * Preliminary step, extract the URI-Reference and make an URI
10910 * from the base.
10911 */
10912 /*
10913 * Attribute "schemaLocation" is mandatory.
10914 */
10915 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10916 if (attr != NULL) {
10917 xmlChar *base = NULL;
10918 xmlChar *uri = NULL;
10919
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010920 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010921 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10922 (const xmlChar **) schemaLocation) != 0)
10923 goto exit_error;
10924 base = xmlNodeGetBase(node->doc, node);
10925 if (base == NULL) {
10926 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10927 } else {
10928 uri = xmlBuildURI(*schemaLocation, base);
10929 xmlFree(base);
10930 }
10931 if (uri == NULL) {
10932 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10933 "could not build an URI from the schemaLocation")
10934 goto exit_failure;
10935 }
10936 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10937 xmlFree(uri);
10938 } else {
10939 xmlSchemaPMissingAttrErr(pctxt,
10940 XML_SCHEMAP_S4S_ATTR_MISSING,
10941 NULL, node, "schemaLocation", NULL);
10942 goto exit_error;
10943 }
10944 /*
10945 * Report self-inclusion and self-redefinition.
10946 */
10947 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010948 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010949 xmlSchemaPCustomErr(pctxt,
10950 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010951 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010952 "The schema document '%s' cannot redefine itself.",
Daniel Veillarddee23482008-04-11 12:58:43 +000010953 *schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010954 } else {
10955 xmlSchemaPCustomErr(pctxt,
10956 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010957 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010958 "The schema document '%s' cannot include itself.",
10959 *schemaLocation);
10960 }
10961 goto exit_error;
10962 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010963
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010964 return(0);
10965exit_error:
10966 return(pctxt->err);
10967exit_failure:
10968 return(-1);
10969}
10970
10971static int
10972xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10973 xmlSchemaPtr schema,
10974 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010975 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010976{
10977 xmlNodePtr child = NULL;
10978 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010979 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010980 int isChameleon = 0, wasChameleon = 0;
10981 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010982
10983 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10984 return (-1);
10985
10986 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010987 * Parse attributes. Note that the returned schemaLocation will
10988 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010989 */
10990 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010991 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010992 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000010993 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010994 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010995 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010996 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010997 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10998 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010999 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000011000 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011001 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011002 * If we get no schema bucket back, then this means that the schema
11003 * document could not be located or was broken XML or was not
11004 * a schema document.
Daniel Veillarddee23482008-04-11 12:58:43 +000011005 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011006 if ((bucket == NULL) || (bucket->doc == NULL)) {
11007 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11008 /*
11009 * WARNING for <include>:
11010 * We will raise an error if the schema cannot be located
11011 * for inclusions, since the that was the feedback from the
11012 * schema people. I.e. the following spec piece will *not* be
11013 * satisfied:
Jan Pokorný761c9e92013-11-29 23:26:27 +010011014 * SPEC src-include: "It is not an error for the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011015 * schemaLocation [attribute] to fail to resolve it all, in which
11016 * case no corresponding inclusion is performed.
11017 * So do we need a warning report here?"
11018 */
11019 res = XML_SCHEMAP_SRC_INCLUDE;
11020 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11021 node, NULL,
11022 "Failed to load the document '%s' for inclusion",
11023 schemaLocation, NULL);
11024 } else {
11025 /*
11026 * NOTE: This was changed to raise an error even if no redefinitions
11027 * are specified.
11028 *
11029 * SPEC src-redefine (1)
11030 * "If there are any element information items among the [children]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011031 * other than <annotation> then the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011032 * schemaLocation [attribute] must successfully resolve."
11033 * TODO: Ask the WG if a the location has always to resolve
11034 * here as well!
11035 */
11036 res = XML_SCHEMAP_SRC_REDEFINE;
11037 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11038 node, NULL,
11039 "Failed to load the document '%s' for redefinition",
11040 schemaLocation, NULL);
11041 }
11042 } else {
11043 /*
11044 * Check targetNamespace sanity before parsing the new schema.
11045 * TODO: Note that we won't check further content if the
11046 * targetNamespace was bad.
Daniel Veillarddee23482008-04-11 12:58:43 +000011047 */
11048 if (bucket->origTargetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011049 /*
11050 * SPEC src-include (2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010011051 * "SII has a targetNamespace [attribute], and its `actual
11052 * value` is identical to the `actual value` of the targetNamespace
11053 * [attribute] of SII' (which must have such an [attribute])."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011054 */
11055 if (pctxt->targetNamespace == NULL) {
11056 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11057 XML_SCHEMAP_SRC_INCLUDE,
11058 node, NULL,
11059 "The target namespace of the included/redefined schema "
11060 "'%s' has to be absent, since the including/redefining "
11061 "schema has no target namespace",
11062 schemaLocation, NULL);
11063 goto exit_error;
11064 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11065 pctxt->targetNamespace)) {
11066 /* TODO: Change error function. */
11067 xmlSchemaPCustomErrExt(pctxt,
11068 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011069 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011070 "The target namespace '%s' of the included/redefined "
11071 "schema '%s' differs from '%s' of the "
11072 "including/redefining schema",
11073 bucket->origTargetNamespace, schemaLocation,
11074 pctxt->targetNamespace);
11075 goto exit_error;
11076 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011077 } else if (pctxt->targetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011078 /*
11079 * Chameleons: the original target namespace will
11080 * differ from the resulting namespace.
11081 */
11082 isChameleon = 1;
11083 if (bucket->parsed &&
Jason Childsedc68aa2009-08-07 20:29:33 +020011084 bucket->origTargetNamespace != NULL) {
11085 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11086 XML_SCHEMAP_SRC_INCLUDE,
11087 node, NULL,
11088 "The target namespace of the included/redefined schema "
11089 "'%s' has to be absent or the same as the "
11090 "including/redefining schema's target namespace",
11091 schemaLocation, NULL);
11092 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011093 }
11094 bucket->targetNamespace = pctxt->targetNamespace;
11095 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011096 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011097 /*
11098 * Parse the schema.
Daniel Veillarddee23482008-04-11 12:58:43 +000011099 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011100 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11101 if (isChameleon) {
11102 /* TODO: Get rid of this flag on the schema itself. */
11103 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11104 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11105 } else
11106 wasChameleon = 1;
11107 }
11108 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11109 /* Restore chameleon flag. */
11110 if (isChameleon && (!wasChameleon))
11111 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11112 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011113 /*
11114 * And now for the children...
11115 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011116 child = node->children;
11117 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011118 /*
11119 * Parse (simpleType | complexType | group | attributeGroup))*
11120 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011121 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011122 /*
11123 * How to proceed if the redefined schema was not located?
11124 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011125 pctxt->isRedefine = 1;
11126 while (IS_SCHEMA(child, "annotation") ||
11127 IS_SCHEMA(child, "simpleType") ||
11128 IS_SCHEMA(child, "complexType") ||
11129 IS_SCHEMA(child, "group") ||
11130 IS_SCHEMA(child, "attributeGroup")) {
11131 if (IS_SCHEMA(child, "annotation")) {
11132 /*
11133 * TODO: discard or not?
11134 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011135 } else if (IS_SCHEMA(child, "simpleType")) {
11136 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11137 } else if (IS_SCHEMA(child, "complexType")) {
11138 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011139 /* hasRedefinitions = 1; */
Daniel Veillarddee23482008-04-11 12:58:43 +000011140 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011141 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011142 xmlSchemaParseModelGroupDefinition(pctxt,
11143 schema, child);
11144 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011145 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011146 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11147 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011148 }
11149 child = child->next;
11150 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011151 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011152 pctxt->isRedefine = 0;
11153 } else {
11154 if (IS_SCHEMA(child, "annotation")) {
11155 /*
11156 * TODO: discard or not?
11157 */
11158 child = child->next;
11159 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011160 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011161 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011162 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011163 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11164 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011165 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011166 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11167 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011168 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011169 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011170 "(annotation?)");
Daniel Veillarddee23482008-04-11 12:58:43 +000011171 }
11172 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011173 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011174
11175exit_error:
11176 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011177}
11178
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011179static int
11180xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11181 xmlNodePtr node)
11182{
11183 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011184#ifndef ENABLE_REDEFINE
11185 TODO
11186 return(0);
11187#endif
11188 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11189 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011190 if (res != 0)
11191 return(res);
11192 return(0);
11193}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011194
11195static int
11196xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11197 xmlNodePtr node)
11198{
11199 int res;
11200
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011201 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11202 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011203 if (res != 0)
11204 return(res);
11205 return(0);
11206}
11207
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011208/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011209 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011210 * @ctxt: a schema validation context
11211 * @schema: the schema being built
11212 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 * @type: the "compositor" type
11214 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011215 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011216 * parse a XML schema Sequence definition.
11217 * Applies parts of:
11218 * Schema Representation Constraint:
11219 * Redefinition Constraints and Semantics (src-redefine)
11220 * (6.1), (6.1.1), (6.1.2)
11221 *
Daniel Veillarddee23482008-04-11 12:58:43 +000011222 * Schema Component Constraint:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011223 * All Group Limited (cos-all-limited) (2)
11224 * TODO: Actually this should go to component-level checks,
11225 * but is done here due to performance. Move it to an other layer
11226 * is schema construction via an API is implemented.
11227 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011228 * *WARNING* this interface is highly subject to change
11229 *
William M. Bracke7091952004-05-11 15:09:58 +000011230 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011231 * 1 in case of success.
11232 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233static xmlSchemaTreeItemPtr
11234xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11235 xmlNodePtr node, xmlSchemaTypeType type,
11236 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011237{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 xmlSchemaModelGroupPtr item;
11239 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011240 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011241 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011242 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011243
11244 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011245 return (NULL);
11246 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011247 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011248 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011249 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011250 if (item == NULL)
11251 return (NULL);
11252
11253 if (withParticle) {
11254 if (type == XML_SCHEMA_TYPE_ALL) {
11255 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011256 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 } else {
11258 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011259 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11260 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11261 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011262 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011263 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11264 /*
11265 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000011267 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011269 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011270 particle->children = (xmlSchemaTreeItemPtr) item;
11271 /*
11272 * Check for illegal attributes.
11273 */
11274 attr = node->properties;
11275 while (attr != NULL) {
11276 if (attr->ns == NULL) {
11277 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11278 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11279 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011280 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 }
11283 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011284 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011285 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011286 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011288 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 } else {
11290 /*
11291 * Check for illegal attributes.
11292 */
11293 attr = node->properties;
11294 while (attr != NULL) {
11295 if (attr->ns == NULL) {
11296 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011297 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011298 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 }
11300 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011301 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011302 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011303 }
11304 attr = attr->next;
11305 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011306 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011307
William M. Brack2f2a6632004-08-20 23:09:47 +000011308 /*
11309 * Extract and validate attributes.
11310 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011311 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011312 /*
11313 * And now for the children...
11314 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011315 child = node->children;
11316 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011317 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011318 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011319 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011320 if (type == XML_SCHEMA_TYPE_ALL) {
11321 xmlSchemaParticlePtr part, last = NULL;
11322
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011323 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011324 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011325 schema, child, &isElemRef, 0);
11326 /*
11327 * SPEC cos-all-limited (2)
11328 * "The {max occurs} of all the particles in the {particles}
11329 * of the ('all') group must be 0 or 1.
11330 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011331 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011332 if (isElemRef)
11333 hasRefs++;
11334 if (part->minOccurs > 1) {
11335 xmlSchemaPCustomErr(ctxt,
11336 XML_SCHEMAP_COS_ALL_LIMITED,
11337 NULL, child,
11338 "Invalid value for minOccurs (must be 0 or 1)",
11339 NULL);
11340 /* Reset to 1. */
11341 part->minOccurs = 1;
11342 }
11343 if (part->maxOccurs > 1) {
11344 xmlSchemaPCustomErr(ctxt,
11345 XML_SCHEMAP_COS_ALL_LIMITED,
11346 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011347 "Invalid value for maxOccurs (must be 0 or 1)",
11348 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011349 /* Reset to 1. */
11350 part->maxOccurs = 1;
11351 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 if (last == NULL)
11353 item->children = (xmlSchemaTreeItemPtr) part;
11354 else
11355 last->next = (xmlSchemaTreeItemPtr) part;
11356 last = part;
11357 }
11358 child = child->next;
11359 }
11360 if (child != NULL) {
11361 xmlSchemaPContentErr(ctxt,
11362 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011363 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011364 "(annotation?, (annotation?, element*)");
11365 }
11366 } else {
11367 /* choice + sequence */
11368 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11369
11370 while ((IS_SCHEMA(child, "element")) ||
11371 (IS_SCHEMA(child, "group")) ||
11372 (IS_SCHEMA(child, "any")) ||
11373 (IS_SCHEMA(child, "choice")) ||
11374 (IS_SCHEMA(child, "sequence"))) {
11375
11376 if (IS_SCHEMA(child, "element")) {
11377 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011378 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11379 if (part && isElemRef)
11380 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011381 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011382 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011383 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011384 if (part != NULL)
11385 hasRefs++;
11386 /*
11387 * Handle redefinitions.
11388 */
11389 if (ctxt->isRedefine && ctxt->redef &&
11390 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11391 part && part->children)
11392 {
11393 if ((xmlSchemaGetQNameRefName(part->children) ==
11394 ctxt->redef->refName) &&
11395 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11396 ctxt->redef->refTargetNs))
11397 {
11398 /*
11399 * SPEC src-redefine:
11400 * (6.1) "If it has a <group> among its contents at
Jan Pokorný761c9e92013-11-29 23:26:27 +010011401 * some level the `actual value` of whose ref
11402 * [attribute] is the same as the `actual value` of
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011403 * its own name attribute plus target namespace, then
11404 * all of the following must be true:"
11405 * (6.1.1) "It must have exactly one such group."
11406 */
11407 if (ctxt->redefCounter != 0) {
11408 xmlChar *str = NULL;
11409
11410 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11411 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11412 "The redefining model group definition "
11413 "'%s' must not contain more than one "
11414 "reference to the redefined definition",
11415 xmlSchemaFormatQName(&str,
11416 ctxt->redef->refTargetNs,
11417 ctxt->redef->refName),
11418 NULL);
11419 FREE_AND_NULL(str)
11420 part = NULL;
11421 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11422 ((WXS_PARTICLE(part))->maxOccurs != 1))
11423 {
11424 xmlChar *str = NULL;
11425 /*
11426 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010011427 * (6.1.2) "The `actual value` of both that
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011428 * group's minOccurs and maxOccurs [attribute]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011429 * must be 1 (or `absent`).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011430 */
11431 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11432 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11433 "The redefining model group definition "
11434 "'%s' must not contain a reference to the "
11435 "redefined definition with a "
11436 "maxOccurs/minOccurs other than 1",
11437 xmlSchemaFormatQName(&str,
11438 ctxt->redef->refTargetNs,
11439 ctxt->redef->refName),
11440 NULL);
11441 FREE_AND_NULL(str)
11442 part = NULL;
11443 }
11444 ctxt->redef->reference = WXS_BASIC_CAST part;
11445 ctxt->redefCounter++;
Daniel Veillarddee23482008-04-11 12:58:43 +000011446 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011447 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011448 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011450 xmlSchemaParseAny(ctxt, schema, child);
11451 } else if (IS_SCHEMA(child, "choice")) {
11452 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11453 XML_SCHEMA_TYPE_CHOICE, 1);
11454 } else if (IS_SCHEMA(child, "sequence")) {
11455 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11456 XML_SCHEMA_TYPE_SEQUENCE, 1);
11457 }
11458 if (part != NULL) {
11459 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011460 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011461 else
11462 last->next = part;
11463 last = part;
11464 }
11465 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011466 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 if (child != NULL) {
11468 xmlSchemaPContentErr(ctxt,
11469 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011470 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011471 "(annotation?, (element | group | choice | sequence | any)*)");
11472 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011473 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011474 if ((max == 0) && (min == 0))
11475 return (NULL);
11476 if (hasRefs) {
11477 /*
11478 * We need to resolve references.
11479 */
11480 WXS_ADD_PENDING(ctxt, item);
11481 }
11482 if (withParticle)
Daniel Veillarddee23482008-04-11 12:58:43 +000011483 return ((xmlSchemaTreeItemPtr) particle);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011484 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011485 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011486}
11487
11488/**
11489 * xmlSchemaParseRestriction:
11490 * @ctxt: a schema validation context
11491 * @schema: the schema being built
11492 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000011493 *
11494 * parse a XML schema Restriction definition
11495 * *WARNING* this interface is highly subject to change
11496 *
11497 * Returns the type definition or NULL in case of error
11498 */
11499static xmlSchemaTypePtr
11500xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011501 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011502{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011503 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011504 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011505 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011506
11507 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11508 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011509 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011510 type = ctxt->ctxtType;
11511 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011512
11513 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011514 * Check for illegal attributes.
11515 */
11516 attr = node->properties;
11517 while (attr != NULL) {
11518 if (attr->ns == NULL) {
11519 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11520 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011522 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011523 }
11524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011525 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011527 }
11528 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011530 /*
11531 * Extract and validate attributes.
11532 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011533 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011534 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000011535 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011536 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011538 * Extract the base type. The "base" attribute is mandatory if inside
11539 * a complex type or if redefining.
11540 *
11541 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011542 * among its [children]), the simple type definition which is
Jan Pokorný761c9e92013-11-29 23:26:27 +010011543 * the {content type} of the type definition `resolved` to by
11544 * the `actual value` of the base [attribute]"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011545 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011546 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011547 &(type->baseNs), &(type->base)) == 0)
11548 {
11549 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11550 xmlSchemaPMissingAttrErr(ctxt,
11551 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011552 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011553 } else if ((ctxt->isRedefine) &&
11554 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11555 {
11556 if (type->base == NULL) {
11557 xmlSchemaPMissingAttrErr(ctxt,
11558 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011559 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011560 } else if ((! xmlStrEqual(type->base, type->name)) ||
11561 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11562 {
11563 xmlChar *str1 = NULL, *str2 = NULL;
11564 /*
11565 * REDEFINE: SPEC src-redefine (5)
11566 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +010011567 * <restriction> among its [children] ... the `actual value` of
11568 * whose base [attribute] must be the same as the `actual value`
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011569 * of its own name attribute plus target namespace;"
11570 */
11571 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011572 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011573 "value '%s' of the 'base' attribute does not match the "
11574 "type's designation '%s'",
11575 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
Daniel Veillardfef73a52006-03-27 09:38:57 +000011576 xmlSchemaFormatQName(&str2, type->targetNamespace,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011577 type->name), NULL);
11578 FREE_AND_NULL(str1);
11579 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011580 /* Avoid confusion and erase the values. */
11581 type->base = NULL;
11582 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011583 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011584 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011586 /*
11587 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011589 child = node->children;
11590 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011591 /*
11592 * Add the annotation to the simple type ancestor.
11593 */
11594 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011595 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011596 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011597 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11599 /*
11600 * Corresponds to <simpleType><restriction><simpleType>.
11601 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011602 if (IS_SCHEMA(child, "simpleType")) {
11603 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011604 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011605 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011606 * Either the base [attribute] or the simpleType [child] of the
11607 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011608 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011609 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011610 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011611 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011612 "The attribute 'base' and the <simpleType> child are "
11613 "mutually exclusive", NULL);
11614 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011615 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011616 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011617 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011618 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011619 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011620 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011621 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011622 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011623 "Either the attribute 'base' or a <simpleType> child "
11624 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011625 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011626 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11627 /*
11628 * Corresponds to <complexType><complexContent><restriction>...
11629 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011630 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011631 * Model groups <all>, <choice> and <sequence>.
11632 */
11633 if (IS_SCHEMA(child, "all")) {
11634 type->subtypes = (xmlSchemaTypePtr)
11635 xmlSchemaParseModelGroup(ctxt, schema, child,
11636 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011637 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011638 } else if (IS_SCHEMA(child, "choice")) {
11639 type->subtypes = (xmlSchemaTypePtr)
11640 xmlSchemaParseModelGroup(ctxt,
11641 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11642 child = child->next;
11643 } else if (IS_SCHEMA(child, "sequence")) {
11644 type->subtypes = (xmlSchemaTypePtr)
11645 xmlSchemaParseModelGroup(ctxt, schema, child,
11646 XML_SCHEMA_TYPE_SEQUENCE, 1);
11647 child = child->next;
11648 /*
11649 * Model group reference <group>.
11650 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011651 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011652 type->subtypes = (xmlSchemaTypePtr)
11653 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011654 /*
11655 * Note that the reference will be resolved in
11656 * xmlSchemaResolveTypeReferences();
11657 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011658 child = child->next;
11659 }
11660 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011661 /*
11662 * Corresponds to <complexType><simpleContent><restriction>...
11663 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011664 * "1.1 the simple type definition corresponding to the <simpleType>
11665 * among the [children] of <restriction> if there is one;"
11666 */
11667 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011668 /*
11669 * We will store the to-be-restricted simple type in
11670 * type->contentTypeDef *temporarily*.
11671 */
11672 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011673 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011674 if ( type->contentTypeDef == NULL)
11675 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011676 child = child->next;
11677 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011678 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011679
11680 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011681 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011682 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011683 /*
11684 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011685 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011686 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011687
Daniel Veillard01fa6152004-06-29 17:04:39 +000011688 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011689 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011690 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011692 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11693 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011694 * *Single Facet Value*
11695 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011696 while ((IS_SCHEMA(child, "minInclusive")) ||
11697 (IS_SCHEMA(child, "minExclusive")) ||
11698 (IS_SCHEMA(child, "maxInclusive")) ||
11699 (IS_SCHEMA(child, "maxExclusive")) ||
11700 (IS_SCHEMA(child, "totalDigits")) ||
11701 (IS_SCHEMA(child, "fractionDigits")) ||
11702 (IS_SCHEMA(child, "pattern")) ||
11703 (IS_SCHEMA(child, "enumeration")) ||
11704 (IS_SCHEMA(child, "whiteSpace")) ||
11705 (IS_SCHEMA(child, "length")) ||
11706 (IS_SCHEMA(child, "maxLength")) ||
11707 (IS_SCHEMA(child, "minLength"))) {
11708 facet = xmlSchemaParseFacet(ctxt, schema, child);
11709 if (facet != NULL) {
11710 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011711 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011712 else
11713 lastfacet->next = facet;
11714 lastfacet = facet;
11715 lastfacet->next = NULL;
11716 }
11717 child = child->next;
11718 }
11719 /*
11720 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011721 */
11722 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011723 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011725 facet = type->facets;
11726 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011727 facetLink = (xmlSchemaFacetLinkPtr)
11728 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011729 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011730 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011731 xmlFree(facetLink);
11732 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011733 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011734 facetLink->facet = facet;
11735 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011736 if (lastFacetLink == NULL)
11737 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011738 else
11739 lastFacetLink->next = facetLink;
11740 lastFacetLink = facetLink;
11741 facet = facet->next;
11742 } while (facet != NULL);
11743 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011744 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11746 /*
11747 * Attribute uses/declarations.
11748 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011749 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11750 (xmlSchemaItemListPtr *) &(type->attrUses),
11751 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11752 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011753 /*
11754 * Attribute wildcard.
11755 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011756 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011757 type->attributeWildcard =
11758 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011759 child = child->next;
11760 }
11761 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011762 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011763 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11764 xmlSchemaPContentErr(ctxt,
11765 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011766 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011767 "annotation?, (group | all | choice | sequence)?, "
11768 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011769 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011770 xmlSchemaPContentErr(ctxt,
11771 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011772 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011773 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11774 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11775 "length | minLength | maxLength | enumeration | whiteSpace | "
11776 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11777 } else {
11778 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011779 xmlSchemaPContentErr(ctxt,
11780 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011781 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011782 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11783 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11784 "length | minLength | maxLength | enumeration | whiteSpace | "
11785 "pattern)*))");
11786 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011788 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011789}
11790
11791/**
11792 * xmlSchemaParseExtension:
11793 * @ctxt: a schema validation context
11794 * @schema: the schema being built
11795 * @node: a subtree containing XML Schema informations
11796 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011797 * Parses an <extension>, which is found inside a
11798 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011800 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011801 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011802 */
11803static xmlSchemaTypePtr
11804xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011805 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011806{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011807 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011808 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011809 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011810
11811 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11812 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011813 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011814 type = ctxt->ctxtType;
11815 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011816
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011817 /*
11818 * Check for illegal attributes.
11819 */
11820 attr = node->properties;
11821 while (attr != NULL) {
11822 if (attr->ns == NULL) {
11823 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11824 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011825 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011826 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011827 }
11828 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011829 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011830 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011831 }
11832 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011833 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011834
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011835 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011836
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011837 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011838 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011839 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011840 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11841 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011842 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011843 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011844 XML_SCHEMAP_S4S_ATTR_MISSING,
11845 NULL, node, "base", NULL);
11846 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011847 /*
11848 * And now for the children...
11849 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011850 child = node->children;
11851 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011852 /*
11853 * Add the annotation to the type ancestor.
11854 */
11855 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011856 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011857 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011858 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011859 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11860 /*
11861 * Corresponds to <complexType><complexContent><extension>... and:
11862 *
11863 * Model groups <all>, <choice>, <sequence> and <group>.
11864 */
11865 if (IS_SCHEMA(child, "all")) {
11866 type->subtypes = (xmlSchemaTypePtr)
11867 xmlSchemaParseModelGroup(ctxt, schema,
11868 child, XML_SCHEMA_TYPE_ALL, 1);
11869 child = child->next;
11870 } else if (IS_SCHEMA(child, "choice")) {
11871 type->subtypes = (xmlSchemaTypePtr)
11872 xmlSchemaParseModelGroup(ctxt, schema,
11873 child, XML_SCHEMA_TYPE_CHOICE, 1);
11874 child = child->next;
11875 } else if (IS_SCHEMA(child, "sequence")) {
11876 type->subtypes = (xmlSchemaTypePtr)
11877 xmlSchemaParseModelGroup(ctxt, schema,
11878 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11879 child = child->next;
11880 } else if (IS_SCHEMA(child, "group")) {
11881 type->subtypes = (xmlSchemaTypePtr)
11882 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011883 /*
11884 * Note that the reference will be resolved in
11885 * xmlSchemaResolveTypeReferences();
11886 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011887 child = child->next;
11888 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011889 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011890 if (child != NULL) {
11891 /*
11892 * Attribute uses/declarations.
11893 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011894 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11895 (xmlSchemaItemListPtr *) &(type->attrUses),
11896 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11897 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011898 /*
11899 * Attribute wildcard.
11900 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011901 if (IS_SCHEMA(child, "anyAttribute")) {
11902 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011903 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11904 child = child->next;
11905 }
11906 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011907 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011908 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11909 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011910 xmlSchemaPContentErr(ctxt,
11911 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011912 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011913 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011914 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011915 } else {
11916 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011917 xmlSchemaPContentErr(ctxt,
11918 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011919 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011920 "(annotation?, ((attribute | attributeGroup)*, "
11921 "anyAttribute?))");
11922 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011924 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011925}
11926
11927/**
11928 * xmlSchemaParseSimpleContent:
11929 * @ctxt: a schema validation context
11930 * @schema: the schema being built
11931 * @node: a subtree containing XML Schema informations
11932 *
11933 * parse a XML schema SimpleContent definition
11934 * *WARNING* this interface is highly subject to change
11935 *
11936 * Returns the type definition or NULL in case of error
11937 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011938static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011939xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011940 xmlSchemaPtr schema, xmlNodePtr node,
11941 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011942{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011943 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011944 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011945 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011946
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011947 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11948 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011949 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011950 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011951 /* Not a component, don't create it. */
11952 type = ctxt->ctxtType;
11953 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11954 /*
11955 * Check for illegal attributes.
11956 */
11957 attr = node->properties;
11958 while (attr != NULL) {
11959 if (attr->ns == NULL) {
11960 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011963 }
11964 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011965 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011966 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011967 }
11968 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011970
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011971 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000011972
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011973 /*
11974 * And now for the children...
11975 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011976 child = node->children;
11977 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011978 /*
11979 * Add the annotation to the complex type ancestor.
11980 */
11981 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011982 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011983 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011984 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011985 if (child == NULL) {
11986 xmlSchemaPContentErr(ctxt,
11987 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011988 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000011989 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011990 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011991 if (child == NULL) {
11992 xmlSchemaPContentErr(ctxt,
11993 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011994 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000011995 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011996 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011997 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011998 xmlSchemaParseRestriction(ctxt, schema, child,
11999 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012000 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012001 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012002 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012003 xmlSchemaParseExtension(ctxt, schema, child,
12004 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012005 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012006 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012007 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012008 if (child != NULL) {
12009 xmlSchemaPContentErr(ctxt,
12010 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012011 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012012 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012013 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012014 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012015}
12016
12017/**
12018 * xmlSchemaParseComplexContent:
12019 * @ctxt: a schema validation context
12020 * @schema: the schema being built
12021 * @node: a subtree containing XML Schema informations
12022 *
12023 * parse a XML schema ComplexContent definition
12024 * *WARNING* this interface is highly subject to change
12025 *
12026 * Returns the type definition or NULL in case of error
12027 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012028static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012029xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012030 xmlSchemaPtr schema, xmlNodePtr node,
12031 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000012032{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012033 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012034 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012035 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000012036
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012037 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12038 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012039 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012040 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012041 /* Not a component, don't create it. */
12042 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012043 /*
12044 * Check for illegal attributes.
12045 */
12046 attr = node->properties;
12047 while (attr != NULL) {
12048 if (attr->ns == NULL) {
12049 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012050 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012051 {
12052 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012053 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012054 }
12055 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12056 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012057 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012058 }
12059 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012060 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012061
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012062 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012063
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012064 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012065 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012066 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012067 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012068 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12069 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012070 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012071 child = node->children;
12072 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012073 /*
12074 * Add the annotation to the complex type ancestor.
12075 */
12076 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012077 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012078 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012079 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012080 if (child == NULL) {
12081 xmlSchemaPContentErr(ctxt,
12082 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012083 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012084 NULL, "(annotation?, (restriction | extension))");
12085 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012086 if (child == NULL) {
12087 xmlSchemaPContentErr(ctxt,
12088 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012089 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012090 NULL, "(annotation?, (restriction | extension))");
12091 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012092 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012093 xmlSchemaParseRestriction(ctxt, schema, child,
12094 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012095 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012096 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012097 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012098 xmlSchemaParseExtension(ctxt, schema, child,
12099 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012100 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012101 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012102 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012103 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012104 xmlSchemaPContentErr(ctxt,
12105 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012106 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012107 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012108 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012109 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012110}
12111
12112/**
12113 * xmlSchemaParseComplexType:
12114 * @ctxt: a schema validation context
12115 * @schema: the schema being built
12116 * @node: a subtree containing XML Schema informations
12117 *
12118 * parse a XML schema Complex Type definition
12119 * *WARNING* this interface is highly subject to change
12120 *
12121 * Returns the type definition or NULL in case of error
12122 */
12123static xmlSchemaTypePtr
12124xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012125 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012126{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012127 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012128 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012129 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012130 xmlAttrPtr attr;
12131 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012132#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012133 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012134#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012135 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012136
Daniel Veillard4255d502002-04-16 15:50:10 +000012137
12138 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12139 return (NULL);
12140
Daniel Veillard01fa6152004-06-29 17:04:39 +000012141 ctxtType = ctxt->ctxtType;
12142
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012143 if (topLevel) {
12144 attr = xmlSchemaGetPropNode(node, "name");
12145 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 xmlSchemaPMissingAttrErr(ctxt,
12147 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012148 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012149 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012150 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12151 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012152 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012154
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012155 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012156 /*
12157 * Parse as local complex type definition.
12158 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012159#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012160 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012161 type = xmlSchemaAddType(ctxt, schema,
12162 XML_SCHEMA_TYPE_COMPLEX,
12163 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012164 ctxt->targetNamespace, node, 0);
12165#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012166 type = xmlSchemaAddType(ctxt, schema,
12167 XML_SCHEMA_TYPE_COMPLEX,
12168 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012169#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012170 if (type == NULL)
12171 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012172 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012173 type->node = node;
12174 type->type = XML_SCHEMA_TYPE_COMPLEX;
12175 /*
12176 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012177 */
12178 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012179 /*
12180 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012181 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012182 type = xmlSchemaAddType(ctxt, schema,
12183 XML_SCHEMA_TYPE_COMPLEX,
12184 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012185 if (type == NULL)
12186 return (NULL);
12187 type->node = node;
12188 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012190 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012191 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012192 /*
12193 * Handle attributes.
12194 */
12195 attr = node->properties;
12196 while (attr != NULL) {
12197 if (attr->ns == NULL) {
12198 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12199 /*
12200 * Attribute "id".
12201 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012202 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012203 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12204 /*
12205 * Attribute "mixed".
12206 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012207 if (xmlSchemaPGetBoolNodeValue(ctxt,
12208 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12210 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012211 /*
12212 * Attributes of global complex type definitions.
12213 */
12214 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12215 /* Pass. */
12216 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12217 /*
12218 * Attribute "abstract".
12219 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012220 if (xmlSchemaPGetBoolNodeValue(ctxt,
12221 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012222 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12223 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12224 /*
12225 * Attribute "final".
12226 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012227 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012228 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012229 if (xmlSchemaPValAttrBlockFinal(attrValue,
12230 &(type->flags),
12231 -1,
12232 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12233 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12234 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012235 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012237 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012238 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012239 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012240 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012241 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012242 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012243 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12244 /*
12245 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012246 */
12247 attrValue = xmlSchemaGetNodeContent(ctxt,
12248 (xmlNodePtr) attr);
12249 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012250 -1,
12251 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012253 -1, -1, -1) != 0) {
12254 xmlSchemaPSimpleTypeErr(ctxt,
12255 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012256 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012257 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012258 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012259 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012260 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012261 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012262 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012263 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012264 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012265 } else {
12266 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012268 }
12269 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012270 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012271 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012272 }
12273 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012274 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012275 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012276 /*
12277 * Apply default "block" values.
12278 */
12279 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12280 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12281 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12282 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12283 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 if (! final) {
12285 /*
12286 * Apply default "block" values.
12287 */
12288 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12289 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12290 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12291 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12292 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012293 /*
12294 * And now for the children...
12295 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012296 child = node->children;
12297 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012298 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012300 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012302 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012303 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012304 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012306 * Specifying mixed='true' when the <simpleContent>
12307 * alternative is chosen has no effect
12308 */
William M. Bracke7091952004-05-11 15:09:58 +000012309 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12310 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012311 xmlSchemaParseSimpleContent(ctxt, schema, child,
12312 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012313 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012314 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012315 /*
12316 * <complexType><complexContent>...
12317 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012318 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012319 xmlSchemaParseComplexContent(ctxt, schema, child,
12320 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012321 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012322 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012323 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012324 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12325 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012326 * SPEC
12327 * "...the third alternative (neither <simpleContent> nor
12328 * <complexContent>) is chosen. This case is understood as shorthand
Jan Pokorný761c9e92013-11-29 23:26:27 +010012329 * for complex content restricting the `ur-type definition`, and the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012330 * details of the mappings should be modified as necessary.
12331 */
12332 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12333 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012334 /*
12335 * Parse model groups.
12336 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012337 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012338 type->subtypes = (xmlSchemaTypePtr)
12339 xmlSchemaParseModelGroup(ctxt, schema, child,
12340 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012341 child = child->next;
12342 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012343 type->subtypes = (xmlSchemaTypePtr)
12344 xmlSchemaParseModelGroup(ctxt, schema, child,
12345 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012346 child = child->next;
12347 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012348 type->subtypes = (xmlSchemaTypePtr)
12349 xmlSchemaParseModelGroup(ctxt, schema, child,
12350 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012351 child = child->next;
12352 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012353 type->subtypes = (xmlSchemaTypePtr)
12354 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012355 /*
12356 * Note that the reference will be resolved in
12357 * xmlSchemaResolveTypeReferences();
12358 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012359 child = child->next;
12360 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012361 /*
12362 * Parse attribute decls/refs.
12363 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012364 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12365 (xmlSchemaItemListPtr *) &(type->attrUses),
12366 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12367 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012368 /*
12369 * Parse attribute wildcard.
12370 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012371 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012372 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12373 child = child->next;
12374 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012375 }
12376 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012377 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012379 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012380 NULL, "(annotation?, (simpleContent | complexContent | "
12381 "((group | all | choice | sequence)?, ((attribute | "
12382 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012383 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012384 /*
12385 * REDEFINE: SPEC src-redefine (5)
12386 */
12387 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12388 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012389 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012390 "<complexType> must have a <restriction> or <extension> "
12391 "grand-child", NULL);
12392 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012393 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012394 return (type);
12395}
12396
Daniel Veillard4255d502002-04-16 15:50:10 +000012397/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012398 * *
12399 * Validating using Schemas *
12400 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012401 ************************************************************************/
12402
12403/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012404 * *
12405 * Reading/Writing Schemas *
12406 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012407 ************************************************************************/
12408
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012409#if 0 /* Will be enabled if it is clear what options are needed. */
12410/**
12411 * xmlSchemaParserCtxtSetOptions:
12412 * @ctxt: a schema parser context
12413 * @options: a combination of xmlSchemaParserOption
12414 *
12415 * Sets the options to be used during the parse.
12416 *
12417 * Returns 0 in case of success, -1 in case of an
12418 * API error.
12419 */
12420static int
12421xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12422 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012423
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012424{
12425 int i;
12426
12427 if (ctxt == NULL)
12428 return (-1);
12429 /*
12430 * WARNING: Change the start value if adding to the
12431 * xmlSchemaParseOption.
12432 */
12433 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12434 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012435 return (-1);
12436 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012437 }
12438 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012439 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012440}
12441
12442/**
12443 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012444 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012445 *
12446 * Returns the option combination of the parser context.
12447 */
12448static int
12449xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012450
12451{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012452 if (ctxt == NULL)
12453 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012454 else
12455 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012456}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012457#endif
12458
Daniel Veillard4255d502002-04-16 15:50:10 +000012459/**
12460 * xmlSchemaNewParserCtxt:
12461 * @URL: the location of the schema
12462 *
12463 * Create an XML Schemas parse context for that file/resource expected
12464 * to contain an XML Schemas file.
12465 *
12466 * Returns the parser context or NULL in case of error
12467 */
12468xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012469xmlSchemaNewParserCtxt(const char *URL)
12470{
Daniel Veillard4255d502002-04-16 15:50:10 +000012471 xmlSchemaParserCtxtPtr ret;
12472
12473 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012474 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012475
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012476 ret = xmlSchemaParserCtxtCreate();
12477 if (ret == NULL)
12478 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012479 ret->dict = xmlDictCreate();
12480 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012481 return (ret);
12482}
12483
12484/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012485 * xmlSchemaNewMemParserCtxt:
12486 * @buffer: a pointer to a char array containing the schemas
12487 * @size: the size of the array
12488 *
12489 * Create an XML Schemas parse context for that memory buffer expected
12490 * to contain an XML Schemas file.
12491 *
12492 * Returns the parser context or NULL in case of error
12493 */
12494xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012495xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12496{
Daniel Veillard6045c902002-10-09 21:13:59 +000012497 xmlSchemaParserCtxtPtr ret;
12498
12499 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012500 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012501 ret = xmlSchemaParserCtxtCreate();
12502 if (ret == NULL)
12503 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012504 ret->buffer = buffer;
12505 ret->size = size;
Daniel Veillarddee23482008-04-11 12:58:43 +000012506 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012507 return (ret);
12508}
12509
12510/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012511 * xmlSchemaNewDocParserCtxt:
12512 * @doc: a preparsed document tree
12513 *
12514 * Create an XML Schemas parse context for that document.
12515 * NB. The document may be modified during the parsing process.
12516 *
12517 * Returns the parser context or NULL in case of error
12518 */
12519xmlSchemaParserCtxtPtr
12520xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12521{
12522 xmlSchemaParserCtxtPtr ret;
12523
12524 if (doc == NULL)
12525 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012526 ret = xmlSchemaParserCtxtCreate();
12527 if (ret == NULL)
12528 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012529 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012530 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012531 /* The application has responsibility for the document */
12532 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012533
12534 return (ret);
12535}
12536
12537/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012538 * xmlSchemaFreeParserCtxt:
12539 * @ctxt: the schema parser context
12540 *
12541 * Free the resources associated to the schema parser context
12542 */
12543void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012544xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12545{
Daniel Veillard4255d502002-04-16 15:50:10 +000012546 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012547 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012548 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillarddee23482008-04-11 12:58:43 +000012549 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012550 if (ctxt->vctxt != NULL) {
12551 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12552 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012553 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12554 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12555 ctxt->constructor = NULL;
12556 ctxt->ownsConstructor = 0;
12557 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012558 if (ctxt->attrProhibs != NULL)
12559 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012560 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012561 xmlFree(ctxt);
12562}
12563
12564/************************************************************************
12565 * *
12566 * Building the content models *
12567 * *
12568 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012569
Daniel Veillard4013e832009-08-26 17:24:31 +020012570/**
12571 * xmlSchemaBuildContentModelForSubstGroup:
12572 *
12573 * Returns 1 if nillable, 0 otherwise
12574 */
12575static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012576xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012577 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012578{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012579 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012580 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012581 xmlSchemaSubstGroupPtr substGroup;
12582 int i;
Daniel Veillard4013e832009-08-26 17:24:31 +020012583 int ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012584
12585 elemDecl = (xmlSchemaElementPtr) particle->children;
12586 /*
12587 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012588 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012589 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012590 if (end == NULL)
12591 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012592 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012593 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012594 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012595 XML_SCHEMAP_INTERNAL,
12596 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12597 "declaration is marked having a subst. group but none "
12598 "available.\n", elemDecl->name, NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020012599 return(0);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012600 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012601 if (counter >= 0) {
12602 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012603 * NOTE that we put the declaration in, even if it's abstract.
12604 * However, an error will be raised during *validation* if an element
12605 * information item shall be validated against an abstract element
12606 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012607 */
12608 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12609 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12610 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12611 /*
12612 * Add subst. group members.
12613 */
12614 for (i = 0; i < substGroup->members->nbItems; i++) {
12615 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12616 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12617 member->name, member->targetNamespace, member);
12618 }
12619 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012620 /*
12621 * NOTE that we put the declaration in, even if it's abstract,
12622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012623 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012624 xmlAutomataNewTransition2(pctxt->am,
12625 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012626 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12627 /*
12628 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012630 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012631 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012632 /*
12633 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12634 * was incorrectly used instead of xmlAutomataNewTransition2()
12635 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12636 * section in xmlSchemaBuildAContentModel() ).
Daniel Veillarddee23482008-04-11 12:58:43 +000012637 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012638 * intended for the above "counter" section originally. I.e.,
12639 * check xs:all with subst-groups.
12640 *
12641 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12642 * member->name, member->targetNamespace,
12643 * 1, 1, member);
12644 */
12645 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012646 member->name, member->targetNamespace, member);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012647 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012648 }
12649 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012650 xmlAutomataStatePtr hop;
12651 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12652 UNBOUNDED : particle->maxOccurs - 1;
12653 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12654
12655 counter =
12656 xmlAutomataNewCounter(pctxt->am, minOccurs,
12657 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012659
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012661 xmlAutomataNewTransition2(pctxt->am,
12662 start, NULL,
12663 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012664 hop);
12665 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012666 * Add subst. group members.
12667 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012668 for (i = 0; i < substGroup->members->nbItems; i++) {
12669 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12670 xmlAutomataNewEpsilon(pctxt->am,
12671 xmlAutomataNewTransition2(pctxt->am,
12672 start, NULL,
12673 member->name, member->targetNamespace, member),
12674 hop);
12675 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012676 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12677 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12678 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012679 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012680 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012681 ret = 1;
12682 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012683 pctxt->state = end;
Daniel Veillard4013e832009-08-26 17:24:31 +020012684 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012685}
12686
Daniel Veillard4013e832009-08-26 17:24:31 +020012687/**
12688 * xmlSchemaBuildContentModelForElement:
12689 *
12690 * Returns 1 if nillable, 0 otherwise
12691 */
12692static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012693xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12694 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012695{
Daniel Veillard4013e832009-08-26 17:24:31 +020012696 int ret = 0;
12697
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012698 if (((xmlSchemaElementPtr) particle->children)->flags &
12699 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012700 /*
12701 * Substitution groups.
12702 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012703 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012704 } else {
12705 xmlSchemaElementPtr elemDecl;
12706 xmlAutomataStatePtr start;
12707
12708 elemDecl = (xmlSchemaElementPtr) particle->children;
12709
12710 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillard4013e832009-08-26 17:24:31 +020012711 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012712 if (particle->maxOccurs == 1) {
12713 start = ctxt->state;
12714 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012715 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12716 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12717 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012718 /* Special case. */
Daniel Veillarddee23482008-04-11 12:58:43 +000012719 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012720 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012721 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012722 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
Daniel Veillarddee23482008-04-11 12:58:43 +000012723 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012724 } else {
12725 int counter;
12726 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12727 UNBOUNDED : particle->maxOccurs - 1;
12728 int minOccurs = particle->minOccurs < 1 ?
12729 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012730
12731 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012732 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12733 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12734 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12735 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12736 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12737 NULL, counter);
12738 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012739 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012740 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
Daniel Veillard4013e832009-08-26 17:24:31 +020012741 ret = 1;
12742 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012743 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012744 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012745}
12746
Daniel Veillard4255d502002-04-16 15:50:10 +000012747/**
12748 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012749 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012750 * @particle: the particle component
12751 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012752 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012753 * Create the automaton for the {content type} of a complex type.
12754 *
Daniel Veillard4013e832009-08-26 17:24:31 +020012755 * Returns 1 if the content is nillable, 0 otherwise
Daniel Veillard4255d502002-04-16 15:50:10 +000012756 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012757static int
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012758xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012759 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012760{
Daniel Veillard4013e832009-08-26 17:24:31 +020012761 int ret = 0, tmp2;
12762
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012763 if (particle == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012764 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Daniel Veillard4013e832009-08-26 17:24:31 +020012765 return(1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012766 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012767 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012768 /*
12769 * Just return in this case. A missing "term" of the particle
12770 * might arise due to an invalid "term" component.
12771 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012772 return(1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012773 }
12774
12775 switch (particle->children->type) {
12776 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012777 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012778 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012779 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012780
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012781 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012782
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012783 start = pctxt->state;
12784 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012785
12786 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012787 if (wild->any == 1) {
12788 /*
12789 * We need to add both transitions:
12790 *
12791 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012792 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012793 pctxt->state =
12794 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012795 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012796 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012797 /*
12798 * 2. the {"*"} for elements in no namespace.
12799 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012800 pctxt->state =
12801 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012802 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012803 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012804
12805 } else if (wild->nsSet != NULL) {
12806 ns = wild->nsSet;
12807 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012808 pctxt->state = start;
12809 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12810 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12811 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012812 ns = ns->next;
12813 } while (ns != NULL);
12814
12815 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012816 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12817 start, end, BAD_CAST "*", wild->negNsSet->value,
12818 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012819 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012820 } else {
12821 int counter;
12822 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012823 int maxOccurs =
Daniel Veillard4013e832009-08-26 17:24:31 +020012824 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12825 particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012826 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012827 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012828
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012829 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12830 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012831 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012832 pctxt->state =
12833 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012834 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012835 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12836 pctxt->state =
12837 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012838 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012839 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012840 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012841 ns = wild->nsSet;
12842 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012843 pctxt->state =
12844 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012845 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012846 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012847 ns = ns->next;
12848 } while (ns != NULL);
12849
12850 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012851 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012852 start, hop, BAD_CAST "*", wild->negNsSet->value,
12853 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012854 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012855 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12856 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012857 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012858 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012859 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012860 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012862 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012863 break;
12864 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012865 case XML_SCHEMA_TYPE_ELEMENT:
Daniel Veillard4013e832009-08-26 17:24:31 +020012866 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012867 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012868 case XML_SCHEMA_TYPE_SEQUENCE:{
Daniel Veillard4013e832009-08-26 17:24:31 +020012869 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012870
Daniel Veillard4013e832009-08-26 17:24:31 +020012871 ret = 1;
12872 /*
12873 * If max and min occurances are default (1) then
12874 * simply iterate over the particles of the <sequence>.
12875 */
12876 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12877 sub = particle->children->children;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012878
Daniel Veillard4013e832009-08-26 17:24:31 +020012879 while (sub != NULL) {
12880 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12881 (xmlSchemaParticlePtr) sub);
12882 if (tmp2 != 1) ret = 0;
12883 sub = sub->next;
12884 }
12885 } else {
12886 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012887
Daniel Veillard4013e832009-08-26 17:24:31 +020012888 if (particle->maxOccurs >= UNBOUNDED) {
12889 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012890 xmlAutomataStatePtr tmp;
12891 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012892
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012893 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012894 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012895 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012896
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012897 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012898 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillard4255d502002-04-16 15:50:10 +000012899
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012900 sub = particle->children->children;
12901 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012902 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12903 (xmlSchemaParticlePtr) sub);
12904 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012905 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012906 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012907 tmp = pctxt->state;
Daniel Veillard4013e832009-08-26 17:24:31 +020012908 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12909 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012910 pctxt->state =
Daniel Veillard4013e832009-08-26 17:24:31 +020012911 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12912 NULL, counter);
12913 if (ret == 1)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012914 xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012915 oldstate, pctxt->state);
12916
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012917 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020012918 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12919 oldstate, NULL);
12920 oldstate = pctxt->state;
12921
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012922 sub = particle->children->children;
12923 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012924 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12925 (xmlSchemaParticlePtr) sub);
12926 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012927 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012928 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012929 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12930 oldstate);
12931 /*
12932 * epsilon needed to block previous trans from
12933 * being allowed to enter back from another
12934 * construct
12935 */
12936 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12937 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012938 if (particle->minOccurs == 0) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012939 xmlAutomataNewEpsilon(pctxt->am,
12940 oldstate, pctxt->state);
12941 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012942 }
12943 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012944 } else if ((particle->maxOccurs > 1)
12945 || (particle->minOccurs > 1)) {
12946 xmlAutomataStatePtr tmp;
12947 int counter;
Daniel Veillardb509f152002-04-17 16:28:10 +000012948
Daniel Veillard4013e832009-08-26 17:24:31 +020012949 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12950 oldstate, NULL);
12951 oldstate = pctxt->state;
Daniel Veillard7646b182002-04-20 06:41:40 +000012952
Daniel Veillard4013e832009-08-26 17:24:31 +020012953 counter = xmlAutomataNewCounter(pctxt->am,
12954 particle->minOccurs - 1,
12955 particle->maxOccurs - 1);
12956
12957 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012958 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012959 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12960 (xmlSchemaParticlePtr) sub);
12961 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012962 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012963 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012964 tmp = pctxt->state;
12965 xmlAutomataNewCountedTrans(pctxt->am,
12966 tmp, oldstate, counter);
12967 pctxt->state =
12968 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12969 counter);
12970 if ((particle->minOccurs == 0) || (ret == 1)) {
12971 xmlAutomataNewEpsilon(pctxt->am,
12972 oldstate, pctxt->state);
12973 ret = 1;
12974 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012975 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020012976 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012977 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012978 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12979 (xmlSchemaParticlePtr) sub);
12980 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012981 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012982 }
Daniel Veillardc70d1852012-08-23 23:28:04 +080012983
12984 /*
12985 * epsilon needed to block previous trans from
12986 * being allowed to enter back from another
12987 * construct
12988 */
12989 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12990 pctxt->state, NULL);
12991
Daniel Veillard4013e832009-08-26 17:24:31 +020012992 if (particle->minOccurs == 0) {
12993 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12994 pctxt->state);
12995 ret = 1;
12996 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012997 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012998 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012999 break;
13000 }
13001 case XML_SCHEMA_TYPE_CHOICE:{
13002 xmlSchemaTreeItemPtr sub;
13003 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013004
Daniel Veillard4013e832009-08-26 17:24:31 +020013005 ret = 0;
13006 start = pctxt->state;
13007 end = xmlAutomataNewState(pctxt->am);
13008
13009 /*
13010 * iterate over the subtypes and remerge the end with an
13011 * epsilon transition
13012 */
13013 if (particle->maxOccurs == 1) {
13014 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013015 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020013016 pctxt->state = start;
13017 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13018 (xmlSchemaParticlePtr) sub);
13019 if (tmp2 == 1) ret = 1;
13020 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13021 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013022 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013023 } else {
13024 int counter;
13025 xmlAutomataStatePtr hop, base;
13026 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13027 UNBOUNDED : particle->maxOccurs - 1;
13028 int minOccurs =
13029 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13030
13031 /*
13032 * use a counter to keep track of the number of transtions
13033 * which went through the choice.
13034 */
13035 counter =
13036 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13037 hop = xmlAutomataNewState(pctxt->am);
13038 base = xmlAutomataNewState(pctxt->am);
13039
13040 sub = particle->children->children;
13041 while (sub != NULL) {
13042 pctxt->state = base;
13043 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13044 (xmlSchemaParticlePtr) sub);
13045 if (tmp2 == 1) ret = 1;
13046 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13047 sub = sub->next;
Daniel Veillardbd56c442009-08-12 15:39:23 +020013048 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013049 xmlAutomataNewEpsilon(pctxt->am, start, base);
13050 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13051 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13052 if (ret == 1)
13053 xmlAutomataNewEpsilon(pctxt->am, base, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013054 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013055 if (particle->minOccurs == 0) {
13056 xmlAutomataNewEpsilon(pctxt->am, start, end);
13057 ret = 1;
13058 }
13059 pctxt->state = end;
13060 break;
13061 }
13062 case XML_SCHEMA_TYPE_ALL:{
13063 xmlAutomataStatePtr start, tmp;
13064 xmlSchemaParticlePtr sub;
13065 xmlSchemaElementPtr elemDecl;
13066
13067 ret = 1;
13068
13069 sub = (xmlSchemaParticlePtr) particle->children->children;
13070 if (sub == NULL)
13071 break;
13072
13073 ret = 0;
13074
13075 start = pctxt->state;
13076 tmp = xmlAutomataNewState(pctxt->am);
13077 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13078 pctxt->state = tmp;
13079 while (sub != NULL) {
13080 pctxt->state = tmp;
13081
13082 elemDecl = (xmlSchemaElementPtr) sub->children;
13083 if (elemDecl == NULL) {
13084 PERROR_INT("xmlSchemaBuildAContentModel",
13085 "<element> particle has no term");
13086 return(ret);
13087 };
13088 /*
13089 * NOTE: The {max occurs} of all the particles in the
13090 * {particles} of the group must be 0 or 1; this is
13091 * already ensured during the parse of the content of
13092 * <all>.
13093 */
13094 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13095 int counter;
13096
13097 /*
13098 * This is an abstract group, we need to share
13099 * the same counter for all the element transitions
13100 * derived from the group
13101 */
13102 counter = xmlAutomataNewCounter(pctxt->am,
13103 sub->minOccurs, sub->maxOccurs);
13104 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13105 sub, counter, pctxt->state);
13106 } else {
13107 if ((sub->minOccurs == 1) &&
13108 (sub->maxOccurs == 1)) {
13109 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13110 pctxt->state,
13111 elemDecl->name,
13112 elemDecl->targetNamespace,
13113 1, 1, elemDecl);
13114 } else if ((sub->minOccurs == 0) &&
13115 (sub->maxOccurs == 1)) {
13116
13117 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13118 pctxt->state,
13119 elemDecl->name,
13120 elemDecl->targetNamespace,
13121 0,
13122 1,
13123 elemDecl);
13124 }
13125 }
13126 sub = (xmlSchemaParticlePtr) sub->next;
13127 }
13128 pctxt->state =
13129 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13130 if (particle->minOccurs == 0) {
13131 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13132 ret = 1;
13133 }
13134 break;
13135 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013136 case XML_SCHEMA_TYPE_GROUP:
13137 /*
13138 * If we hit a model group definition, then this means that
13139 * it was empty, thus was not substituted for the containing
13140 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013141 * TODO: But the group should be substituted and not occur at
13142 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013143 */
Daniel Veillard4013e832009-08-26 17:24:31 +020013144 ret = 1;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013145 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013146 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013147 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13148 "xmlSchemaBuildAContentModel",
13149 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013150 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020013151 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013152 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013153 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013154}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013155
Daniel Veillard4255d502002-04-16 15:50:10 +000013156/**
13157 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000013158 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013160 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013161 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013162 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013163 */
13164static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013165xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013166 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013167{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013168 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13169 (type->contModel != NULL) ||
13170 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13171 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013172 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013173
13174#ifdef DEBUG_CONTENT
13175 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013176 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013177#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013178 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013179 ctxt->am = xmlNewAutomata();
13180 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013181 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013182 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013183 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013184 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013185 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013186 /*
13187 * Build the automaton.
13188 */
13189 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013190 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013191 type->contModel = xmlAutomataCompile(ctxt->am);
13192 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013193 xmlSchemaPCustomErr(ctxt,
13194 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013195 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013196 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013197 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013198 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013199 XML_SCHEMAP_NOT_DETERMINISTIC,
13200 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013201 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013202 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013203 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013204#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013205 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013206 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013207 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013208#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013209 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013210 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013211 xmlFreeAutomata(ctxt->am);
13212 ctxt->am = NULL;
13213}
13214
13215/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013216 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013217 * @elem: the schema element context
13218 * @ctxt: the schema parser context
13219 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013220 * Resolves the references of an element declaration
13221 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013223 */
13224static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013225xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13226 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013227{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013228 if ((ctxt == NULL) || (elemDecl == NULL) ||
13229 ((elemDecl != NULL) &&
13230 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013231 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013232 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013233
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013234 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013235 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013236
Jan Pokorný761c9e92013-11-29 23:26:27 +010013237 /* (type definition) ... otherwise the type definition `resolved`
13238 * to by the `actual value` of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013239 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013240 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013241 elemDecl->namedTypeNs);
13242 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013243 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013244 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013245 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013246 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247 XML_SCHEMA_TYPE_BASIC, "type definition");
13248 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013249 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013250 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013251 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013252 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013253
Daniel Veillardc0826a72004-08-10 14:17:33 +000013254 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013255 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013256 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013257 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013258 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13259 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013260 if (substHead == NULL) {
13261 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013262 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013263 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013264 "substitutionGroup", elemDecl->substGroup,
13265 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013266 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013267 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013268 /*
13269 * Set the "substitution group affiliation".
13270 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013272 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013273 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013274 * The type definitions is set to:
13275 * SPEC "...the {type definition} of the element
Jan Pokorný761c9e92013-11-29 23:26:27 +010013276 * declaration `resolved` to by the `actual value`
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013277 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013279 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013280 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013281 }
13282 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013283 /*
13284 * SPEC "The definition of anyType serves as the default type definition
13285 * for element declarations whose XML representation does not specify one."
13286 */
13287 if ((elemDecl->subtypes == NULL) &&
13288 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013289 (elemDecl->substGroup == NULL))
13290 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013291}
13292
13293/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013294 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013295 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013296 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013297 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013298 * Checks and builds the "member type definitions" property of the union
13299 * simple type. This handles part (1), part (2) is done in
13300 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13301 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013302 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013303 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013304static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013305xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13306 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013307{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013308
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013309 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013310 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013311
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013312 /*
13313 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Jan Pokorný761c9e92013-11-29 23:26:27 +010013314 * define the explicit members as the type definitions `resolved`
13315 * to by the items in the `actual value` of the memberTypes [attribute],
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013316 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013317 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013318 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013319 /*
13320 * Resolve references.
13321 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013322 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013323 lastLink = NULL;
13324 while (link != NULL) {
13325 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013327 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13328 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13329
13330 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013331 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013332 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013333 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013334 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13335 /*
13336 * Remove the member type link.
13337 */
13338 if (lastLink == NULL)
13339 type->memberTypes = link->next;
13340 else
13341 lastLink->next = link->next;
13342 newLink = link;
13343 link = link->next;
13344 xmlFree(newLink);
13345 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013346 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013347 lastLink = link;
13348 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013349 }
13350 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013351 /*
13352 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013353 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013354 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013355 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013356 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13357 if (link == NULL) {
13358 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13359 return (-1);
13360 }
13361 link->type = memberType;
13362 link->next = NULL;
13363 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013364 type->memberTypes = link;
13365 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013366 lastLink->next = link;
13367 lastLink = link;
13368 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013369 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013370 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013371}
13372
Daniel Veillard4255d502002-04-16 15:50:10 +000013373/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013374 * xmlSchemaIsDerivedFromBuiltInType:
13375 * @ctxt: the schema parser context
13376 * @type: the type definition
13377 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013378 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013379 *
13380 * Returns 1 if the type has the given value type, or
13381 * is derived from such a type.
13382 */
William M. Brack803812b2004-06-03 02:11:24 +000013383static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013385{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013386 if (type == NULL)
13387 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013388 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013389 return (0);
13390 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13391 if (type->builtInType == valType)
13392 return(1);
13393 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13394 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13395 return (0);
13396 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013397 }
13398 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013399}
13400
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013401#if 0
13402/**
13403 * xmlSchemaIsDerivedFromBuiltInType:
13404 * @ctxt: the schema parser context
13405 * @type: the type definition
13406 * @valType: the value type
13407 *
13408 *
13409 * Returns 1 if the type has the given value type, or
13410 * is derived from such a type.
13411 */
13412static int
13413xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13414{
13415 if (type == NULL)
13416 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013417 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 return (0);
13419 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13420 if (type->builtInType == valType)
13421 return(1);
13422 return (0);
13423 } else
13424 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13425
13426 return (0);
13427}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428
13429static xmlSchemaTypePtr
13430xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13431{
13432 if (type == NULL)
13433 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013434 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013435 return (NULL);
13436 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013437 return(type);
13438 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013439}
Daniel Veillard15724252008-08-30 15:01:04 +000013440#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013441
Daniel Veillard3646d642004-06-02 19:19:14 +000013442/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013443 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 * @type: the simpleType definition
13445 *
13446 * Returns the primitive type of the given type or
13447 * NULL in case of error.
13448 */
13449static xmlSchemaTypePtr
13450xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13451{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013452
Daniel Veillard01fa6152004-06-29 17:04:39 +000013453 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013454 /*
13455 * Note that anySimpleType is actually not a primitive type
13456 * but we need that here.
13457 */
13458 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13459 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 return (type);
13461 type = type->baseType;
13462 }
13463
13464 return (NULL);
13465}
13466
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013467#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013468/**
13469 * xmlSchemaGetBuiltInTypeAncestor:
13470 * @type: the simpleType definition
13471 *
13472 * Returns the primitive type of the given type or
13473 * NULL in case of error.
13474 */
13475static xmlSchemaTypePtr
13476xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13477{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013478 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013479 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013480 while (type != NULL) {
13481 if (type->type == XML_SCHEMA_TYPE_BASIC)
13482 return (type);
13483 type = type->baseType;
13484 }
13485
13486 return (NULL);
13487}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013488#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013489
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013491 * xmlSchemaCloneWildcardNsConstraints:
13492 * @ctxt: the schema parser context
13493 * @dest: the destination wildcard
13494 * @source: the source wildcard
13495 *
13496 * Clones the namespace constraints of source
13497 * and assignes them to dest.
13498 * Returns -1 on internal error, 0 otherwise.
13499 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013500static int
13501xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013502 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013504{
13505 xmlSchemaWildcardNsPtr cur, tmp, last;
13506
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013507 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013509 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013510 cur = source->nsSet;
13511 last = NULL;
13512 while (cur != NULL) {
13513 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13514 if (tmp == NULL)
13515 return(-1);
13516 tmp->value = cur->value;
13517 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013518 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013520 last->next = tmp;
13521 last = tmp;
13522 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013524 if (dest->negNsSet != NULL)
13525 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013526 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013527 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13528 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013529 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013530 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013531 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013532 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013533 return(0);
13534}
13535
Daniel Veillard50355f02004-06-08 17:52:16 +000013536/**
13537 * xmlSchemaUnionWildcards:
13538 * @ctxt: the schema parser context
13539 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013541 *
13542 * Unions the namespace constraints of the given wildcards.
13543 * @completeWild will hold the resulting union.
13544 * Returns a positive error code on failure, -1 in case of an
13545 * internal error, 0 otherwise.
13546 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013547static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013548xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013549 xmlSchemaWildcardPtr completeWild,
13550 xmlSchemaWildcardPtr curWild)
13551{
13552 xmlSchemaWildcardNsPtr cur, curB, tmp;
13553
13554 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013555 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013556 * value.
13557 */
13558 if ((completeWild->any == curWild->any) &&
13559 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13560 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561
Daniel Veillard3646d642004-06-02 19:19:14 +000013562 if ((completeWild->negNsSet == NULL) ||
13563 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564
Daniel Veillard3646d642004-06-02 19:19:14 +000013565 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013566 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567
13568 /*
13569 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013570 */
13571 cur = completeWild->nsSet;
13572 while (cur != NULL) {
13573 found = 0;
13574 curB = curWild->nsSet;
13575 while (curB != NULL) {
13576 if (cur->value == curB->value) {
13577 found = 1;
13578 break;
13579 }
13580 curB = curB->next;
13581 }
13582 if (!found)
13583 break;
13584 cur = cur->next;
13585 }
13586 if (found)
13587 return(0);
13588 } else
13589 return(0);
13590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 /*
13593 * 2 If either O1 or O2 is any, then any must be the value
13594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013595 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013596 if (completeWild->any == 0) {
13597 completeWild->any = 1;
13598 if (completeWild->nsSet != NULL) {
13599 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13600 completeWild->nsSet = NULL;
13601 }
13602 if (completeWild->negNsSet != NULL) {
13603 xmlFree(completeWild->negNsSet);
13604 completeWild->negNsSet = NULL;
13605 }
13606 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013607 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013608 }
13609 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013610 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013611 * then the union of those sets must be the value.
13612 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013614 int found;
13615 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013616
Daniel Veillard3646d642004-06-02 19:19:14 +000013617 cur = curWild->nsSet;
13618 start = completeWild->nsSet;
13619 while (cur != NULL) {
13620 found = 0;
13621 curB = start;
13622 while (curB != NULL) {
13623 if (cur->value == curB->value) {
13624 found = 1;
13625 break;
13626 }
13627 curB = curB->next;
13628 }
13629 if (!found) {
13630 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013632 return (-1);
13633 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013634 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013635 completeWild->nsSet = tmp;
13636 }
13637 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 }
13639
Daniel Veillard3646d642004-06-02 19:19:14 +000013640 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013641 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013642 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643 * 4 If the two are negations of different values (namespace names
Jan Pokorný761c9e92013-11-29 23:26:27 +010013644 * or `absent`), then a pair of not and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013647 (curWild->negNsSet != NULL) &&
13648 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13649 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013650
13651 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013652 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013653 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013654 * 5.
13655 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013656 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013657 (completeWild->negNsSet->value != NULL) &&
13658 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013659 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013660 (curWild->negNsSet->value != NULL) &&
13661 (completeWild->nsSet != NULL))) {
13662
13663 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013664
Daniel Veillard3646d642004-06-02 19:19:14 +000013665 if (completeWild->nsSet != NULL) {
13666 cur = completeWild->nsSet;
13667 curB = curWild->negNsSet;
13668 } else {
13669 cur = curWild->nsSet;
13670 curB = completeWild->negNsSet;
13671 }
13672 nsFound = 0;
13673 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013675 absentFound = 1;
13676 else if (cur->value == curB->value)
13677 nsFound = 1;
13678 if (nsFound && absentFound)
13679 break;
13680 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013681 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013682
13683 if (nsFound && absentFound) {
13684 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013685 * 5.1 If the set S includes both the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013686 * name and `absent`, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013688 completeWild->any = 1;
13689 if (completeWild->nsSet != NULL) {
13690 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13691 completeWild->nsSet = NULL;
13692 }
13693 if (completeWild->negNsSet != NULL) {
13694 xmlFree(completeWild->negNsSet);
13695 completeWild->negNsSet = NULL;
13696 }
13697 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 /*
13699 * 5.2 If the set S includes the negated namespace name
Jan Pokorný761c9e92013-11-29 23:26:27 +010013700 * but not `absent`, then a pair of not and `absent` must
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 * be the value.
13702 */
13703 if (completeWild->nsSet != NULL) {
13704 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13705 completeWild->nsSet = NULL;
13706 }
13707 if (completeWild->negNsSet == NULL) {
13708 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13709 if (completeWild->negNsSet == NULL)
13710 return (-1);
13711 }
13712 completeWild->negNsSet->value = NULL;
13713 } else if ((!nsFound) && absentFound) {
13714 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013715 * 5.3 If the set S includes `absent` but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013716 * namespace name, then the union is not expressible.
13717 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013719 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013720 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013721 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013722 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 /*
13725 * 5.4 If the set S does not include either the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013726 * name or `absent`, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013727 * and a namespace name must be the value.
13728 */
13729 if (completeWild->negNsSet == NULL) {
13730 if (completeWild->nsSet != NULL) {
13731 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732 completeWild->nsSet = NULL;
13733 }
13734 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735 if (completeWild->negNsSet == NULL)
13736 return (-1);
13737 completeWild->negNsSet->value = curWild->negNsSet->value;
13738 }
13739 }
13740 return (0);
13741 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013742 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013743 * 6.
13744 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013746 (completeWild->negNsSet->value == NULL) &&
13747 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013749 (curWild->negNsSet->value == NULL) &&
13750 (completeWild->nsSet != NULL))) {
13751
13752 if (completeWild->nsSet != NULL) {
13753 cur = completeWild->nsSet;
13754 } else {
13755 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013756 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013757 while (cur != NULL) {
13758 if (cur->value == NULL) {
13759 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013760 * 6.1 If the set S includes `absent`, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 * value.
13762 */
13763 completeWild->any = 1;
13764 if (completeWild->nsSet != NULL) {
13765 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13766 completeWild->nsSet = NULL;
13767 }
13768 if (completeWild->negNsSet != NULL) {
13769 xmlFree(completeWild->negNsSet);
13770 completeWild->negNsSet = NULL;
13771 }
13772 return (0);
13773 }
13774 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013775 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013776 if (completeWild->negNsSet == NULL) {
13777 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013778 * 6.2 If the set S does not include `absent`, then a pair of not
13779 * and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013780 */
13781 if (completeWild->nsSet != NULL) {
13782 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13783 completeWild->nsSet = NULL;
13784 }
13785 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13786 if (completeWild->negNsSet == NULL)
13787 return (-1);
13788 completeWild->negNsSet->value = NULL;
13789 }
13790 return (0);
13791 }
13792 return (0);
13793
13794}
13795
Daniel Veillard50355f02004-06-08 17:52:16 +000013796/**
13797 * xmlSchemaIntersectWildcards:
13798 * @ctxt: the schema parser context
13799 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013801 *
13802 * Intersects the namespace constraints of the given wildcards.
13803 * @completeWild will hold the resulting intersection.
13804 * Returns a positive error code on failure, -1 in case of an
13805 * internal error, 0 otherwise.
13806 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013807static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013808xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013809 xmlSchemaWildcardPtr completeWild,
13810 xmlSchemaWildcardPtr curWild)
13811{
William M. Brack803812b2004-06-03 02:11:24 +000013812 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013813
13814 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013815 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013816 * value.
13817 */
13818 if ((completeWild->any == curWild->any) &&
13819 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13820 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013821
Daniel Veillard3646d642004-06-02 19:19:14 +000013822 if ((completeWild->negNsSet == NULL) ||
13823 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824
Daniel Veillard3646d642004-06-02 19:19:14 +000013825 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013826 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013827
13828 /*
13829 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013830 */
13831 cur = completeWild->nsSet;
13832 while (cur != NULL) {
13833 found = 0;
13834 curB = curWild->nsSet;
13835 while (curB != NULL) {
13836 if (cur->value == curB->value) {
13837 found = 1;
13838 break;
13839 }
13840 curB = curB->next;
13841 }
13842 if (!found)
13843 break;
13844 cur = cur->next;
13845 }
13846 if (found)
13847 return(0);
13848 } else
13849 return(0);
13850 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013851 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013852 /*
13853 * 2 If either O1 or O2 is any, then the other must be the value.
13854 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013855 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013856 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013858 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013859 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013860 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013861 * 3 If either O1 or O2 is a pair of not and a value (a namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013862 * name or `absent`) and the other is a set of (namespace names or
13863 * `absent`), then that set, minus the negated value if it was in
13864 * the set, minus `absent` if it was in the set, must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013865 */
13866 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13867 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13868 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013869
Daniel Veillard3646d642004-06-02 19:19:14 +000013870 if (completeWild->nsSet == NULL) {
13871 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013872 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013873 return(-1);
13874 } else
13875 neg = curWild->negNsSet->value;
13876 /*
13877 * Remove absent and negated.
13878 */
13879 prev = NULL;
13880 cur = completeWild->nsSet;
13881 while (cur != NULL) {
13882 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013883 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013884 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013885 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013886 prev->next = cur->next;
13887 xmlFree(cur);
13888 break;
13889 }
13890 prev = cur;
13891 cur = cur->next;
13892 }
13893 if (neg != NULL) {
13894 prev = NULL;
13895 cur = completeWild->nsSet;
13896 while (cur != NULL) {
13897 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013898 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013899 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013901 prev->next = cur->next;
13902 xmlFree(cur);
13903 break;
13904 }
13905 prev = cur;
13906 cur = cur->next;
13907 }
13908 }
13909
13910 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013912 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013913 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013914 * then the intersection of those sets must be the value.
13915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013916 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013917 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013918
Daniel Veillard3646d642004-06-02 19:19:14 +000013919 cur = completeWild->nsSet;
13920 prev = NULL;
13921 while (cur != NULL) {
13922 found = 0;
13923 curB = curWild->nsSet;
13924 while (curB != NULL) {
13925 if (cur->value == curB->value) {
13926 found = 1;
13927 break;
13928 }
13929 curB = curB->next;
13930 }
13931 if (!found) {
13932 if (prev == NULL)
13933 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013935 prev->next = cur->next;
13936 tmp = cur->next;
13937 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013938 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013939 continue;
13940 }
13941 prev = cur;
13942 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013943 }
13944
Daniel Veillard3646d642004-06-02 19:19:14 +000013945 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946 }
13947 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000013948 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013949 */
13950 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013951 (curWild->negNsSet != NULL) &&
13952 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013953 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013954 (curWild->negNsSet->value != NULL)) {
13955
13956 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013957 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013958 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013959 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013960 }
13961 /*
13962 * 6 If the one is a negation of a namespace name and the other
Jan Pokorný761c9e92013-11-29 23:26:27 +010013963 * is a negation of `absent`, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000013964 * of a namespace name must be the value.
13965 */
13966 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13967 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013968 (completeWild->negNsSet->value == NULL)) {
13969 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013970 }
13971 return(0);
13972}
13973
Daniel Veillard50355f02004-06-08 17:52:16 +000013974/**
13975 * xmlSchemaIsWildcardNsConstraintSubset:
13976 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013977 * @sub: the first wildcard
13978 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013979 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013980 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13981 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013982 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013983 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000013984 */
13985static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013986xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13987 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013988{
Daniel Veillard50355f02004-06-08 17:52:16 +000013989 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013990 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000013991 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013992 if (super->any)
13993 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013994 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013995 * 2.1 sub must be a pair of not and a namespace name or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000013996 * 2.2 super must be a pair of not and the same value.
13997 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013998 if ((sub->negNsSet != NULL) &&
13999 (super->negNsSet != NULL) &&
Ryan Sleevi5cf1deb2012-02-29 10:56:32 +080014000 (sub->negNsSet->value == super->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014001 return (0);
14002 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014003 * 3.1 sub must be a set whose members are either namespace names or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000014004 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014005 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014006 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014007 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000014008 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014009 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014010 xmlSchemaWildcardNsPtr cur, curB;
14011 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014013 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000014014 while (cur != NULL) {
14015 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014016 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000014017 while (curB != NULL) {
14018 if (cur->value == curB->value) {
14019 found = 1;
14020 break;
14021 }
14022 curB = curB->next;
14023 }
14024 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014025 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014026 cur = cur->next;
14027 }
14028 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014029 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014030 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014031 xmlSchemaWildcardNsPtr cur;
14032 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014033 * 3.2.2 super must be a pair of not and a namespace name or
Jan Pokorný761c9e92013-11-29 23:26:27 +010014034 * `absent` and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000014035 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014036 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014037 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014038 if (cur->value == super->negNsSet->value)
14039 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014040 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014042 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000014043 }
14044 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014045 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014046}
14047
Daniel Veillard50355f02004-06-08 17:52:16 +000014048static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014049xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014050 int *fixed,
14051 const xmlChar **value,
14052 xmlSchemaValPtr *val)
14053{
14054 *fixed = 0;
14055 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014056 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014057 *val = NULL;
14058
Daniel Veillarddee23482008-04-11 12:58:43 +000014059 if (attruse->defValue != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014060 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014061 if (val != NULL)
14062 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014063 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014064 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014065 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014066 } else if ((attruse->attrDecl != NULL) &&
14067 (attruse->attrDecl->defValue != NULL)) {
14068 *value = attruse->attrDecl->defValue;
14069 if (val != NULL)
14070 *val = attruse->attrDecl->defVal;
14071 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014072 *fixed = 1;
14073 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014074 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014075 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014076}
Daniel Veillard3646d642004-06-02 19:19:14 +000014077/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014078 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000014079 * @wild: the wildcard
14080 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014081 *
14082 * Validation Rule: Wildcard allows Namespace Name
14083 * (cvc-wildcard-namespace)
14084 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014085 * Returns 0 if the given namespace matches the wildcard,
14086 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000014087 */
14088static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014089xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14090 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000014091{
14092 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014093 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014094
14095 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014096 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014097 else if (wild->nsSet != NULL) {
14098 xmlSchemaWildcardNsPtr cur;
14099
14100 cur = wild->nsSet;
14101 while (cur != NULL) {
14102 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014103 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014104 cur = cur->next;
14105 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014106 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000014107 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014108 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014109
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014110 return(1);
14111}
14112
14113#define XML_SCHEMA_ACTION_DERIVE 0
14114#define XML_SCHEMA_ACTION_REDEFINE 1
14115
14116#define WXS_ACTION_STR(a) \
14117((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14118
14119/*
14120* Schema Component Constraint:
14121* Derivation Valid (Restriction, Complex)
14122* derivation-ok-restriction (2) - (4)
14123*
14124* ATTENTION:
14125* In XML Schema 1.1 this will be:
14126* Validation Rule:
14127* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14128*
14129*/
14130static int
14131xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14132 int action,
14133 xmlSchemaBasicItemPtr item,
14134 xmlSchemaBasicItemPtr baseItem,
14135 xmlSchemaItemListPtr uses,
14136 xmlSchemaItemListPtr baseUses,
14137 xmlSchemaWildcardPtr wild,
14138 xmlSchemaWildcardPtr baseWild)
Daniel Veillarddee23482008-04-11 12:58:43 +000014139{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014140 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014141 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014142 const xmlChar *bEffValue;
14143 int effFixed;
Daniel Veillarddee23482008-04-11 12:58:43 +000014144
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014145 if (uses != NULL) {
14146 for (i = 0; i < uses->nbItems; i++) {
14147 cur = uses->items[i];
14148 found = 0;
14149 if (baseUses == NULL)
14150 goto not_found;
14151 for (j = 0; j < baseUses->nbItems; j++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014152 bcur = baseUses->items[j];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014153 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14154 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14155 (WXS_ATTRUSE_DECL_TNS(cur) ==
14156 WXS_ATTRUSE_DECL_TNS(bcur)))
14157 {
14158 /*
14159 * (2.1) "If there is an attribute use in the {attribute
14160 * uses} of the {base type definition} (call this B) whose
14161 * {attribute declaration} has the same {name} and {target
14162 * namespace}, then all of the following must be true:"
14163 */
14164 found = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000014165
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014166 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14167 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14168 {
14169 xmlChar *str = NULL;
14170 /*
14171 * (2.1.1) "one of the following must be true:"
14172 * (2.1.1.1) "B's {required} is false."
14173 * (2.1.1.2) "R's {required} is true."
14174 */
14175 xmlSchemaPAttrUseErr4(pctxt,
14176 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14177 WXS_ITEM_NODE(item), item, cur,
14178 "The 'optional' attribute use is inconsistent "
14179 "with the corresponding 'required' attribute use of "
14180 "the %s %s",
14181 WXS_ACTION_STR(action),
14182 xmlSchemaGetComponentDesignation(&str, baseItem),
14183 NULL, NULL);
14184 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014185 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014186 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014187 WXS_ATTRUSE_TYPEDEF(cur),
14188 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14189 {
14190 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014191
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014192 /*
14193 * SPEC (2.1.2) "R's {attribute declaration}'s
14194 * {type definition} must be validly derived from
14195 * B's {type definition} given the empty set as
Jan Pokorný761c9e92013-11-29 23:26:27 +010014196 * defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014197 */
14198 xmlSchemaPAttrUseErr4(pctxt,
14199 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14200 WXS_ITEM_NODE(item), item, cur,
14201 "The attribute declaration's %s "
14202 "is not validly derived from "
14203 "the corresponding %s of the "
14204 "attribute declaration in the %s %s",
14205 xmlSchemaGetComponentDesignation(&strA,
14206 WXS_ATTRUSE_TYPEDEF(cur)),
14207 xmlSchemaGetComponentDesignation(&strB,
14208 WXS_ATTRUSE_TYPEDEF(bcur)),
14209 WXS_ACTION_STR(action),
14210 xmlSchemaGetComponentDesignation(&strC, baseItem));
14211 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14212 FREE_AND_NULL(strA);
14213 FREE_AND_NULL(strB);
14214 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014215 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014216 } else {
14217 /*
14218 * 2.1.3 [Definition:] Let the effective value
14219 * constraint of an attribute use be its {value
14220 * constraint}, if present, otherwise its {attribute
14221 * declaration}'s {value constraint} .
14222 */
14223 xmlSchemaGetEffectiveValueConstraint(bcur,
14224 &effFixed, &bEffValue, NULL);
14225 /*
14226 * 2.1.3 ... one of the following must be true
14227 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010014228 * 2.1.3.1 B's `effective value constraint` is
14229 * `absent` or default.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014230 */
14231 if ((bEffValue != NULL) &&
14232 (effFixed == 1)) {
14233 const xmlChar *rEffValue = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014234
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014235 xmlSchemaGetEffectiveValueConstraint(bcur,
14236 &effFixed, &rEffValue, NULL);
14237 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014238 * 2.1.3.2 R's `effective value constraint` is
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014239 * fixed with the same string as B's.
14240 * MAYBE TODO: Compare the computed values.
14241 * Hmm, it says "same string" so
14242 * string-equality might really be sufficient.
14243 */
14244 if ((effFixed == 0) ||
14245 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14246 {
14247 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014248
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014249 xmlSchemaPAttrUseErr4(pctxt,
14250 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14251 WXS_ITEM_NODE(item), item, cur,
14252 "The effective value constraint of the "
14253 "attribute use is inconsistent with "
14254 "its correspondent in the %s %s",
14255 WXS_ACTION_STR(action),
14256 xmlSchemaGetComponentDesignation(&str,
14257 baseItem),
14258 NULL, NULL);
14259 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014260 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014261 }
14262 }
14263 }
14264 break;
14265 }
14266 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014267not_found:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014268 if (!found) {
14269 /*
14270 * (2.2) "otherwise the {base type definition} must have an
14271 * {attribute wildcard} and the {target namespace} of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014272 * R's {attribute declaration} must be `valid` with respect
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014273 * to that wildcard, as defined in Wildcard allows Namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010014274 * Name ($3.10.4)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014275 */
14276 if ((baseWild == NULL) ||
14277 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14278 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14279 {
14280 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014281
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014282 xmlSchemaPAttrUseErr4(pctxt,
14283 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14284 WXS_ITEM_NODE(item), item, cur,
14285 "Neither a matching attribute use, "
14286 "nor a matching wildcard exists in the %s %s",
14287 WXS_ACTION_STR(action),
14288 xmlSchemaGetComponentDesignation(&str, baseItem),
14289 NULL, NULL);
14290 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014291 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014292 }
14293 }
14294 }
14295 }
14296 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000014297 * SPEC derivation-ok-restriction (3):
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014298 * (3) "For each attribute use in the {attribute uses} of the {base type
14299 * definition} whose {required} is true, there must be an attribute
14300 * use with an {attribute declaration} with the same {name} and
14301 * {target namespace} as its {attribute declaration} in the {attribute
14302 * uses} of the complex type definition itself whose {required} is true.
14303 */
14304 if (baseUses != NULL) {
14305 for (j = 0; j < baseUses->nbItems; j++) {
14306 bcur = baseUses->items[j];
14307 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14308 continue;
14309 found = 0;
14310 if (uses != NULL) {
14311 for (i = 0; i < uses->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014312 cur = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014313 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14314 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14315 (WXS_ATTRUSE_DECL_TNS(cur) ==
14316 WXS_ATTRUSE_DECL_TNS(bcur))) {
14317 found = 1;
14318 break;
14319 }
14320 }
14321 }
14322 if (!found) {
14323 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014324
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014325 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14326 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14327 NULL, item,
14328 "A matching attribute use for the "
14329 "'required' %s of the %s %s is missing",
14330 xmlSchemaGetComponentDesignation(&strA, bcur),
14331 WXS_ACTION_STR(action),
14332 xmlSchemaGetComponentDesignation(&strB, baseItem),
14333 NULL);
14334 FREE_AND_NULL(strA);
14335 FREE_AND_NULL(strB);
14336 }
14337 }
14338 }
14339 /*
14340 * derivation-ok-restriction (4)
14341 */
14342 if (wild != NULL) {
14343 /*
14344 * (4) "If there is an {attribute wildcard}, all of the
14345 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000014346 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014347 if (baseWild == NULL) {
14348 xmlChar *str = NULL;
14349
14350 /*
14351 * (4.1) "The {base type definition} must also have one."
Daniel Veillarddee23482008-04-11 12:58:43 +000014352 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014353 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14354 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14355 NULL, item,
14356 "The %s has an attribute wildcard, "
14357 "but the %s %s '%s' does not have one",
Daniel Veillarddee23482008-04-11 12:58:43 +000014358 WXS_ITEM_TYPE_NAME(item),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014359 WXS_ACTION_STR(action),
14360 WXS_ITEM_TYPE_NAME(baseItem),
14361 xmlSchemaGetComponentQName(&str, baseItem));
14362 FREE_AND_NULL(str);
14363 return(pctxt->err);
14364 } else if ((baseWild->any == 0) &&
14365 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14366 {
14367 xmlChar *str = NULL;
14368 /*
14369 * (4.2) "The complex type definition's {attribute wildcard}'s
14370 * {namespace constraint} must be a subset of the {base type
14371 * definition}'s {attribute wildcard}'s {namespace constraint},
Jan Pokorný761c9e92013-11-29 23:26:27 +010014372 * as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014373 */
14374 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14375 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14376 NULL, item,
14377 "The attribute wildcard is not a valid "
14378 "subset of the wildcard in the %s %s '%s'",
14379 WXS_ACTION_STR(action),
14380 WXS_ITEM_TYPE_NAME(baseItem),
14381 xmlSchemaGetComponentQName(&str, baseItem),
14382 NULL);
14383 FREE_AND_NULL(str);
14384 return(pctxt->err);
14385 }
Jan Pokorný761c9e92013-11-29 23:26:27 +010014386 /* 4.3 Unless the {base type definition} is the `ur-type
14387 * definition`, the complex type definition's {attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014388 * wildcard}'s {process contents} must be identical to or
14389 * stronger than the {base type definition}'s {attribute
14390 * wildcard}'s {process contents}, where strict is stronger
14391 * than lax is stronger than skip.
14392 */
14393 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14394 (wild->processContents < baseWild->processContents)) {
14395 xmlChar *str = NULL;
14396 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14397 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14398 NULL, baseItem,
14399 "The {process contents} of the attribute wildcard is "
14400 "weaker than the one in the %s %s '%s'",
14401 WXS_ACTION_STR(action),
14402 WXS_ITEM_TYPE_NAME(baseItem),
14403 xmlSchemaGetComponentQName(&str, baseItem),
14404 NULL);
14405 FREE_AND_NULL(str)
14406 return(pctxt->err);
14407 }
14408 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014409 return(0);
14410}
14411
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014412
14413static int
14414xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14415 xmlSchemaBasicItemPtr item,
14416 xmlSchemaWildcardPtr *completeWild,
14417 xmlSchemaItemListPtr list,
14418 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014419/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014420 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014421 * @ctxt: the schema parser context
14422 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014423 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014424 *
14425 * Builds the wildcard and the attribute uses on the given complex type.
14426 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014427 *
14428 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14429 * strings, so recheck this if we start to hardcode some schemata, since
14430 * they might not be in the same dict.
14431 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014432 */
14433static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014434xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014435 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014436{
14437 xmlSchemaTypePtr baseType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014438 xmlSchemaAttributeUsePtr use;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014439 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014440
Daniel Veillard01fa6152004-06-29 17:04:39 +000014441 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014442 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014443 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014444 return (-1);
14445 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014446 baseType = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014447 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014448 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014449 return(-1);
14450
14451 uses = type->attrUses;
14452 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014453 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014454 * Expand attribute group references. And build the 'complete'
14455 * wildcard, i.e. intersect multiple wildcards.
14456 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014457 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014458 if (uses != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014459 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014460 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014461 * This one will transfer all attr. prohibitions
14462 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014463 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014464 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14465 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14466 pctxt->attrProhibs) == -1)
14467 {
14468 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14469 "failed to expand attributes");
14470 }
14471 if (pctxt->attrProhibs->nbItems != 0)
14472 prohibs = pctxt->attrProhibs;
14473 } else {
14474 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14475 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14476 NULL) == -1)
14477 {
14478 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14479 "failed to expand attributes");
14480 }
14481 }
14482 }
14483 /*
14484 * Inherit the attribute uses of the base type.
14485 */
14486 if (baseUses != NULL) {
14487 int i, j;
14488 xmlSchemaAttributeUseProhibPtr pro;
14489
14490 if (WXS_IS_RESTRICTION(type)) {
14491 int usesCount;
Daniel Veillarddee23482008-04-11 12:58:43 +000014492 xmlSchemaAttributeUsePtr tmp;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014493
14494 if (uses != NULL)
14495 usesCount = uses->nbItems;
14496 else
14497 usesCount = 0;
14498
14499 /* Restriction. */
14500 for (i = 0; i < baseUses->nbItems; i++) {
14501 use = baseUses->items[i];
14502 if (prohibs) {
14503 /*
14504 * Filter out prohibited uses.
14505 */
14506 for (j = 0; j < prohibs->nbItems; j++) {
14507 pro = prohibs->items[j];
14508 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14509 (WXS_ATTRUSE_DECL_TNS(use) ==
14510 pro->targetNamespace))
14511 {
14512 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014513 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014514 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014515 }
14516 if (usesCount) {
14517 /*
14518 * Filter out existing uses.
14519 */
14520 for (j = 0; j < usesCount; j++) {
14521 tmp = uses->items[j];
14522 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14523 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14524 (WXS_ATTRUSE_DECL_TNS(use) ==
14525 WXS_ATTRUSE_DECL_TNS(tmp)))
14526 {
14527 goto inherit_next;
14528 }
14529 }
14530 }
14531 if (uses == NULL) {
14532 type->attrUses = xmlSchemaItemListCreate();
14533 if (type->attrUses == NULL)
14534 goto exit_failure;
14535 uses = type->attrUses;
14536 }
14537 xmlSchemaItemListAddSize(uses, 2, use);
14538inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014539 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014540 } else {
14541 /* Extension. */
Daniel Veillarddee23482008-04-11 12:58:43 +000014542 for (i = 0; i < baseUses->nbItems; i++) {
14543 use = baseUses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014544 if (uses == NULL) {
14545 type->attrUses = xmlSchemaItemListCreate();
14546 if (type->attrUses == NULL)
14547 goto exit_failure;
14548 uses = type->attrUses;
14549 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014550 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014551 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014552 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014553 }
14554 /*
14555 * Shrink attr. uses.
14556 */
14557 if (uses) {
14558 if (uses->nbItems == 0) {
14559 xmlSchemaItemListFree(uses);
14560 type->attrUses = NULL;
14561 }
14562 /*
14563 * TODO: We could shrink the size of the array
14564 * to fit the actual number of items.
14565 */
14566 }
14567 /*
14568 * Compute the complete wildcard.
14569 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014570 if (WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014571 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014572 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014573 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014574 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014575 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014576 if (type->attributeWildcard != NULL) {
14577 /*
14578 * Union the complete wildcard with the base wildcard.
14579 * SPEC {attribute wildcard}
14580 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
Jan Pokorný761c9e92013-11-29 23:26:27 +010014581 * and {annotation} are those of the `complete wildcard`,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014582 * and whose {namespace constraint} is the intensional union
Jan Pokorný761c9e92013-11-29 23:26:27 +010014583 * of the {namespace constraint} of the `complete wildcard`
14584 * and of the `base wildcard`, as defined in Attribute
14585 * Wildcard Union ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014586 */
14587 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14588 baseType->attributeWildcard) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000014589 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014590 } else {
14591 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014592 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14593 * then the `base wildcard`."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014594 */
14595 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillarddee23482008-04-11 12:58:43 +000014596 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014597 } else {
14598 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014599 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14600 * `complete wildcard`"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014601 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014602 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014603 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014604 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014605 /*
14606 * SPEC {attribute wildcard}
14607 * (3.1) "If the <restriction> alternative is chosen, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014608 * `complete wildcard`;"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014609 * NOOP
14610 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014611 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014612
Daniel Veillard3646d642004-06-02 19:19:14 +000014613 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014614
14615exit_failure:
14616 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014617}
14618
14619/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014620 * xmlSchemaTypeFinalContains:
14621 * @schema: the schema
14622 * @type: the type definition
14623 * @final: the final
14624 *
14625 * Evaluates if a type definition contains the given "final".
14626 * This does take "finalDefault" into account as well.
14627 *
14628 * Returns 1 if the type does containt the given "final",
14629 * 0 otherwise.
14630 */
14631static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014632xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014633{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014634 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014635 return (0);
14636 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014637 return (1);
14638 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014639 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014640}
14641
14642/**
14643 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14644 * @type: the Union Simple Type
14645 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014646 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014647 * returns NULL otherwise.
14648 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014649static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14651{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014652 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014653 if (type->memberTypes != NULL)
14654 return (type->memberTypes);
14655 else
14656 type = type->baseType;
14657 }
14658 return (NULL);
14659}
14660
14661/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014662 * xmlSchemaGetParticleTotalRangeMin:
14663 * @particle: the particle
14664 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014665 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014666 * (all and sequence) + (choice)
14667 *
14668 * Returns the minimun Effective Total Range.
14669 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014670static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014671xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014672{
14673 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014674 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014675 return (0);
14676 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014677 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014679 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014680
14681 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014682 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014683 while (part != NULL) {
14684 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14685 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014686 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014687 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014688 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014689 if (cur == 0)
14690 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014691 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014692 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014693 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014694 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014695 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014696 } else {
14697 /* <all> and <sequence> */
14698 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014699 xmlSchemaParticlePtr part =
14700 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014701
14702 if (part == NULL)
14703 return (0);
14704 do {
14705 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14706 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014707 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014708 else
14709 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014710 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014711 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014712 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014713 }
14714}
14715
Daniel Veillard15724252008-08-30 15:01:04 +000014716#if 0
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014717/**
14718 * xmlSchemaGetParticleTotalRangeMax:
14719 * @particle: the particle
14720 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014721 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014722 * (all and sequence) + (choice)
14723 *
14724 * Returns the maximum Effective Total Range.
14725 */
14726static int
14727xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14728{
14729 if ((particle->children == NULL) ||
14730 (particle->children->children == NULL))
14731 return (0);
14732 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14733 int max = -1, cur;
14734 xmlSchemaParticlePtr part =
14735 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014736
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014737 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14738 if (part->children == NULL)
14739 continue;
14740 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14741 (part->children->type == XML_SCHEMA_TYPE_ANY))
14742 cur = part->maxOccurs;
14743 else
14744 cur = xmlSchemaGetParticleTotalRangeMax(part);
14745 if (cur == UNBOUNDED)
14746 return (UNBOUNDED);
14747 if ((max < cur) || (max == -1))
14748 max = cur;
14749 }
14750 /* TODO: Handle overflows? */
14751 return (particle->maxOccurs * max);
14752 } else {
14753 /* <all> and <sequence> */
14754 int sum = 0, cur;
14755 xmlSchemaParticlePtr part =
14756 (xmlSchemaParticlePtr) particle->children->children;
14757
14758 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14759 if (part->children == NULL)
14760 continue;
14761 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14762 (part->children->type == XML_SCHEMA_TYPE_ANY))
14763 cur = part->maxOccurs;
14764 else
14765 cur = xmlSchemaGetParticleTotalRangeMax(part);
14766 if (cur == UNBOUNDED)
14767 return (UNBOUNDED);
14768 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14769 return (UNBOUNDED);
14770 sum += cur;
14771 }
14772 /* TODO: Handle overflows? */
14773 return (particle->maxOccurs * sum);
14774 }
14775}
Daniel Veillard15724252008-08-30 15:01:04 +000014776#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014777
14778/**
14779 * xmlSchemaIsParticleEmptiable:
14780 * @particle: the particle
14781 *
14782 * Schema Component Constraint: Particle Emptiable
14783 * Checks whether the given particle is emptiable.
14784 *
14785 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014786 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014787static int
14788xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14789{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014790 /*
14791 * SPEC (1) "Its {min occurs} is 0."
14792 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 if ((particle == NULL) || (particle->minOccurs == 0) ||
14794 (particle->children == NULL))
14795 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014796 /*
14797 * SPEC (2) "Its {term} is a group and the minimum part of the
14798 * effective total range of that group, [...] is 0."
14799 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014800 if (WXS_IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014801 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802 return (1);
14803 }
14804 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014805}
14806
14807/**
14808 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014809 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014810 * @type: the derived simple type definition
14811 * @baseType: the base type definition
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014812 * @subset: the subset of ('restriction', ect.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014813 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014814 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014815 * Type Derivation OK (Simple) (cos-st-derived-OK)
14816 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014817 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014818 * derived from @baseType.
14819 *
14820 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014821 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014822static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014823xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014824 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014825 xmlSchemaTypePtr baseType,
14826 int subset)
14827{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014828 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014829 * 1 They are the same type definition.
14830 * TODO: The identy check might have to be more complex than this.
14831 */
14832 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014833 return (0);
14834 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014835 * 2.1 restriction is not in the subset, or in the {final}
14836 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014837 *
14838 * NOTE that this will be used also via "xsi:type".
14839 *
14840 * TODO: Revise this, it looks strange. How can the "type"
14841 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014842 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014843 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014844 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014845 return(-1);
14846 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014847 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014848 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014849 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014850 (xmlSchemaTypeFinalContains(type->baseType,
14851 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14852 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014853 }
14854 /* 2.2 */
14855 if (type->baseType == baseType) {
14856 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014857 * 2.2.1 D's `base type definition` is B.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014858 */
14859 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014860 }
14861 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014862 * 2.2.2 D's `base type definition` is not the `ur-type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014863 * and is validly derived from B given the subset, as defined by this
14864 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014865 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014866 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014867 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014868 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014869 return (0);
14870 }
14871 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014872 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14873 * definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014874 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014875 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14876 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014877 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014878 }
14879 /*
14880 * 2.2.4 B's {variety} is union and D is validly derived from a type
14881 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014882 * defined by this constraint.
14883 *
14884 * NOTE: This seems not to involve built-in types, since there is no
14885 * built-in Union Simple Type.
14886 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014887 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014888 xmlSchemaTypeLinkPtr cur;
14889
14890 cur = baseType->memberTypes;
14891 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014892 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014893 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014894 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014895 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014896 type, cur->type, subset) == 0)
14897 {
14898 /*
14899 * It just has to be validly derived from at least one
14900 * member-type.
14901 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014902 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014903 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014904 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014906 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014907 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14908}
14909
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014910/**
14911 * xmlSchemaCheckTypeDefCircularInternal:
14912 * @pctxt: the schema parser context
14913 * @ctxtType: the type definition
14914 * @ancestor: an ancestor of @ctxtType
14915 *
14916 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014918 *
14919 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14920 * circular, 0 otherwise.
14921 */
14922static int
14923xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14924 xmlSchemaTypePtr ctxtType,
14925 xmlSchemaTypePtr ancestor)
14926{
14927 int ret;
14928
14929 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14930 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014931
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014932 if (ctxtType == ancestor) {
14933 xmlSchemaPCustomErr(pctxt,
14934 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014935 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014936 "The definition is circular", NULL);
14937 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14938 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014939 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14940 /*
14941 * Avoid inifinite recursion on circular types not yet checked.
14942 */
14943 return (0);
14944 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014945 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14946 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14947 ancestor->baseType);
14948 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14949 return (ret);
14950}
14951
14952/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014953 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014954 * @item: the complex/simple type definition
14955 * @ctxt: the parser context
14956 * @name: the name
14957 *
14958 * Checks for circular type definitions.
14959 */
14960static void
14961xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014962 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014963{
14964 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014965 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14966 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014967 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014968 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14969 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014970}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014971
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014972/*
14973* Simple Type Definition Representation OK (src-simple-type) 4
14974*
14975* "4 Circular union type definition is disallowed. That is, if the
14976* <union> alternative is chosen, there must not be any entries in the
14977* memberTypes [attribute] at any depth which resolve to the component
14978* corresponding to the <simpleType>."
14979*
14980* Note that this should work on the *representation* of a component,
14981* thus assumes any union types in the member types not being yet
14982* substituted. At this stage we need the variety of the types
14983* to be already computed.
14984*/
14985static int
14986xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14987 xmlSchemaTypePtr ctxType,
14988 xmlSchemaTypeLinkPtr members)
Daniel Veillarddee23482008-04-11 12:58:43 +000014989{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014990 xmlSchemaTypeLinkPtr member;
14991 xmlSchemaTypePtr memberType;
Daniel Veillarddee23482008-04-11 12:58:43 +000014992
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014993 member = members;
14994 while (member != NULL) {
14995 memberType = member->type;
14996 while ((memberType != NULL) &&
14997 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14998 if (memberType == ctxType) {
14999 xmlSchemaPCustomErr(pctxt,
15000 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015001 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015002 "The union type definition is circular", NULL);
15003 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15004 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015005 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015006 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15007 {
15008 int res;
15009 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15010 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15011 ctxType,
15012 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15013 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15014 if (res != 0)
15015 return(res);
15016 }
15017 memberType = memberType->baseType;
15018 }
15019 member = member->next;
15020 }
15021 return(0);
15022}
15023
15024static int
15025xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15026 xmlSchemaTypePtr type)
15027{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015028 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015029 return(0);
15030 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15031 type->memberTypes));
15032}
15033
Daniel Veillard01fa6152004-06-29 17:04:39 +000015034/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015035 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015036 * @item: the complex/simple type definition
15037 * @ctxt: the parser context
15038 * @name: the name
15039 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015040 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015041 */
15042static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015043xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015044 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015045{
15046 if (typeDef == NULL)
15047 return;
15048
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015049 /*
15050 * Resolve the base type.
15051 */
15052 if (typeDef->baseType == NULL) {
15053 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15054 typeDef->base, typeDef->baseNs);
15055 if (typeDef->baseType == NULL) {
15056 xmlSchemaPResCompAttrErr(ctxt,
15057 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015058 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015059 "base", typeDef->base, typeDef->baseNs,
15060 XML_SCHEMA_TYPE_SIMPLE, NULL);
15061 return;
15062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015063 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015064 if (WXS_IS_SIMPLE(typeDef)) {
15065 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015066 /*
15067 * Resolve the memberTypes.
15068 */
15069 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15070 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015071 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015072 /*
15073 * Resolve the itemType.
15074 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015075 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15076
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015077 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015078 typeDef->base, typeDef->baseNs);
15079
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015080 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015081 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15082 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083 typeDef->subtypes = NULL;
15084 xmlSchemaPResCompAttrErr(ctxt,
15085 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015086 WXS_BASIC_CAST typeDef, typeDef->node,
15087 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015088 XML_SCHEMA_TYPE_SIMPLE, NULL);
15089 }
15090 }
15091 return;
15092 }
Daniel Veillarddee23482008-04-11 12:58:43 +000015093 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015094 /*
15095 * The ball of letters below means, that if we have a particle
15096 * which has a QName-helper component as its {term}, we want
15097 * to resolve it...
15098 */
15099 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15100 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15101 XML_SCHEMA_TYPE_PARTICLE) &&
15102 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15103 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15104 XML_SCHEMA_EXTRA_QNAMEREF))
15105 {
15106 xmlSchemaQNameRefPtr ref =
15107 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15108 xmlSchemaModelGroupDefPtr groupDef;
15109
15110 /*
15111 * URGENT TODO: Test this.
15112 */
15113 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15114 /*
15115 * Resolve the MG definition reference.
15116 */
15117 groupDef =
15118 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15119 ref->itemType, ref->name, ref->targetNamespace);
15120 if (groupDef == NULL) {
15121 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15122 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15123 "ref", ref->name, ref->targetNamespace, ref->itemType,
15124 NULL);
15125 /* Remove the particle. */
15126 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15127 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15128 /* Remove the particle. */
15129 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15130 else {
15131 /*
15132 * Assign the MG definition's {model group} to the
15133 * particle's {term}.
15134 */
15135 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
Daniel Veillarddee23482008-04-11 12:58:43 +000015136
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015137 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15138 /*
15139 * SPEC cos-all-limited (1.2)
15140 * "1.2 the {term} property of a particle with
15141 * {max occurs}=1 which is part of a pair which constitutes
15142 * the {content type} of a complex type definition."
15143 */
15144 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15145 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15146 /* TODO: error code */
15147 XML_SCHEMAP_COS_ALL_LIMITED,
15148 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15149 "The particle's {max occurs} must be 1, since the "
15150 "reference resolves to an 'all' model group",
15151 NULL, NULL);
15152 }
15153 }
15154 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015156}
15157
15158
15159
15160/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015161 * xmlSchemaCheckSTPropsCorrect:
15162 * @ctxt: the schema parser context
15163 * @type: the simple type definition
15164 *
15165 * Checks st-props-correct.
15166 *
15167 * Returns 0 if the properties are correct,
15168 * if not, a positive error code and -1 on internal
15169 * errors.
15170 */
15171static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015172xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015173 xmlSchemaTypePtr type)
15174{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015175 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015176 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177
Daniel Veillardc0826a72004-08-10 14:17:33 +000015178 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015179 /*
15180 * Schema Component Constraint: Simple Type Definition Properties Correct
15181 *
15182 * NOTE: This is somehow redundant, since we actually built a simple type
15183 * to have all the needed information; this acts as an self test.
15184 */
Jan Pokorný761c9e92013-11-29 23:26:27 +010015185 /* Base type: If the datatype has been `derived` by `restriction`
15186 * then the Simple Type Definition component from which it is `derived`,
15187 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015188 */
15189 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015190 /*
15191 * TODO: Think about: "modulo the impact of Missing
Jan Pokorný761c9e92013-11-29 23:26:27 +010015192 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015193 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015194 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015195 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015196 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015197 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015198 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015199
Daniel Veillard01fa6152004-06-29 17:04:39 +000015200 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015201 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015202 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015203 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015204 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015205 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015206 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015207 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015208 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15209 }
Toyoda Eizi8bb12982011-08-04 16:40:48 +080015210 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15211 (WXS_IS_RESTRICTION(type) == 0) &&
15212 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15213 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015214 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015215 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015216 WXS_BASIC_CAST type, NULL,
Daniel Veillardbf9c1da2008-08-26 07:46:42 +000015217 "A type, derived by list or union, must have "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015218 "the simple ur-type definition as base type, not '%s'",
15219 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015220 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015221 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15222 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015223 /*
15224 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015225 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015226 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15227 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015228 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015229 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015230 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015231 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015232 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15233 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015234 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015235
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015236 /*
15237 * 3 The {final} of the {base type definition} must not contain restriction.
15238 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015239 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15241 xmlSchemaPCustomErr(ctxt,
15242 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015243 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015244 "The 'final' of its base type '%s' must not contain "
15245 "'restriction'",
15246 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015247 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015248 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015250
15251 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015252 * 2 All simple type definitions must be derived ultimately from the `simple
15253 * ur-type definition` (so circular definitions are disallowed). That is, it
15254 * must be possible to reach a built-in primitive datatype or the `simple
15255 * ur-type definition` by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015256 *
15257 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015258 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015259 return (0);
15260}
15261
15262/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015263 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015264 * @ctxt: the schema parser context
15265 * @type: the simple type definition
15266 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015267 * Schema Component Constraint:
15268 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15269
15270 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015271 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015272 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015273 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015274 * a positive error code otherwise.
15275 */
15276static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015277xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015278 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015279{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015280 xmlChar *str = NULL;
15281
Daniel Veillard01fa6152004-06-29 17:04:39 +000015282 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015283 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15284 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015285 return (-1);
15286 }
15287
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015288 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015289 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015290 /*
15291 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015292 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015293 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015294 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015296 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015297 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015298 "The base type '%s' is not an atomic simple type",
15299 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015300 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15302 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015303 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015304 * restriction.
15305 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015306 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015308 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015309 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015310 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015311 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015312 "The final of its base type '%s' must not contain 'restriction'",
15313 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015314 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015315 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15316 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015317
15318 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015319 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015320 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015321 * Primitive datatypes.
15322 */
15323 if (type->facets != NULL) {
15324 xmlSchemaFacetPtr facet;
15325 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015326
Daniel Veillard01fa6152004-06-29 17:04:39 +000015327 primitive = xmlSchemaGetPrimitiveType(type);
15328 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015329 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15330 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015331 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015332 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015333 facet = type->facets;
15334 do {
15335 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015336 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015337 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015338 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015339 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015340 }
15341 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015342 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015343 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015345 }
15346 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015347 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15348 * of the {base type definition} (call this BF),then the DF's {value}
15349 * must be a valid restriction of BF's {value} as defined in
15350 * [XML Schemas: Datatypes]."
15351 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015353 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015354 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015355 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015356 xmlSchemaTypePtr itemType = NULL;
15357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015359 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015360 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15361 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015362 return (-1);
15363 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015364 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015365 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015366 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015367 * 2.1 The {item type definition} must have a {variety} of atomic or
15368 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015369 * must be atomic).
15370 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015371 if ((! WXS_IS_ATOMIC(itemType)) &&
15372 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015373 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015374 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015375 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015376 "The item type '%s' does not have a variety of atomic or union",
15377 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015378 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015379 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015380 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015381 xmlSchemaTypeLinkPtr member;
15382
15383 member = itemType->memberTypes;
15384 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015385 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015387 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015388 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015389 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015390 "member type '%s' of this item type is not atomic",
15391 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015393 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15394 }
15395 member = member->next;
15396 }
15397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015398
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015399 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015400 xmlSchemaFacetPtr facet;
15401 /*
15402 * This is the case if we have: <simpleType><list ..
15403 */
15404 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015405 * 2.3.1
15406 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015407 * contain list.
15408 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015409 if (xmlSchemaTypeFinalContains(itemType,
15410 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15411 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015412 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015413 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015414 "The final of its item type '%s' must not contain 'list'",
15415 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015416 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015417 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15418 }
15419 /*
15420 * 2.3.1.2 The {facets} must only contain the whiteSpace
15421 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015422 * OPTIMIZE TODO: the S4S already disallows any facet
15423 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 */
15425 if (type->facets != NULL) {
15426 facet = type->facets;
15427 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015428 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015430 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015431 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015432 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15433 }
15434 facet = facet->next;
15435 } while (facet != NULL);
15436 }
15437 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015438 * MAYBE TODO: (Hmm, not really) Datatypes states:
Jan Pokorný761c9e92013-11-29 23:26:27 +010015439 * A `list` datatype can be `derived` from an `atomic` datatype
15440 * whose `lexical space` allows space (such as string or anyURI)or
15441 * a `union` datatype any of whose {member type definitions}'s
15442 * `lexical space` allows space.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015443 */
15444 } else {
15445 /*
15446 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015448 */
15449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015450 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015451 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15452 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015453 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015454 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015455 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015456 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015457 "The base type '%s' must be a list type",
15458 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015459 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015460 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15461 }
15462 /*
15463 * 2.3.2.2 The {final} of the {base type definition} must not
15464 * contain restriction.
15465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015466 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015467 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015468 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015469 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015470 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015471 "The 'final' of the base type '%s' must not contain 'restriction'",
15472 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015473 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015474 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15475 }
15476 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015477 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015478 * from the {base type definition}'s {item type definition} given
Jan Pokorný761c9e92013-11-29 23:26:27 +010015479 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015480 */
15481 {
15482 xmlSchemaTypePtr baseItemType;
15483
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015484 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015485 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015486 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15487 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015488 return (-1);
15489 }
15490 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015491 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015492 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015493 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015494 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015495 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015496 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015497 "The item type '%s' is not validly derived from "
15498 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015499 xmlSchemaGetComponentQName(&str, itemType),
15500 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15501 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015502
15503 FREE_AND_NULL(str)
15504 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015505 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015506 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15507 }
15508 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015509
Daniel Veillard01fa6152004-06-29 17:04:39 +000015510 if (type->facets != NULL) {
15511 xmlSchemaFacetPtr facet;
15512 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015513 /*
15514 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015515 * and enumeration facet components are allowed among the {facets}.
15516 */
15517 facet = type->facets;
15518 do {
15519 switch (facet->type) {
15520 case XML_SCHEMA_FACET_LENGTH:
15521 case XML_SCHEMA_FACET_MINLENGTH:
15522 case XML_SCHEMA_FACET_MAXLENGTH:
15523 case XML_SCHEMA_FACET_WHITESPACE:
15524 /*
15525 * TODO: 2.5.1.2 List datatypes
Jan Pokorný761c9e92013-11-29 23:26:27 +010015526 * The value of `whiteSpace` is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015527 */
15528 case XML_SCHEMA_FACET_PATTERN:
15529 case XML_SCHEMA_FACET_ENUMERATION:
15530 break;
15531 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015532 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015533 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015534 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015535 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015536 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015537 * invalid facets.
15538 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015539 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015542 facet = facet->next;
15543 } while (facet != NULL);
15544 if (ok == 0)
15545 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15546 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015547 * SPEC (2.3.2.5) (same as 1.3.2)
15548 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015549 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015550 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015551 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015552 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015553 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015554 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015555 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015556 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015557 * atomic or list.
15558 */
15559 xmlSchemaTypeLinkPtr member;
15560
15561 member = type->memberTypes;
15562 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015563 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015564 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015565
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015566 if ((! WXS_IS_ATOMIC(member->type)) &&
15567 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015568 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015569 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015570 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015571 "The member type '%s' is neither an atomic, nor a list type",
15572 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015573 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015574 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15575 }
15576 member = member->next;
15577 }
15578 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015579 * 3.3.1 If the {base type definition} is the `simple ur-type
15580 * definition`
Daniel Veillard01fa6152004-06-29 17:04:39 +000015581 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015582 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015584 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015585 * {final} which does not contain union.
15586 */
15587 member = type->memberTypes;
15588 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015589 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015590 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015591 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015592 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015593 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015594 "The 'final' of member type '%s' contains 'union'",
15595 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015596 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015597 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15598 }
15599 member = member->next;
15600 }
15601 /*
15602 * 3.3.1.2 The {facets} must be empty.
15603 */
15604 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015605 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015606 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015607 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015608 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015609 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15610 }
15611 } else {
15612 /*
15613 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015614 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015615 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015616 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015617 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015618 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015619 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015620 "The base type '%s' is not a union type",
15621 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015622 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015623 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15624 }
15625 /*
15626 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15627 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015628 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015629 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015630 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015631 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015632 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015633 "The 'final' of its base type '%s' must not contain 'restriction'",
15634 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015635 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015636 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15637 }
15638 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015639 * 3.3.2.3 The {member type definitions}, in order, must be validly
15640 * derived from the corresponding type definitions in the {base
15641 * type definition}'s {member type definitions} given the empty set,
Jan Pokorný761c9e92013-11-29 23:26:27 +010015642 * as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015643 */
15644 {
15645 xmlSchemaTypeLinkPtr baseMember;
15646
15647 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015648 * OPTIMIZE: if the type is restricting, it has no local defined
15649 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015650 * thus a check for equality can be skipped.
15651 */
15652 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015653 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015655 * types of it's base type. This check seems not necessary with
15656 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015657 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015658 */
15659 if (type->memberTypes != NULL) {
15660 member = type->memberTypes;
15661 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015662 if ((member == NULL) && (baseMember != NULL)) {
15663 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15664 "different number of member types in base");
15665 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015666 while (member != NULL) {
15667 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015668 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15669 "different number of member types in base");
Daniel Veillard14b56432006-03-09 18:41:40 +000015670 } else if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015671 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015672 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015673 xmlChar *strBMT = NULL, *strBT = NULL;
15674
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015675 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015676 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015677 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015678 "The member type %s is not validly "
15679 "derived from its corresponding member "
15680 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015681 xmlSchemaGetComponentQName(&str, member->type),
15682 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15683 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015684 FREE_AND_NULL(str)
15685 FREE_AND_NULL(strBMT)
15686 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015687 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015688 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015689 member = member->next;
Daniel Veillardd44b9362009-09-07 12:15:08 +020015690 if (baseMember != NULL)
15691 baseMember = baseMember->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015692 }
15693 }
15694 }
15695 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015696 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015697 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015698 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015699 if (type->facets != NULL) {
15700 xmlSchemaFacetPtr facet;
15701 int ok = 1;
15702
15703 facet = type->facets;
15704 do {
15705 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15706 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015708 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015709 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015710 ok = 0;
15711 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015712 facet = facet->next;
15713 } while (facet != NULL);
15714 if (ok == 0)
15715 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015716
Daniel Veillard01fa6152004-06-29 17:04:39 +000015717 }
15718 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015719 * SPEC (3.3.2.5) (same as 1.3.2)
15720 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015722 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015723 */
15724 }
15725 }
15726
15727 return (0);
15728}
15729
15730/**
15731 * xmlSchemaCheckSRCSimpleType:
15732 * @ctxt: the schema parser context
15733 * @type: the simple type definition
15734 *
Daniel Veillarddee23482008-04-11 12:58:43 +000015735 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015736 *
15737 * Returns 0 if the constraints are satisfied,
15738 * if not a positive error code and -1 on internal
15739 * errors.
15740 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015741#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015742static int
15743xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15744 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745{
15746 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015747 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015748 * must satisfy the conditions set out in Constraints on Simple Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010015749 * Definition Schema Components ($3.14.6).
Daniel Veillarddee23482008-04-11 12:58:43 +000015750 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015751 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015752 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015753 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015754 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015755 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015756 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015757 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015758 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000015759 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015760 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015761 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015762 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015763 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015764 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015765 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015766 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015767 */
Daniel Veillarddee23482008-04-11 12:58:43 +000015768 } else if (WXS_IS_UNION(type)) {
15769 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015770 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015772 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015773 return (0);
15774}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015775#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015776
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015777static int
15778xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15779{
15780 if (ctxt->vctxt == NULL) {
15781 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15782 if (ctxt->vctxt == NULL) {
15783 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015784 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015785 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015786 "failed to create a temp. validation context.\n",
15787 NULL, NULL);
15788 return (-1);
15789 }
15790 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015791 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015792 ctxt->error, ctxt->warning, ctxt->errCtxt);
15793 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15794 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015795 }
15796 return (0);
15797}
15798
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799static int
15800xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15801 xmlNodePtr node,
15802 xmlSchemaTypePtr type,
15803 const xmlChar *value,
15804 xmlSchemaValPtr *retVal,
15805 int fireErrors,
15806 int normalize,
15807 int isNormalized);
15808
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015809/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015810 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015811 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015812 * @type: the simple type definition
15813 * @value: the default value
15814 * @node: an optional node (the holder of the value)
15815 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015816 * Schema Component Constraint: Element Default Valid (Immediate)
15817 * (cos-valid-default)
15818 * This will be used by the parser only. For the validator there's
15819 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015820 *
15821 * Returns 0 if the constraints are satisfied,
15822 * if not, a positive error code and -1 on internal
15823 * errors.
15824 */
15825static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015826xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15827 xmlNodePtr node,
15828 xmlSchemaTypePtr type,
15829 const xmlChar *value,
15830 xmlSchemaValPtr *val)
15831{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015832 int ret = 0;
15833
15834 /*
15835 * cos-valid-default:
15836 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015837 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015838 * definition the appropriate case among the following must be true:
15839 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015840 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015841 /*
15842 * Complex type.
15843 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015844 * SPEC (2.1) "its {content type} must be a simple type definition
15845 * or mixed."
15846 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010015847 * type}'s particle must be `emptiable` as defined by
15848 * Particle Emptiable ($3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015849 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015850 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15851 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015852 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015853 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015854 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015855 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015856 "For a string to be a valid default, the type definition "
15857 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015858 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015859 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15860 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015861 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015863 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010015864 * must be `valid` with respect to that definition as defined by String
15865 * Valid ($3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015866 *
15867 * AND
15868 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010015870 * string must be `valid` with respect to that simple type definition
15871 * as defined by String Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015872 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015873 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015874 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015875 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015876 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015877 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015878 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015879 else
15880 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015881
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015882 if (ret < 0) {
15883 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15884 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015885 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015886
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015887 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015888}
15889
15890/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015891 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015892 * @ctxt: the schema parser context
15893 * @type: the complex type definition
15894 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015895 *.(4.6) Constraints on Complex Type Definition Schema Components
15896 * Schema Component Constraint:
15897 * Complex Type Definition Properties Correct (ct-props-correct)
15898 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000015899 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015900 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020015901 * error code if not and -1 if an internal error occurred.
William M. Brack2f2a6632004-08-20 23:09:47 +000015902 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015903static int
15904xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15905 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015906{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015907 /*
15908 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15909 *
15910 * SPEC (1) "The values of the properties of a complex type definition must
15911 * be as described in the property tableau in The Complex Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010015912 * Schema Component ($3.4.1), modulo the impact of Missing
15913 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015914 */
15915 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015916 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015917 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015918 /*
15919 * SPEC (2) "If the {base type definition} is a simple type definition,
15920 * the {derivation method} must be extension."
15921 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015922 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015923 XML_SCHEMAP_SRC_CT_1,
Daniel Veillarddee23482008-04-11 12:58:43 +000015924 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015925 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015926 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015927 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015928 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015929 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015930 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15931 * definition`. That is, it must be possible to reach the `ur-type
15932 * definition` by repeatedly following the {base type definition}."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015933 *
15934 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015935 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015936 /*
15937 * NOTE that (4) and (5) need the following:
15938 * - attribute uses need to be already inherited (apply attr. prohibitions)
15939 * - attribute group references need to be expanded already
15940 * - simple types need to be typefixed already
Daniel Veillarddee23482008-04-11 12:58:43 +000015941 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015942 if (type->attrUses &&
15943 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15944 {
15945 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15946 xmlSchemaAttributeUsePtr use, tmp;
15947 int i, j, hasId = 0;
15948
15949 for (i = uses->nbItems -1; i >= 0; i--) {
15950 use = uses->items[i];
Daniel Veillarddee23482008-04-11 12:58:43 +000015951
15952 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015953 * SPEC ct-props-correct
15954 * (4) "Two distinct attribute declarations in the
15955 * {attribute uses} must not have identical {name}s and
15956 * {target namespace}s."
15957 */
15958 if (i > 0) {
15959 for (j = i -1; j >= 0; j--) {
15960 tmp = uses->items[j];
15961 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15962 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15963 (WXS_ATTRUSE_DECL_TNS(use) ==
15964 WXS_ATTRUSE_DECL_TNS(tmp)))
15965 {
15966 xmlChar *str = NULL;
15967
15968 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15969 XML_SCHEMAP_AG_PROPS_CORRECT,
15970 NULL, WXS_BASIC_CAST type,
15971 "Duplicate %s",
15972 xmlSchemaGetComponentDesignation(&str, use),
15973 NULL);
15974 FREE_AND_NULL(str);
15975 /*
15976 * Remove the duplicate.
15977 */
15978 if (xmlSchemaItemListRemove(uses, i) == -1)
15979 goto exit_failure;
15980 goto next_use;
15981 }
15982 }
15983 }
15984 /*
15985 * SPEC ct-props-correct
15986 * (5) "Two distinct attribute declarations in the
15987 * {attribute uses} must not have {type definition}s which
15988 * are or are derived from ID."
15989 */
15990 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15991 if (xmlSchemaIsDerivedFromBuiltInType(
15992 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000015993 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015994 if (hasId) {
15995 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000015996
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015997 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15998 XML_SCHEMAP_AG_PROPS_CORRECT,
15999 NULL, WXS_BASIC_CAST type,
16000 "There must not exist more than one attribute "
16001 "declaration of type 'xs:ID' "
16002 "(or derived from 'xs:ID'). The %s violates this "
16003 "constraint",
16004 xmlSchemaGetComponentDesignation(&str, use),
16005 NULL);
16006 FREE_AND_NULL(str);
16007 if (xmlSchemaItemListRemove(uses, i) == -1)
16008 goto exit_failure;
16009 }
Daniel Veillarddee23482008-04-11 12:58:43 +000016010
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016011 hasId = 1;
16012 }
16013 }
16014next_use: {}
16015 }
16016 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016017 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016018exit_failure:
16019 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000016020}
16021
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016022static int
16023xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16024 xmlSchemaTypePtr typeB)
16025{
16026 /*
16027 * TODO: This should implement component-identity
16028 * in the future.
16029 */
16030 if ((typeA == NULL) || (typeB == NULL))
16031 return (0);
16032 return (typeA == typeB);
16033}
16034
16035/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016036 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016037 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016038 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016039 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016040 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016041 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016043 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16044 *
16045 * STATUS: completed
16046 *
16047 * Returns 0 if the constraints are satisfied, or 1
16048 * if not.
16049 */
16050static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016051xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016052 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016053 xmlSchemaTypePtr baseType,
16054 int set)
16055{
16056 int equal = xmlSchemaAreEqualTypes(type, baseType);
16057 /* TODO: Error codes. */
16058 /*
16059 * SPEC "For a complex type definition (call it D, for derived)
16060 * to be validly derived from a type definition (call this
16061 * B, for base) given a subset of {extension, restriction}
16062 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016063 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016064 if (! equal) {
16065 /*
16066 * SPEC (1) "If B and D are not the same type definition, then the
16067 * {derivation method} of D must not be in the subset."
16068 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016069 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16070 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016071 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016072 } else {
16073 /*
16074 * SPEC (2.1) "B and D must be the same type definition."
16075 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016076 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016077 }
16078 /*
16079 * SPEC (2.2) "B must be D's {base type definition}."
16080 */
16081 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016082 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016083 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016084 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16085 * definition`."
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016086 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016087 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016088 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016089
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016090 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016091 /*
16092 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16093 * must be validly derived from B given the subset as defined by this
16094 * constraint."
16095 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016096 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016097 baseType, set));
16098 } else {
16099 /*
16100 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16101 * must be validly derived from B given the subset as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016102 * Derivation OK (Simple) ($3.14.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016103 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016104 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016105 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016106 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016107}
16108
16109/**
16110 * xmlSchemaCheckCOSDerivedOK:
16111 * @type: the derived simple type definition
16112 * @baseType: the base type definition
16113 *
16114 * Calls:
16115 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016116 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016117 * Checks wheter @type can be validly derived from @baseType.
16118 *
16119 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016120 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016121static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016122xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016123 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016124 xmlSchemaTypePtr baseType,
16125 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016126{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016127 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016128 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016129 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016130 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016131}
16132
William M. Brack2f2a6632004-08-20 23:09:47 +000016133/**
16134 * xmlSchemaCheckCOSCTExtends:
16135 * @ctxt: the schema parser context
16136 * @type: the complex type definition
16137 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016138 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016139 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 * Derivation Valid (Extension) (cos-ct-extends)
16141 *
16142 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016143 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016144 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016145 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000016146 *
16147 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016148 * error code if not and -1 if an internal error occurred.
William M. Brack2f2a6632004-08-20 23:09:47 +000016149 */
16150static int
16151xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16152 xmlSchemaTypePtr type)
16153{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016154 xmlSchemaTypePtr base = type->baseType;
16155 /*
16156 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16157 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000016158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 /*
16160 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 * then all of the following must be true:"
16162 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016163 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016164 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016165 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016167 */
16168 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16169 xmlSchemaPCustomErr(ctxt,
16170 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016171 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016172 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016173 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016174 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16175 }
Daniel Veillarddee23482008-04-11 12:58:43 +000016176
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016177 /*
16178 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16179 * since they are automatically satisfied through the
16180 * inheriting mechanism.
16181 * Note that even if redefining components, the inheriting mechanism
16182 * is used.
16183 */
16184#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016185 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016186 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016187 * uses}
16188 * of the complex type definition itself, that is, for every attribute
16189 * use in the {attribute uses} of the {base type definition}, there
16190 * must be an attribute use in the {attribute uses} of the complex
16191 * type definition itself whose {attribute declaration} has the same
16192 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016193 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016194 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016195 if (base->attrUses != NULL) {
16196 int i, j, found;
16197 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016198
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016199 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16200 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16201 found = 0;
16202 if (type->attrUses != NULL) {
16203 use = (WXS_LIST_CAST type->attrUses)->items[j];
16204 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16205 {
16206 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16207 WXS_ATTRUSE_DECL_NAME(buse)) &&
16208 (WXS_ATTRUSE_DECL_TNS(use) ==
16209 WXS_ATTRUSE_DECL_TNS(buse)) &&
16210 (WXS_ATTRUSE_TYPEDEF(use) ==
16211 WXS_ATTRUSE_TYPEDEF(buse))
16212 {
16213 found = 1;
16214 break;
16215 }
16216 }
16217 }
16218 if (! found) {
16219 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016220
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016221 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16222 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16223 NULL, WXS_BASIC_CAST type,
Daniel Veillarddee23482008-04-11 12:58:43 +000016224 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016225 * TODO: The report does not indicate that also the
16226 * type needs to be the same.
16227 */
16228 "This type is missing a matching correspondent "
16229 "for its {base type}'s %s in its {attribute uses}",
16230 xmlSchemaGetComponentDesignation(&str,
16231 buse->children),
16232 NULL);
16233 FREE_AND_NULL(str)
16234 }
16235 }
16236 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016237 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16239 * definition must also have one, and the base type definition's
16240 * {attribute wildcard}'s {namespace constraint} must be a subset
16241 * of the complex type definition's {attribute wildcard}'s {namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010016242 * constraint}, as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016243 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016244
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016245 /*
16246 * MAYBE TODO: Enable if ever needed. But this will be needed only
16247 * if created the type via a schema construction API.
16248 */
16249 if (base->attributeWildcard != NULL) {
16250 if (type->attributeWilcard == NULL) {
16251 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016253 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16254 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16255 NULL, type,
16256 "The base %s has an attribute wildcard, "
16257 "but this type is missing an attribute wildcard",
16258 xmlSchemaGetComponentDesignation(&str, base));
16259 FREE_AND_NULL(str)
16260
16261 } else if (xmlSchemaCheckCOSNSSubset(
16262 base->attributeWildcard, type->attributeWildcard))
16263 {
16264 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016265
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016266 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16267 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16268 NULL, type,
16269 "The attribute wildcard is not a valid "
16270 "superset of the one in the base %s",
16271 xmlSchemaGetComponentDesignation(&str, base));
16272 FREE_AND_NULL(str)
16273 }
16274 }
16275#endif
16276 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016277 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016278 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016279 if ((type->contentTypeDef != NULL) &&
16280 (type->contentTypeDef == base->contentTypeDef)) {
16281 /*
16282 * SPEC (1.4.1) "The {content type} of the {base type definition}
16283 * and the {content type} of the complex type definition itself
16284 * must be the same simple type definition"
16285 * PASS
16286 */
16287 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16288 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16289 /*
16290 * SPEC (1.4.2) "The {content type} of both the {base type
16291 * definition} and the complex type definition itself must
16292 * be empty."
16293 * PASS
16294 */
16295 } else {
16296 /*
16297 * SPEC (1.4.3) "All of the following must be true:"
16298 */
16299 if (type->subtypes == NULL) {
16300 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016301 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 * definition itself must specify a particle.
16303 */
16304 xmlSchemaPCustomErr(ctxt,
16305 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016306 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016307 "The content type must specify a particle", NULL);
16308 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16309 }
16310 /*
16311 * SPEC (1.4.3.2) "One of the following must be true:"
16312 */
16313 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16314 /*
16315 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16316 * definition} must be empty.
16317 * PASS
16318 */
16319 } else {
16320 /*
16321 * SPEC (1.4.3.2.2) "All of the following must be true:"
16322 */
16323 if ((type->contentType != base->contentType) ||
16324 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16325 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16326 /*
16327 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16328 * or both must be element-only."
16329 */
16330 xmlSchemaPCustomErr(ctxt,
16331 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016332 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016333 "The content type of both, the type and its base "
16334 "type, must either 'mixed' or 'element-only'", NULL);
16335 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016337 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016338 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016339 * complex type definition must be a `valid extension`
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016340 * of the {base type definition}'s particle, as defined
Jan Pokorný761c9e92013-11-29 23:26:27 +010016341 * in Particle Valid (Extension) ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 *
16343 * NOTE that we won't check "Particle Valid (Extension)",
16344 * since it is ensured by the derivation process in
16345 * xmlSchemaTypeFixup(). We need to implement this when heading
16346 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016347 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 }
16350 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016351 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016352 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016353 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016354 } else {
16355 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016356 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016358 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016359 if (type->contentTypeDef != base) {
16360 /*
16361 * SPEC (2.1) "The {content type} must be the same simple type
16362 * definition."
16363 */
16364 xmlSchemaPCustomErr(ctxt,
16365 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016366 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016367 "The content type must be the simple base type", NULL);
16368 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16369 }
16370 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16371 /*
16372 * SPEC (2.2) "The {final} of the {base type definition} must not
16373 * contain extension"
16374 * NOTE that this is the same as (1.1).
16375 */
16376 xmlSchemaPCustomErr(ctxt,
16377 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016378 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016379 "The 'final' of the base type definition "
16380 "contains 'extension'", NULL);
16381 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016385}
16386
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387/**
16388 * xmlSchemaCheckDerivationOKRestriction:
16389 * @ctxt: the schema parser context
16390 * @type: the complex type definition
16391 *
16392 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16395 *
16396 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016397 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016398 * (5.4.2) ???
16399 *
16400 * ATTENTION:
16401 * In XML Schema 1.1 this will be:
16402 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016403 *
16404 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016405 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016406 */
16407static int
16408xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16409 xmlSchemaTypePtr type)
16410{
16411 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016412
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016413 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016414 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016415 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016416 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016417 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016418 if (! WXS_IS_COMPLEX(base)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000016419 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016420 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16421 type->node, WXS_BASIC_CAST type,
16422 "The base type must be a complex type", NULL, NULL);
16423 return(ctxt->err);
16424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016425 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16426 /*
16427 * SPEC (1) "The {base type definition} must be a complex type
16428 * definition whose {final} does not contain restriction."
16429 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016430 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016431 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16432 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016434 "contains 'restriction'", NULL, NULL);
16435 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016436 }
16437 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016438 * SPEC (2), (3) and (4)
16439 * Those are handled in a separate function, since the
16440 * same constraints are needed for redefinition of
16441 * attribute groups as well.
16442 */
16443 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16444 XML_SCHEMA_ACTION_DERIVE,
16445 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16446 type->attrUses, base->attrUses,
16447 type->attributeWildcard,
16448 base->attributeWildcard) == -1)
16449 {
16450 return(-1);
16451 }
16452 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016453 * SPEC (5) "One of the following must be true:"
16454 */
16455 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16456 /*
16457 * SPEC (5.1) "The {base type definition} must be the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016458 * `ur-type definition`."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016459 * PASS
16460 */
16461 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16462 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16463 /*
16464 * SPEC (5.2.1) "The {content type} of the complex type definition
16465 * must be a simple type definition"
16466 *
16467 * SPEC (5.2.2) "One of the following must be true:"
16468 */
16469 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016470 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16471 {
16472 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016473 /*
16474 * SPEC (5.2.2.1) "The {content type} of the {base type
16475 * definition} must be a simple type definition from which
16476 * the {content type} is validly derived given the empty
Jan Pokorný761c9e92013-11-29 23:26:27 +010016477 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016478 *
16479 * ATTENTION TODO: This seems not needed if the type implicitely
16480 * derived from the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +000016481 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016482 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016483 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16484 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016485 if (err != 0) {
16486 xmlChar *strA = NULL, *strB = NULL;
16487
16488 if (err == -1)
16489 return(-1);
16490 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16491 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492 NULL, WXS_BASIC_CAST type,
16493 "The {content type} %s is not validly derived from the "
16494 "base type's {content type} %s",
16495 xmlSchemaGetComponentDesignation(&strA,
16496 type->contentTypeDef),
16497 xmlSchemaGetComponentDesignation(&strB,
16498 base->contentTypeDef));
16499 FREE_AND_NULL(strA);
16500 FREE_AND_NULL(strB);
16501 return(ctxt->err);
16502 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016503 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16504 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016505 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016506 /*
16507 * SPEC (5.2.2.2) "The {base type definition} must be mixed
Jan Pokorný761c9e92013-11-29 23:26:27 +010016508 * and have a particle which is `emptiable` as defined in
16509 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016510 * PASS
16511 */
16512 } else {
16513 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016514 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16515 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016516 "The content type of the base type must be either "
16517 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016518 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016519 }
16520 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16521 /*
16522 * SPEC (5.3.1) "The {content type} of the complex type itself must
16523 * be empty"
16524 */
16525 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16526 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016527 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 * definition} must also be empty."
16529 * PASS
16530 */
16531 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16532 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16533 xmlSchemaIsParticleEmptiable(
16534 (xmlSchemaParticlePtr) base->subtypes)) {
16535 /*
16536 * SPEC (5.3.2.2) "The {content type} of the {base type
16537 * definition} must be elementOnly or mixed and have a particle
Jan Pokorný761c9e92013-11-29 23:26:27 +010016538 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 * PASS
16540 */
16541 } else {
16542 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016543 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16544 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016545 "The content type of the base type must be either "
16546 "empty or 'mixed' (or 'elements-only') and an emptiable "
16547 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016548 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016549 }
16550 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016551 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016552 /*
16553 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16554 * itself must be element-only"
Daniel Veillarddee23482008-04-11 12:58:43 +000016555 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016556 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016557 /*
16558 * SPEC (5.4.1.2) "The {content type} of the complex type
16559 * definition itself and of the {base type definition} must be
16560 * mixed"
16561 */
16562 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016563 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16564 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016565 "If the content type is 'mixed', then the content type of the "
16566 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016567 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016568 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016569 /*
16570 * SPEC (5.4.2) "The particle of the complex type definition itself
Jan Pokorný761c9e92013-11-29 23:26:27 +010016571 * must be a `valid restriction` of the particle of the {content
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016572 * type} of the {base type definition} as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010016573 * (Restriction) ($3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016574 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016575 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016576 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016577 } else {
16578 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016579 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16580 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016581 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016582 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016583 }
16584 return (0);
16585}
16586
16587/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016588 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016589 * @ctxt: the schema parser context
16590 * @type: the complex type definition
16591 *
16592 * (3.4.6) Constraints on Complex Type Definition Schema Components
16593 *
16594 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016595 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016596 */
16597static int
16598xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16599 xmlSchemaTypePtr type)
16600{
16601 int ret;
16602 /*
16603 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016604 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016605 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16606 if (ret != 0)
16607 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016608 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016609 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16610 else
16611 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16612 return (ret);
16613}
16614
16615/**
16616 * xmlSchemaCheckSRCCT:
16617 * @ctxt: the schema parser context
16618 * @type: the complex type definition
16619 *
16620 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016621 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016622 * Complex Type Definition Representation OK (src-ct)
16623 *
16624 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016625 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016626 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016627static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016628xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016629 xmlSchemaTypePtr type)
16630{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016631 xmlSchemaTypePtr base;
16632 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016633
16634 /*
16635 * TODO: Adjust the error codes here, as I used
16636 * XML_SCHEMAP_SRC_CT_1 only yet.
16637 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016638 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016639 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016640 /*
16641 * 1 If the <complexContent> alternative is chosen, the type definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010016642 * `resolved` to by the `actual value` of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016643 * must be a complex type definition;
16644 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016645 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016646 xmlChar *str = NULL;
16647 xmlSchemaPCustomErr(ctxt,
16648 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016649 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016650 "If using <complexContent>, the base type is expected to be "
16651 "a complex type. The base type '%s' is a simple type",
16652 xmlSchemaFormatQName(&str, base->targetNamespace,
16653 base->name));
16654 FREE_AND_NULL(str)
16655 return (XML_SCHEMAP_SRC_CT_1);
16656 }
16657 } else {
16658 /*
16659 * SPEC
16660 * 2 If the <simpleContent> alternative is chosen, all of the
16661 * following must be true:
Jan Pokorný761c9e92013-11-29 23:26:27 +010016662 * 2.1 The type definition `resolved` to by the `actual value` of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016663 * base [attribute] must be one of the following:
16664 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016665 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016666 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016667 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016668 /*
16669 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016670 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016672 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016673 xmlSchemaPCustomErr(ctxt,
16674 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016675 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016676 "If using <simpleContent> and <restriction>, the base "
16677 "type must be a complex type. The base type '%s' is "
16678 "a simple type",
16679 xmlSchemaFormatQName(&str, base->targetNamespace,
16680 base->name));
16681 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016682 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016683 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016684 } else {
16685 /* Base type is a complex type. */
16686 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16687 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16688 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016689 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016690 * simple type definition;
16691 * PASS
16692 */
16693 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016694 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016695 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016696 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016697 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016698 type->name);
16699 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016700 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016701 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016702 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016703
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016704 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016705 * 2.1.2 only if the <restriction> alternative is also
16706 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016707 * is mixed and a particle emptiable.
16708 */
16709 if (! xmlSchemaIsParticleEmptiable(
16710 (xmlSchemaParticlePtr) base->subtypes)) {
16711 ret = XML_SCHEMAP_SRC_CT_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000016712 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016713 /*
16714 * Attention: at this point the <simpleType> child is in
16715 * ->contentTypeDef (put there during parsing).
Daniel Veillarddee23482008-04-11 12:58:43 +000016716 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016717 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016718 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016719 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016720 * 2.2 If clause 2.1.2 above is satisfied, then there
16721 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016722 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016724 /* TODO: Change error code to ..._SRC_CT_2_2. */
16725 xmlSchemaPCustomErr(ctxt,
16726 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016727 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016728 "A <simpleType> is expected among the children "
16729 "of <restriction>, if <simpleContent> is used and "
16730 "the base type '%s' is a complex type",
16731 xmlSchemaFormatQName(&str, base->targetNamespace,
16732 base->name));
16733 FREE_AND_NULL(str)
16734 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016735 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016736 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016737 ret = XML_SCHEMAP_SRC_CT_1;
16738 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016739 }
16740 if (ret > 0) {
16741 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016742 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016743 xmlSchemaPCustomErr(ctxt,
16744 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016745 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016746 "If <simpleContent> and <restriction> is used, the "
16747 "base type must be a simple type or a complex type with "
16748 "mixed content and particle emptiable. The base type "
16749 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016750 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016751 base->name));
16752 } else {
16753 xmlSchemaPCustomErr(ctxt,
16754 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016755 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016756 "If <simpleContent> and <extension> is used, the "
16757 "base type must be a simple type. The base type '%s' "
16758 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016759 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016760 base->name));
16761 }
16762 FREE_AND_NULL(str)
16763 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016764 }
16765 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016766 * SPEC (3) "The corresponding complex type definition component must
16767 * satisfy the conditions set out in Constraints on Complex Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016768 * Definition Schema Components ($3.4.6);"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016769 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016771 /*
16772 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016773 * above for {attribute wildcard} is satisfied, the intensional
16774 * intersection must be expressible, as defined in Attribute Wildcard
Jan Pokorný761c9e92013-11-29 23:26:27 +010016775 * Intersection ($3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016776 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016777 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016778 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016779}
William M. Brack2f2a6632004-08-20 23:09:47 +000016780
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016781#ifdef ENABLE_PARTICLE_RESTRICTION
16782/**
16783 * xmlSchemaCheckParticleRangeOK:
16784 * @ctxt: the schema parser context
16785 * @type: the complex type definition
16786 *
16787 * (3.9.6) Constraints on Particle Schema Components
16788 * Schema Component Constraint:
16789 * Occurrence Range OK (range-ok)
16790 *
16791 * STATUS: complete
16792 *
16793 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016794 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016795 */
16796static int
16797xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16798 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016799{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016800 if (rmin < bmin)
16801 return (1);
16802 if ((bmax != UNBOUNDED) &&
16803 (rmax > bmax))
16804 return (1);
16805 return (0);
16806}
16807
16808/**
16809 * xmlSchemaCheckRCaseNameAndTypeOK:
16810 * @ctxt: the schema parser context
16811 * @r: the restricting element declaration particle
16812 * @b: the base element declaration particle
16813 *
16814 * (3.9.6) Constraints on Particle Schema Components
16815 * Schema Component Constraint:
16816 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16817 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016818 *
16819 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016820 * MISSING (3.2.3)
16821 * CLARIFY: (3.2.2)
16822 *
16823 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016824 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016825 */
16826static int
16827xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16828 xmlSchemaParticlePtr r,
16829 xmlSchemaParticlePtr b)
16830{
16831 xmlSchemaElementPtr elemR, elemB;
16832
16833 /* TODO: Error codes (rcase-NameAndTypeOK). */
16834 elemR = (xmlSchemaElementPtr) r->children;
16835 elemB = (xmlSchemaElementPtr) b->children;
16836 /*
16837 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16838 * the same."
16839 */
16840 if ((elemR != elemB) &&
16841 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16842 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16843 return (1);
16844 /*
16845 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016846 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016847 */
16848 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16849 b->minOccurs, b->maxOccurs) != 0)
16850 return (1);
16851 /*
16852 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16853 * {scope} are global."
16854 */
16855 if (elemR == elemB)
16856 return (0);
16857 /*
16858 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16859 */
16860 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16861 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16862 return (1);
16863 /*
16864 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16865 * or is not fixed, or R's declaration's {value constraint} is fixed
16866 * with the same value."
16867 */
16868 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16869 ((elemR->value == NULL) ||
16870 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16871 /* TODO: Equality of the initial value or normalized or canonical? */
16872 (! xmlStrEqual(elemR->value, elemB->value))))
16873 return (1);
16874 /*
16875 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16876 * definitions} is a subset of B's declaration's {identity-constraint
16877 * definitions}, if any."
16878 */
16879 if (elemB->idcs != NULL) {
16880 /* TODO */
16881 }
16882 /*
16883 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16884 * superset of B's declaration's {disallowed substitutions}."
16885 */
16886 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16887 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16888 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16889 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16890 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16891 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16892 return (1);
16893 /*
16894 * SPEC (3.2.5) "R's {type definition} is validly derived given
16895 * {extension, list, union} from B's {type definition}"
16896 *
16897 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16898 * set, if the corresponding constraints handle "restriction" and
16899 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016900 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016901 */
16902 {
16903 int set = 0;
16904
16905 set |= SUBSET_EXTENSION;
16906 set |= SUBSET_LIST;
16907 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016908 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016909 elemB->subtypes, set) != 0)
16910 return (1);
16911 }
16912 return (0);
16913}
16914
16915/**
16916 * xmlSchemaCheckRCaseNSCompat:
16917 * @ctxt: the schema parser context
16918 * @r: the restricting element declaration particle
16919 * @b: the base wildcard particle
16920 *
16921 * (3.9.6) Constraints on Particle Schema Components
16922 * Schema Component Constraint:
16923 * Particle Derivation OK (Elt:Any -- NSCompat)
16924 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016925 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016926 * STATUS: complete
16927 *
16928 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016929 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016930 */
16931static int
16932xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16933 xmlSchemaParticlePtr r,
16934 xmlSchemaParticlePtr b)
16935{
16936 /* TODO:Error codes (rcase-NSCompat). */
16937 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016938 * SPEC "For an element declaration particle to be a `valid restriction`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016939 * of a wildcard particle all of the following must be true:"
16940 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010016941 * SPEC (1) "The element declaration's {target namespace} is `valid`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016942 * with respect to the wildcard's {namespace constraint} as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010016943 * Wildcard allows Namespace Name ($3.10.4)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016944 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016945 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016946 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16947 return (1);
16948 /*
16949 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016950 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016951 */
16952 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16953 b->minOccurs, b->maxOccurs) != 0)
16954 return (1);
16955
16956 return (0);
16957}
16958
16959/**
16960 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16961 * @ctxt: the schema parser context
16962 * @r: the restricting element declaration particle
16963 * @b: the base model group particle
16964 *
16965 * (3.9.6) Constraints on Particle Schema Components
16966 * Schema Component Constraint:
16967 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16968 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016970 * STATUS: TODO
16971 *
16972 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016973 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016974 */
16975static int
16976xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16977 xmlSchemaParticlePtr r,
16978 xmlSchemaParticlePtr b)
16979{
16980 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16981 TODO
16982 return (0);
16983}
16984
16985/**
16986 * xmlSchemaCheckRCaseNSSubset:
16987 * @ctxt: the schema parser context
16988 * @r: the restricting wildcard particle
16989 * @b: the base wildcard particle
16990 *
16991 * (3.9.6) Constraints on Particle Schema Components
16992 * Schema Component Constraint:
16993 * Particle Derivation OK (Any:Any -- NSSubset)
16994 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016995 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016996 * STATUS: complete
16997 *
16998 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016999 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017000 */
17001static int
17002xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17003 xmlSchemaParticlePtr r,
17004 xmlSchemaParticlePtr b,
17005 int isAnyTypeBase)
17006{
17007 /* TODO: Error codes (rcase-NSSubset). */
17008 /*
17009 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017010 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017011 */
17012 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17013 b->minOccurs, b->maxOccurs))
17014 return (1);
17015 /*
17016 * SPEC (2) "R's {namespace constraint} must be an intensional subset
Jan Pokorný761c9e92013-11-29 23:26:27 +010017017 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017018 */
17019 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17020 (xmlSchemaWildcardPtr) b->children))
17021 return (1);
17022 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017023 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17024 * definition`, R's {process contents} must be identical to or stronger
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017025 * than B's {process contents}, where strict is stronger than lax is
17026 * stronger than skip."
17027 */
17028 if (! isAnyTypeBase) {
17029 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17030 ((xmlSchemaWildcardPtr) b->children)->processContents)
17031 return (1);
17032 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017033
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017034 return (0);
17035}
17036
17037/**
17038 * xmlSchemaCheckCOSParticleRestrict:
17039 * @ctxt: the schema parser context
17040 * @type: the complex type definition
17041 *
17042 * (3.9.6) Constraints on Particle Schema Components
17043 * Schema Component Constraint:
17044 * Particle Valid (Restriction) (cos-particle-restrict)
17045 *
17046 * STATUS: TODO
17047 *
17048 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017049 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017050 */
17051static int
17052xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17053 xmlSchemaParticlePtr r,
17054 xmlSchemaParticlePtr b)
17055{
17056 int ret = 0;
17057
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017058 /*part = WXS_TYPE_PARTICLE(type);
17059 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017060 */
17061
17062 TODO
17063
17064 /*
17065 * SPEC (1) "They are the same particle."
17066 */
17067 if (r == b)
17068 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017069
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017070
17071 return (0);
17072}
17073
Daniel Veillard15724252008-08-30 15:01:04 +000017074#if 0
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017075/**
17076 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17077 * @ctxt: the schema parser context
17078 * @r: the model group particle
17079 * @b: the base wildcard particle
17080 *
17081 * (3.9.6) Constraints on Particle Schema Components
17082 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017083 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017084 * NSRecurseCheckCardinality)
17085 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017086 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017087 * STATUS: TODO: subst-groups
17088 *
17089 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017090 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017091 */
17092static int
17093xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17094 xmlSchemaParticlePtr r,
17095 xmlSchemaParticlePtr b)
17096{
17097 xmlSchemaParticlePtr part;
17098 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17099 if ((r->children == NULL) || (r->children->children == NULL))
17100 return (-1);
17101 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017102 * SPEC "For a group particle to be a `valid restriction` of a
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017103 * wildcard particle..."
17104 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010017105 * SPEC (1) "Every member of the {particles} of the group is a `valid
17106 * restriction` of the wildcard as defined by
17107 * Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017108 */
17109 part = (xmlSchemaParticlePtr) r->children->children;
17110 do {
17111 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17112 return (1);
17113 part = (xmlSchemaParticlePtr) part->next;
17114 } while (part != NULL);
17115 /*
17116 * SPEC (2) "The effective total range of the group [...] is a
17117 * valid restriction of B's occurrence range as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010017118 * Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017119 */
17120 if (xmlSchemaCheckParticleRangeOK(
17121 xmlSchemaGetParticleTotalRangeMin(r),
17122 xmlSchemaGetParticleTotalRangeMax(r),
17123 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017124 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017125 return (0);
17126}
Daniel Veillard15724252008-08-30 15:01:04 +000017127#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017128
17129/**
17130 * xmlSchemaCheckRCaseRecurse:
17131 * @ctxt: the schema parser context
17132 * @r: the <all> or <sequence> model group particle
17133 * @b: the base <all> or <sequence> model group particle
17134 *
17135 * (3.9.6) Constraints on Particle Schema Components
17136 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017137 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017138 Recurse)
17139 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017140 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017141 * STATUS: ?
17142 * TODO: subst-groups
17143 *
17144 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017145 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017146 */
17147static int
17148xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17149 xmlSchemaParticlePtr r,
17150 xmlSchemaParticlePtr b)
17151{
17152 /* xmlSchemaParticlePtr part; */
17153 /* TODO: Error codes (rcase-Recurse). */
17154 if ((r->children == NULL) || (b->children == NULL) ||
17155 (r->children->type != b->children->type))
17156 return (-1);
17157 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017158 * SPEC "For an all or sequence group particle to be a `valid
17159 * restriction` of another group particle with the same {compositor}..."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017160 *
17161 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017162 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017163 */
17164 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17165 b->minOccurs, b->maxOccurs))
17166 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017167
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017168
17169 return (0);
17170}
17171
17172#endif
17173
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017174#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17175 xmlSchemaPCustomErrExt(pctxt, \
17176 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017177 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017178 "It is an error for both '%s' and '%s' to be specified on the "\
17179 "same type definition", \
17180 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17181 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17182
17183#define FACET_RESTR_ERR(fac1, msg) \
17184 xmlSchemaPCustomErr(pctxt, \
17185 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017186 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017187 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017188
17189#define FACET_RESTR_FIXED_ERR(fac) \
17190 xmlSchemaPCustomErr(pctxt, \
17191 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017192 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017193 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017194 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017195
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017196static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017197xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17198 xmlSchemaFacetPtr facet1,
17199 xmlSchemaFacetPtr facet2,
17200 int lessGreater,
17201 int orEqual,
17202 int ofBase)
17203{
17204 xmlChar *msg = NULL;
17205
17206 msg = xmlStrdup(BAD_CAST "'");
17207 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17208 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17209 if (lessGreater == 0)
17210 msg = xmlStrcat(msg, BAD_CAST " equal to");
17211 if (lessGreater == 1)
17212 msg = xmlStrcat(msg, BAD_CAST " greater than");
17213 else
17214 msg = xmlStrcat(msg, BAD_CAST " less than");
17215
17216 if (orEqual)
17217 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17218 msg = xmlStrcat(msg, BAD_CAST " '");
17219 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17220 if (ofBase)
17221 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17222 else
17223 msg = xmlStrcat(msg, BAD_CAST "'");
17224
17225 xmlSchemaPCustomErr(pctxt,
17226 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017227 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017228 (const char *) msg, NULL);
17229
17230 if (msg != NULL)
17231 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017232}
17233
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017234/*
17235* xmlSchemaDeriveAndValidateFacets:
17236*
17237* Schema Component Constraint: Simple Type Restriction (Facets)
17238* (st-restrict-facets)
17239*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017240static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017241xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17242 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017243{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017244 xmlSchemaTypePtr base = type->baseType;
17245 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017246 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017247 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17248 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17249 fmininc = NULL, fmaxinc = NULL,
17250 fminexc = NULL, fmaxexc = NULL,
17251 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17252 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17253 bfmininc = NULL, bfmaxinc = NULL,
17254 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017255 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017256
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017257 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017258 * SPEC st-restrict-facets 1:
Daniel Veillarddee23482008-04-11 12:58:43 +000017259 * "The {variety} of R is the same as that of B."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017260 */
17261 /*
17262 * SPEC st-restrict-facets 2:
17263 * "If {variety} is atomic, the {primitive type definition}
17264 * of R is the same as that of B."
17265 *
17266 * NOTE: we leave 1 & 2 out for now, since this will be
17267 * satisfied by the derivation process.
17268 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17269 */
17270 /*
17271 * SPEC st-restrict-facets 3:
17272 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017273 * of B, eliminating duplicates. To eliminate duplicates,
17274 * when a facet of the same kind occurs in both S and the
17275 * {facets} of B, the one in the {facets} of B is not
17276 * included, with the exception of enumeration and pattern
17277 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017278 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017281 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17282 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017283
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017284 last = type->facetSet;
17285 if (last != NULL)
17286 while (last->next != NULL)
17287 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017288
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017289 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17290 facet = cur->facet;
17291 switch (facet->type) {
17292 case XML_SCHEMA_FACET_LENGTH:
17293 flength = facet; break;
17294 case XML_SCHEMA_FACET_MINLENGTH:
17295 fminlen = facet; break;
17296 case XML_SCHEMA_FACET_MININCLUSIVE:
17297 fmininc = facet; break;
17298 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17299 fminexc = facet; break;
17300 case XML_SCHEMA_FACET_MAXLENGTH:
17301 fmaxlen = facet; break;
17302 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17303 fmaxinc = facet; break;
17304 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17305 fmaxexc = facet; break;
17306 case XML_SCHEMA_FACET_TOTALDIGITS:
17307 ftotdig = facet; break;
17308 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17309 ffracdig = facet; break;
17310 default:
17311 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017312 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017313 }
17314 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17315 facet = cur->facet;
17316 switch (facet->type) {
17317 case XML_SCHEMA_FACET_LENGTH:
17318 bflength = facet; break;
17319 case XML_SCHEMA_FACET_MINLENGTH:
17320 bfminlen = facet; break;
17321 case XML_SCHEMA_FACET_MININCLUSIVE:
17322 bfmininc = facet; break;
17323 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17324 bfminexc = facet; break;
17325 case XML_SCHEMA_FACET_MAXLENGTH:
17326 bfmaxlen = facet; break;
17327 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17328 bfmaxinc = facet; break;
17329 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17330 bfmaxexc = facet; break;
17331 case XML_SCHEMA_FACET_TOTALDIGITS:
17332 bftotdig = facet; break;
17333 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17334 bffracdig = facet; break;
17335 default:
17336 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017337 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017338 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017339 /*
17340 * length and minLength or maxLength (2.2) + (3.2)
17341 */
17342 if (flength && (fminlen || fmaxlen)) {
17343 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17344 "either of 'minLength' or 'maxLength' to be specified on "
17345 "the same type definition")
17346 }
17347 /*
17348 * Mutual exclusions in the same derivation step.
17349 */
17350 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017351 /*
17352 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017353 */
17354 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17355 }
17356 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017357 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017358 * SCC "minInclusive and minExclusive"
17359 */
17360 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017361 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017362
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017363 if (flength && bflength) {
17364 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017365 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017366 * The values have to be equal.
17367 */
17368 res = xmlSchemaCompareValues(flength->val, bflength->val);
17369 if (res == -2)
17370 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017371 if (res != 0)
17372 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17373 if ((res != 0) && (bflength->fixed)) {
17374 FACET_RESTR_FIXED_ERR(flength)
17375 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017376
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017377 }
17378 if (fminlen && bfminlen) {
17379 /*
17380 * SCC "minLength valid restriction"
17381 * minLength >= BASE minLength
17382 */
17383 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17384 if (res == -2)
17385 goto internal_error;
17386 if (res == -1)
17387 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17388 if ((res != 0) && (bfminlen->fixed)) {
17389 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017390 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017391 }
17392 if (fmaxlen && bfmaxlen) {
17393 /*
17394 * SCC "maxLength valid restriction"
17395 * maxLength <= BASE minLength
17396 */
17397 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17398 if (res == -2)
17399 goto internal_error;
17400 if (res == 1)
17401 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17402 if ((res != 0) && (bfmaxlen->fixed)) {
17403 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017404 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017405 }
17406 /*
17407 * SCC "length and minLength or maxLength"
17408 */
17409 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017410 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017411 if (flength) {
17412 if (! fminlen)
Miroslav Bajtos8f58f892009-08-07 17:22:12 +020017413 fminlen = bfminlen;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017414 if (fminlen) {
17415 /* (1.1) length >= minLength */
17416 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17417 if (res == -2)
17418 goto internal_error;
17419 if (res == -1)
17420 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17421 }
17422 if (! fmaxlen)
17423 fmaxlen = bfmaxlen;
17424 if (fmaxlen) {
17425 /* (2.1) length <= maxLength */
17426 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17427 if (res == -2)
17428 goto internal_error;
17429 if (res == 1)
17430 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17431 }
17432 }
17433 if (fmaxinc) {
17434 /*
17435 * "maxInclusive"
17436 */
17437 if (fmininc) {
17438 /* SCC "maxInclusive >= minInclusive" */
17439 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17440 if (res == -2)
17441 goto internal_error;
17442 if (res == -1) {
17443 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17444 }
17445 }
17446 /*
17447 * SCC "maxInclusive valid restriction"
17448 */
17449 if (bfmaxinc) {
17450 /* maxInclusive <= BASE maxInclusive */
17451 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17452 if (res == -2)
17453 goto internal_error;
17454 if (res == 1)
17455 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17456 if ((res != 0) && (bfmaxinc->fixed)) {
17457 FACET_RESTR_FIXED_ERR(fmaxinc)
17458 }
17459 }
17460 if (bfmaxexc) {
17461 /* maxInclusive < BASE maxExclusive */
17462 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17463 if (res == -2)
17464 goto internal_error;
17465 if (res != -1) {
17466 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17467 }
17468 }
17469 if (bfmininc) {
17470 /* maxInclusive >= BASE minInclusive */
17471 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17472 if (res == -2)
17473 goto internal_error;
17474 if (res == -1) {
17475 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17476 }
17477 }
17478 if (bfminexc) {
17479 /* maxInclusive > BASE minExclusive */
17480 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17481 if (res == -2)
17482 goto internal_error;
17483 if (res != 1) {
17484 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017486 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017487 }
17488 if (fmaxexc) {
17489 /*
17490 * "maxExclusive >= minExclusive"
17491 */
17492 if (fminexc) {
17493 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17494 if (res == -2)
17495 goto internal_error;
17496 if (res == -1) {
17497 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17498 }
17499 }
17500 /*
17501 * "maxExclusive valid restriction"
17502 */
17503 if (bfmaxexc) {
17504 /* maxExclusive <= BASE maxExclusive */
17505 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17506 if (res == -2)
17507 goto internal_error;
17508 if (res == 1) {
17509 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17510 }
17511 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017512 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017513 }
17514 }
17515 if (bfmaxinc) {
17516 /* maxExclusive <= BASE maxInclusive */
17517 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17518 if (res == -2)
17519 goto internal_error;
17520 if (res == 1) {
17521 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17522 }
17523 }
17524 if (bfmininc) {
17525 /* maxExclusive > BASE minInclusive */
17526 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17527 if (res == -2)
17528 goto internal_error;
17529 if (res != 1) {
17530 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17531 }
17532 }
17533 if (bfminexc) {
17534 /* maxExclusive > BASE minExclusive */
17535 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17536 if (res == -2)
17537 goto internal_error;
17538 if (res != 1) {
17539 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17540 }
17541 }
17542 }
17543 if (fminexc) {
17544 /*
17545 * "minExclusive < maxInclusive"
17546 */
17547 if (fmaxinc) {
17548 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17549 if (res == -2)
17550 goto internal_error;
17551 if (res != -1) {
17552 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17553 }
17554 }
17555 /*
17556 * "minExclusive valid restriction"
17557 */
17558 if (bfminexc) {
17559 /* minExclusive >= BASE minExclusive */
17560 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17561 if (res == -2)
17562 goto internal_error;
17563 if (res == -1) {
17564 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17565 }
17566 if ((res != 0) && (bfminexc->fixed)) {
17567 FACET_RESTR_FIXED_ERR(fminexc)
17568 }
17569 }
17570 if (bfmaxinc) {
17571 /* minExclusive <= BASE maxInclusive */
17572 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17573 if (res == -2)
17574 goto internal_error;
17575 if (res == 1) {
17576 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17577 }
17578 }
17579 if (bfmininc) {
17580 /* minExclusive >= BASE minInclusive */
17581 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17582 if (res == -2)
17583 goto internal_error;
17584 if (res == -1) {
17585 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17586 }
17587 }
17588 if (bfmaxexc) {
17589 /* minExclusive < BASE maxExclusive */
17590 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17591 if (res == -2)
17592 goto internal_error;
17593 if (res != -1) {
17594 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17595 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017596 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017597 }
17598 if (fmininc) {
17599 /*
17600 * "minInclusive < maxExclusive"
17601 */
17602 if (fmaxexc) {
17603 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17604 if (res == -2)
17605 goto internal_error;
17606 if (res != -1) {
17607 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17608 }
17609 }
17610 /*
17611 * "minExclusive valid restriction"
17612 */
17613 if (bfmininc) {
17614 /* minInclusive >= BASE minInclusive */
17615 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17616 if (res == -2)
17617 goto internal_error;
17618 if (res == -1) {
17619 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17620 }
17621 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017622 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017623 }
17624 }
17625 if (bfmaxinc) {
17626 /* minInclusive <= BASE maxInclusive */
17627 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17628 if (res == -2)
17629 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017630 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017631 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17632 }
17633 }
17634 if (bfminexc) {
17635 /* minInclusive > BASE minExclusive */
17636 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17637 if (res == -2)
17638 goto internal_error;
17639 if (res != 1)
17640 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17641 }
17642 if (bfmaxexc) {
17643 /* minInclusive < BASE maxExclusive */
17644 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17645 if (res == -2)
17646 goto internal_error;
17647 if (res != -1)
17648 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17649 }
17650 }
17651 if (ftotdig && bftotdig) {
17652 /*
17653 * SCC " totalDigits valid restriction"
17654 * totalDigits <= BASE totalDigits
17655 */
17656 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17657 if (res == -2)
17658 goto internal_error;
17659 if (res == 1)
17660 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17661 -1, 1, 1);
17662 if ((res != 0) && (bftotdig->fixed)) {
17663 FACET_RESTR_FIXED_ERR(ftotdig)
17664 }
17665 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017666 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017667 /*
17668 * SCC "fractionDigits valid restriction"
17669 * fractionDigits <= BASE fractionDigits
17670 */
17671 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17672 if (res == -2)
17673 goto internal_error;
17674 if (res == 1)
17675 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17676 -1, 1, 1);
17677 if ((res != 0) && (bffracdig->fixed)) {
17678 FACET_RESTR_FIXED_ERR(ffracdig)
17679 }
17680 }
17681 /*
17682 * SCC "fractionDigits less than or equal to totalDigits"
17683 */
17684 if (! ftotdig)
17685 ftotdig = bftotdig;
17686 if (! ffracdig)
17687 ffracdig = bffracdig;
17688 if (ftotdig && ffracdig) {
17689 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17690 if (res == -2)
17691 goto internal_error;
17692 if (res == 1)
17693 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17694 -1, 1, 0);
17695 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017696 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017697 * *Enumerations* won' be added here, since only the first set
17698 * of enumerations in the ancestor-or-self axis is used
17699 * for validation, plus we need to use the base type of those
17700 * enumerations for whitespace.
17701 *
17702 * *Patterns*: won't be add here, since they are ORed at
17703 * type level and ANDed at ancestor level. This will
17704 * happed during validation by walking the base axis
17705 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017706 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017707 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17708 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017709 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017710 * Special handling of enumerations and patterns.
17711 * TODO: hmm, they should not appear in the set, so remove this.
17712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017713 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017714 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017715 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017716 /*
17717 * Search for a duplicate facet in the current type.
17718 */
17719 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017720 /* err = 0; */
17721 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017722 while (link != NULL) {
17723 facet = link->facet;
17724 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017725 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017726 case XML_SCHEMA_FACET_WHITESPACE:
17727 /*
17728 * The whitespace must be stronger.
17729 */
17730 if (facet->whitespace < bfacet->whitespace) {
Rob Richardsc6947bb2008-06-29 15:04:41 +000017731 FACET_RESTR_ERR(facet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017732 "The 'whitespace' value has to be equal to "
17733 "or stronger than the 'whitespace' value of "
17734 "the base type")
17735 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017736 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017737 (facet->whitespace != bfacet->whitespace)) {
17738 FACET_RESTR_FIXED_ERR(facet)
17739 }
17740 break;
17741 default:
17742 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017743 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017744 /* Duplicate found. */
17745 break;
17746 }
17747 link = link->next;
17748 }
17749 /*
17750 * If no duplicate was found: add the base types's facet
17751 * to the set.
17752 */
17753 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017754 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017755 xmlMalloc(sizeof(xmlSchemaFacetLink));
17756 if (link == NULL) {
17757 xmlSchemaPErrMemory(pctxt,
17758 "deriving facets, creating a facet link", NULL);
17759 return (-1);
17760 }
17761 link->facet = cur->facet;
17762 link->next = NULL;
17763 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017764 type->facetSet = link;
17765 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017766 last->next = link;
17767 last = link;
17768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017770 }
17771
17772 return (0);
17773internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017774 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017775 "an error occurred");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017776 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017777}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017778
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017779static int
17780xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17781 xmlSchemaTypePtr type)
17782{
17783 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17784 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017785 * The actual value is then formed by replacing any union type
Jan Pokorný761c9e92013-11-29 23:26:27 +010017786 * definition in the `explicit members` with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017787 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017788 *
17789 * TODO: There's a bug entry at
17790 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17791 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017792 */
17793 link = type->memberTypes;
17794 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017795
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017796 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017797 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017798
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017799 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017800 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017801 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017802 link->type = subLink->type;
17803 if (subLink->next != NULL) {
17804 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017805 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017806 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017807 while (subLink != NULL) {
17808 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017809 xmlMalloc(sizeof(xmlSchemaTypeLink));
17810 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017811 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017812 NULL);
17813 return (-1);
17814 }
17815 newLink->type = subLink->type;
17816 prevLink->next = newLink;
17817 prevLink = newLink;
17818 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017819
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017820 subLink = subLink->next;
17821 }
17822 }
17823 }
17824 }
17825 link = link->next;
17826 }
17827 return (0);
17828}
17829
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017830static void
17831xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
Daniel Veillarddee23482008-04-11 12:58:43 +000017832{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017833 int has = 0, needVal = 0, normVal = 0;
17834
17835 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17836 if (has) {
17837 needVal = (type->baseType->flags &
17838 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17839 normVal = (type->baseType->flags &
17840 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17841 }
17842 if (type->facets != NULL) {
17843 xmlSchemaFacetPtr fac;
Daniel Veillarddee23482008-04-11 12:58:43 +000017844
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017845 for (fac = type->facets; fac != NULL; fac = fac->next) {
17846 switch (fac->type) {
17847 case XML_SCHEMA_FACET_WHITESPACE:
17848 break;
17849 case XML_SCHEMA_FACET_PATTERN:
17850 normVal = 1;
17851 has = 1;
17852 break;
17853 case XML_SCHEMA_FACET_ENUMERATION:
17854 needVal = 1;
17855 normVal = 1;
17856 has = 1;
17857 break;
17858 default:
17859 has = 1;
17860 break;
17861 }
Daniel Veillarddee23482008-04-11 12:58:43 +000017862 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017863 }
17864 if (normVal)
17865 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17866 if (needVal)
17867 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17868 if (has)
17869 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17870
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017871 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017872 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17873 /*
17874 * OPTIMIZE VAL TODO: Some facets need a computed value.
17875 */
17876 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17877 (prim->builtInType != XML_SCHEMAS_STRING)) {
17878 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
Daniel Veillarddee23482008-04-11 12:58:43 +000017879 }
17880 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017881}
17882
17883static int
17884xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17885{
Daniel Veillarddee23482008-04-11 12:58:43 +000017886
17887
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017888 /*
17889 * Evaluate the whitespace-facet value.
Daniel Veillarddee23482008-04-11 12:58:43 +000017890 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017891 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017892 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17893 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017894 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017895 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000017896
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017897 if (type->facetSet != NULL) {
17898 xmlSchemaFacetLinkPtr lin;
17899
17900 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17901 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17902 switch (lin->facet->whitespace) {
17903 case XML_SCHEMAS_FACET_PRESERVE:
17904 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17905 break;
17906 case XML_SCHEMAS_FACET_REPLACE:
17907 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17908 break;
17909 case XML_SCHEMAS_FACET_COLLAPSE:
17910 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17911 break;
17912 default:
17913 return (-1);
17914 }
17915 return (0);
17916 }
17917 }
17918 }
17919 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017920 * For all `atomic` datatypes other than string (and types `derived`
17921 * by `restriction` from it) the value of whiteSpace is fixed to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017922 * collapse
17923 */
17924 {
17925 xmlSchemaTypePtr anc;
17926
Daniel Veillarddee23482008-04-11 12:58:43 +000017927 for (anc = type->baseType; anc != NULL &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017928 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17929 anc = anc->baseType) {
17930
17931 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillarddee23482008-04-11 12:58:43 +000017932 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017933 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17934
17935 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
Daniel Veillarddee23482008-04-11 12:58:43 +000017936 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017937 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17938
17939 } else
17940 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17941 break;
17942 }
17943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017944 }
17945 return (0);
17946}
17947
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017948static int
17949xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17950 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000017951{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017952 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17953 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017954 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017955 return(0);
17956 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017957
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017958 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017959 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017960 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017961 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017962 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017963 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017964 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017965 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017966 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017967 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017968 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017969 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017970 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017971 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017972 * Corresponds to <simpleType><union>...
Daniel Veillarddee23482008-04-11 12:58:43 +000017973 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017974 if (type->memberTypes == NULL) {
17975 /*
17976 * This one is really needed, so get out.
17977 */
17978 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17979 "union type has no member-types assigned");
17980 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000017981 }
17982 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017983 /*
17984 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017985 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017986 if (type->baseType == NULL) {
17987 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17988 "type has no base-type assigned");
17989 return(-1);
17990 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017991 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017992 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17993 return(-1);
17994 /*
17995 * Variety
17996 * If the <restriction> alternative is chosen, then the
17997 * {variety} of the {base type definition}.
17998 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017999 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018000 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018001 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018002 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018003 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018004 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018005 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018006 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018007 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018008 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018010 * NOTE that we won't assign the memberTypes of the base,
18011 * since this will make trouble when freeing them; we will
18012 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018013 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018014 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018015 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018016 return(0);
18017}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018018
Daniel Veillard8651f532002-04-17 09:06:27 +000018019#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000018020static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018021xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18022 xmlSchemaTypePtr type)
18023{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018024 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018025 xmlGenericError(xmlGenericErrorContext,
18026 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018027 type->node->doc->URL,
18028 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018029 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018030 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018031 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018032 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018033 switch (type->contentType) {
18034 case XML_SCHEMA_CONTENT_SIMPLE:
18035 xmlGenericError(xmlGenericErrorContext, "simple\n");
18036 break;
18037 case XML_SCHEMA_CONTENT_ELEMENTS:
18038 xmlGenericError(xmlGenericErrorContext, "elements\n");
18039 break;
18040 case XML_SCHEMA_CONTENT_UNKNOWN:
18041 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18042 break;
18043 case XML_SCHEMA_CONTENT_EMPTY:
18044 xmlGenericError(xmlGenericErrorContext, "empty\n");
18045 break;
18046 case XML_SCHEMA_CONTENT_MIXED:
18047 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018048 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018049 xmlGenericError(xmlGenericErrorContext,
18050 "mixed as emptiable particle\n");
18051 else
18052 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18053 break;
18054 /* Removed, since not used. */
18055 /*
18056 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18057 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18058 break;
18059 */
18060 case XML_SCHEMA_CONTENT_BASIC:
18061 xmlGenericError(xmlGenericErrorContext, "basic\n");
18062 break;
18063 default:
18064 xmlGenericError(xmlGenericErrorContext,
18065 "not registered !!!\n");
18066 break;
18067 }
Daniel Veillard8651f532002-04-17 09:06:27 +000018068 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018069}
Daniel Veillard8651f532002-04-17 09:06:27 +000018070#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018071
18072/*
18073* 3.14.6 Constraints on Simple Type Definition Schema Components
18074*/
18075static int
18076xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18077 xmlSchemaTypePtr type)
18078{
18079 int res, olderrs = pctxt->nberrors;
18080
18081 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18082 return(-1);
18083
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018084 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018085 return(0);
18086
18087 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18088 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18089
18090 if (type->baseType == NULL) {
18091 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18092 "missing baseType");
18093 goto exit_failure;
18094 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018095 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018096 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000018097 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018098 * If a member type of a union is a union itself, we need to substitute
18099 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018100 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18101 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018102 */
18103 if ((type->memberTypes != NULL) &&
18104 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
Daniel Veillarddee23482008-04-11 12:58:43 +000018105 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018106 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000018107 * SPEC src-simple-type 1
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018108 * "The corresponding simple type definition, if any, must satisfy
18109 * the conditions set out in Constraints on Simple Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010018110 * Schema Components ($3.14.6)."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018111 */
18112 /*
18113 * Schema Component Constraint: Simple Type Definition Properties Correct
18114 * (st-props-correct)
18115 */
18116 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18117 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018118 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018119 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18120 * (cos-st-restricts)
18121 */
18122 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18123 HFAILURE HERROR
18124 /*
18125 * TODO: Removed the error report, since it got annoying to get an
18126 * extra error report, if anything failed until now.
18127 * Enable this if needed.
18128 *
18129 * xmlSchemaPErr(ctxt, type->node,
18130 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18131 * "Simple type '%s' does not satisfy the constraints "
18132 * "on simple type definitions.\n",
18133 * type->name, NULL);
18134 */
18135 /*
18136 * Schema Component Constraint: Simple Type Restriction (Facets)
18137 * (st-restrict-facets)
18138 */
18139 res = xmlSchemaCheckFacetValues(type, pctxt);
18140 HFAILURE HERROR
18141 if ((type->facetSet != NULL) ||
18142 (type->baseType->facetSet != NULL)) {
18143 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18144 HFAILURE HERROR
18145 }
18146 /*
18147 * Whitespace value.
18148 */
18149 res = xmlSchemaTypeFixupWhitespace(type);
18150 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018151 xmlSchemaTypeFixupOptimFacets(type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018152
18153exit_error:
18154#ifdef DEBUG_TYPE
18155 xmlSchemaDebugFixedType(pctxt, type);
18156#endif
18157 if (olderrs != pctxt->nberrors)
18158 return(pctxt->err);
18159 return(0);
18160
18161exit_failure:
18162#ifdef DEBUG_TYPE
18163 xmlSchemaDebugFixedType(pctxt, type);
18164#endif
18165 return(-1);
18166}
18167
18168static int
18169xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18170 xmlSchemaTypePtr type)
18171{
18172 int res = 0, olderrs = pctxt->nberrors;
18173 xmlSchemaTypePtr baseType = type->baseType;
18174
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018175 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018176 return(0);
18177 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18178 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018179 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018180 "missing baseType");
18181 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018182 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018183 /*
18184 * Fixup the base type.
18185 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018186 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018187 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018188 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18189 /*
18190 * Skip fixup if the base type is invalid.
18191 * TODO: Generate a warning!
18192 */
18193 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000018194 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018195 /*
18196 * This basically checks if the base type can be derived.
18197 */
18198 res = xmlSchemaCheckSRCCT(pctxt, type);
Daniel Veillarddee23482008-04-11 12:58:43 +000018199 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018200 /*
18201 * Fixup the content type.
18202 */
18203 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18204 /*
18205 * Corresponds to <complexType><simpleContent>...
18206 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018207 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018208 (baseType->contentTypeDef != NULL) &&
18209 (WXS_IS_RESTRICTION(type))) {
18210 xmlSchemaTypePtr contentBase, content;
18211#ifdef ENABLE_NAMED_LOCALS
18212 char buf[30];
18213 const xmlChar *tmpname;
18214#endif
18215 /*
18216 * SPEC (1) If <restriction> + base type is <complexType>,
18217 * "whose own {content type} is a simple type..."
18218 */
18219 if (type->contentTypeDef != NULL) {
18220 /*
18221 * SPEC (1.1) "the simple type definition corresponding to the
18222 * <simpleType> among the [children] of <restriction> if there
18223 * is one;"
18224 * Note that this "<simpleType> among the [children]" was put
18225 * into ->contentTypeDef during parsing.
18226 */
18227 contentBase = type->contentTypeDef;
18228 type->contentTypeDef = NULL;
18229 } else {
18230 /*
18231 * (1.2) "...otherwise (<restriction> has no <simpleType>
18232 * among its [children]), the simple type definition which
18233 * is the {content type} of the ... base type."
18234 */
18235 contentBase = baseType->contentTypeDef;
18236 }
18237 /*
18238 * SPEC
18239 * "... a simple type definition which restricts the simple
18240 * type definition identified in clause 1.1 or clause 1.2
18241 * with a set of facet components"
18242 *
18243 * Create the anonymous simple type, which will be the content
18244 * type of the complex type.
18245 */
18246#ifdef ENABLE_NAMED_LOCALS
18247 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18248 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018249 content = xmlSchemaAddType(pctxt, pctxt->schema,
18250 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018251 type->node, 0);
18252#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018253 content = xmlSchemaAddType(pctxt, pctxt->schema,
18254 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018255 type->node, 0);
18256#endif
18257 if (content == NULL)
18258 goto exit_failure;
18259 /*
18260 * We will use the same node as for the <complexType>
18261 * to have it somehow anchored in the schema doc.
18262 */
18263 content->type = XML_SCHEMA_TYPE_SIMPLE;
18264 content->baseType = contentBase;
18265 /*
18266 * Move the facets, previously anchored on the
18267 * complexType during parsing.
18268 */
18269 content->facets = type->facets;
18270 type->facets = NULL;
18271 content->facetSet = type->facetSet;
18272 type->facetSet = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000018273
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018274 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018275 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018276 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018277 /*
18278 * Fixup the newly created type. We don't need to check
18279 * for circularity here.
18280 */
18281 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018282 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018283 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018284 HFAILURE HERROR
18285
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018286 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018287 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18288 (WXS_IS_RESTRICTION(type))) {
18289 /*
18290 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18291 * an emptiable particle, then a simple type definition which
18292 * restricts the <restriction>'s <simpleType> child.
18293 */
18294 if ((type->contentTypeDef == NULL) ||
18295 (type->contentTypeDef->baseType == NULL)) {
18296 /*
18297 * TODO: Check if this ever happens.
18298 */
18299 xmlSchemaPCustomErr(pctxt,
18300 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018301 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018302 "Internal error: xmlSchemaTypeFixup, "
18303 "complex type '%s': the <simpleContent><restriction> "
18304 "is missing a <simpleType> child, but was not catched "
18305 "by xmlSchemaCheckSRCCT()", type->name);
18306 goto exit_failure;
18307 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018308 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018309 /*
18310 * SPEC (3) If <extension> + base is <complexType> with
18311 * <simpleType> content, "...then the {content type} of that
18312 * complex type definition"
18313 */
18314 if (baseType->contentTypeDef == NULL) {
18315 /*
18316 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18317 * should have catched this already.
18318 */
18319 xmlSchemaPCustomErr(pctxt,
18320 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018321 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018322 "Internal error: xmlSchemaTypeFixup, "
18323 "complex type '%s': the <extension>ed base type is "
18324 "a complex type with no simple content type",
18325 type->name);
18326 goto exit_failure;
18327 }
18328 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018329 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018330 /*
18331 * SPEC (4) <extension> + base is <simpleType>
18332 * "... then that simple type definition"
18333 */
18334 type->contentTypeDef = baseType;
18335 } else {
18336 /*
18337 * TODO: Check if this ever happens.
18338 */
18339 xmlSchemaPCustomErr(pctxt,
18340 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018341 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018342 "Internal error: xmlSchemaTypeFixup, "
18343 "complex type '%s' with <simpleContent>: unhandled "
18344 "derivation case", type->name);
18345 goto exit_failure;
18346 }
18347 } else {
18348 int dummySequence = 0;
18349 xmlSchemaParticlePtr particle =
18350 (xmlSchemaParticlePtr) type->subtypes;
18351 /*
18352 * Corresponds to <complexType><complexContent>...
18353 *
18354 * NOTE that the effective mixed was already set during parsing of
18355 * <complexType> and <complexContent>; its flag value is
18356 * XML_SCHEMAS_TYPE_MIXED.
18357 *
18358 * Compute the "effective content":
18359 * (2.1.1) + (2.1.2) + (2.1.3)
18360 */
18361 if ((particle == NULL) ||
18362 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18363 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18364 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18365 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18366 (particle->minOccurs == 0))) &&
18367 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18368 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18369 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018370 * SPEC (2.1.4) "If the `effective mixed` is true, then
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018371 * a particle whose properties are as follows:..."
18372 *
18373 * Empty sequence model group with
18374 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18375 * NOTE that we sill assign it the <complexType> node to
18376 * somehow anchor it in the doc.
18377 */
18378 if ((particle == NULL) ||
18379 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18380 /*
18381 * Create the particle.
18382 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018383 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018384 type->node, 1, 1);
18385 if (particle == NULL)
18386 goto exit_failure;
18387 /*
18388 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018389 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018390 particle->children = (xmlSchemaTreeItemPtr)
18391 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18392 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18393 if (particle->children == NULL)
18394 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018395
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018396 type->subtypes = (xmlSchemaTypePtr) particle;
18397 }
18398 dummySequence = 1;
18399 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18400 } else {
18401 /*
18402 * SPEC (2.1.5) "otherwise empty"
18403 */
18404 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18405 }
18406 } else {
18407 /*
18408 * SPEC (2.2) "otherwise the particle corresponding to the
18409 * <all>, <choice>, <group> or <sequence> among the
18410 * [children]."
18411 */
18412 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18413 }
18414 /*
18415 * Compute the "content type".
18416 */
18417 if (WXS_IS_RESTRICTION(type)) {
18418 /*
18419 * SPEC (3.1) "If <restriction>..."
18420 * (3.1.1) + (3.1.2) */
18421 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18422 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18423 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18424 }
18425 } else {
18426 /*
18427 * SPEC (3.2) "If <extension>..."
18428 */
18429 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18430 /*
18431 * SPEC (3.2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010018432 * "If the `effective content` is empty, then the
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018433 * {content type} of the [...] base ..."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018434 */
18435 type->contentType = baseType->contentType;
18436 type->subtypes = baseType->subtypes;
18437 /*
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018438 * Fixes bug #347316:
18439 * This is the case when the base type has a simple
18440 * type definition as content.
18441 */
18442 type->contentTypeDef = baseType->contentTypeDef;
18443 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018444 * NOTE that the effective mixed is ignored here.
18445 */
18446 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18447 /*
18448 * SPEC (3.2.2)
18449 */
18450 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18451 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18452 } else {
18453 /*
18454 * SPEC (3.2.3)
18455 */
18456 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18457 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18458 /*
18459 * "A model group whose {compositor} is sequence and whose
18460 * {particles} are..."
18461 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018462 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18463 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18464 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18465 XML_SCHEMA_TYPE_ALL))
18466 {
18467 /*
18468 * SPEC cos-all-limited (1)
18469 */
18470 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18471 /* TODO: error code */
18472 XML_SCHEMAP_COS_ALL_LIMITED,
18473 WXS_ITEM_NODE(type), NULL,
18474 "The type has an 'all' model group in its "
18475 "{content type} and thus cannot be derived from "
18476 "a non-empty type, since this would produce a "
18477 "'sequence' model group containing the 'all' "
18478 "model group; 'all' model groups are not "
18479 "allowed to appear inside other model groups",
18480 NULL, NULL);
18481
18482 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18483 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18484 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18485 XML_SCHEMA_TYPE_ALL))
18486 {
18487 /*
18488 * SPEC cos-all-limited (1)
18489 */
18490 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18491 /* TODO: error code */
18492 XML_SCHEMAP_COS_ALL_LIMITED,
18493 WXS_ITEM_NODE(type), NULL,
18494 "A type cannot be derived by extension from a type "
18495 "which has an 'all' model group in its "
18496 "{content type}, since this would produce a "
18497 "'sequence' model group containing the 'all' "
18498 "model group; 'all' model groups are not "
18499 "allowed to appear inside other model groups",
18500 NULL, NULL);
18501
18502 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018503 xmlSchemaTreeItemPtr effectiveContent =
18504 (xmlSchemaTreeItemPtr) type->subtypes;
18505 /*
18506 * Create the particle.
18507 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018508 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018509 type->node, 1, 1);
18510 if (particle == NULL)
18511 goto exit_failure;
18512 /*
18513 * Create the "sequence" model group.
18514 */
18515 particle->children = (xmlSchemaTreeItemPtr)
18516 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18517 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18518 if (particle->children == NULL)
18519 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018520 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018521 /*
18522 * SPEC "the particle of the {content type} of
18523 * the ... base ..."
18524 * Create a duplicate of the base type's particle
18525 * and assign its "term" to it.
18526 */
18527 particle->children->children =
18528 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018529 type->node,
Remi Gacogne4609e6c2012-05-11 15:31:05 +080018530 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18531 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018532 if (particle->children->children == NULL)
18533 goto exit_failure;
18534 particle = (xmlSchemaParticlePtr)
18535 particle->children->children;
18536 particle->children =
18537 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18538 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018539 * SPEC "followed by the `effective content`."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018540 */
18541 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018542 /*
18543 * This all will result in:
18544 * new-particle
18545 * --> new-sequence(
18546 * new-particle
18547 * --> base-model,
18548 * this-particle
18549 * --> this-model
18550 * )
18551 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018552 } else {
18553 /*
18554 * This is the case when there is already an empty
18555 * <sequence> with minOccurs==maxOccurs==1.
18556 * Just add the base types's content type.
18557 * NOTE that, although we miss to add an intermediate
18558 * <sequence>, this should produce no difference to
18559 * neither the regex compilation of the content model,
18560 * nor to the complex type contraints.
18561 */
18562 particle->children->children =
18563 (xmlSchemaTreeItemPtr) baseType->subtypes;
18564 }
18565 }
18566 }
18567 }
18568 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018569 * Now fixup attribute uses:
18570 * - expand attr. group references
18571 * - intersect attribute wildcards
18572 * - inherit attribute uses of the base type
18573 * - inherit or union attr. wildcards if extending
18574 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018575 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018576 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018577 HFAILURE HERROR
18578 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018579 * Apply the complex type component constraints; this will not
18580 * check attributes, since this is done in
18581 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018582 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018583 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018584 HFAILURE HERROR
18585
18586#ifdef DEBUG_TYPE
18587 xmlSchemaDebugFixedType(pctxt, type);
18588#endif
18589 if (olderrs != pctxt->nberrors)
18590 return(pctxt->err);
18591 else
18592 return(0);
18593
18594exit_error:
18595 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18596#ifdef DEBUG_TYPE
18597 xmlSchemaDebugFixedType(pctxt, type);
18598#endif
18599 return(pctxt->err);
18600
18601exit_failure:
18602 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18603#ifdef DEBUG_TYPE
18604 xmlSchemaDebugFixedType(pctxt, type);
18605#endif
18606 return(-1);
18607}
18608
18609
18610/**
18611 * xmlSchemaTypeFixup:
18612 * @typeDecl: the schema type definition
18613 * @ctxt: the schema parser context
18614 *
18615 * Fixes the content model of the type.
18616 * URGENT TODO: We need an int result!
18617 */
18618static int
18619xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018620 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018621{
18622 if (type == NULL)
18623 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018624 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18625 AERROR_INT("xmlSchemaTypeFixup",
18626 "this function needs a parser context");
18627 return(-1);
18628 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018629 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018630 return(0);
18631 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018632 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018633 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018634 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018635 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018636}
18637
18638/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018639 * xmlSchemaCheckFacet:
18640 * @facet: the facet
18641 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018642 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018643 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018644 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018646 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018647 * Returns 0 if valid, a positive error code if not valid and
18648 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018649 */
18650int
18651xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018652 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018653 xmlSchemaParserCtxtPtr pctxt,
18654 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018655{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018657
Daniel Veillardce682bc2004-11-05 17:22:25 +000018658 if ((facet == NULL) || (typeDecl == NULL))
18659 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018660 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018661 * TODO: will the parser context be given if used from
18662 * the relaxNG module?
18663 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018664 if (pctxt == NULL)
18665 ctxtGiven = 0;
18666 else
18667 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018668
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018669 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018670 case XML_SCHEMA_FACET_MININCLUSIVE:
18671 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18672 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018673 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18674 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018675 /*
18676 * Okay we need to validate the value
18677 * at that point.
18678 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018679 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018680
18681 /* 4.3.5.5 Constraints on enumeration Schema Components
18682 * Schema Component Constraint: enumeration valid restriction
Jan Pokorný761c9e92013-11-29 23:26:27 +010018683 * It is an `error` if any member of {value} is not in the
18684 * `value space` of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018685 *
18686 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Jan Pokorný761c9e92013-11-29 23:26:27 +010018687 * The value `must` be in the
18688 * `value space` of the `base type`.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018689 */
18690 /*
18691 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018692 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018693 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018694 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018695 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018696 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018697 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018698 */
18699 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18700 base = typeDecl->baseType;
18701 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018702 PERROR_INT("xmlSchemaCheckFacet",
18703 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018704 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018705 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018706 } else
18707 base = typeDecl;
Daniel Veillarddee23482008-04-11 12:58:43 +000018708
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709 if (! ctxtGiven) {
18710 /*
18711 * A context is needed if called from RelaxNG.
Daniel Veillarddee23482008-04-11 12:58:43 +000018712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018713 pctxt = xmlSchemaNewParserCtxt("*");
18714 if (pctxt == NULL)
18715 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018717 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018718 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018719 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018720 * facet->node is just the node holding the facet
18721 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018722 * of the facet.
Daniel Veillarddee23482008-04-11 12:58:43 +000018723 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018724 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018725 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018726 facet->value, &(facet->val), 1, 1, 0);
18727 if (ret != 0) {
18728 if (ret < 0) {
18729 /* No error message for RelaxNG. */
Daniel Veillarddee23482008-04-11 12:58:43 +000018730 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018731 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018732 XML_SCHEMAP_INTERNAL, facet->node, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000018733 "Internal error: xmlSchemaCheckFacet, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018734 "failed to validate the value '%s' of the "
18735 "facet '%s' against the base type",
18736 facet->value, xmlSchemaFacetTypeToString(facet->type));
18737 }
18738 goto internal_error;
18739 }
18740 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18741 /* No error message for RelaxNG. */
18742 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018743 xmlChar *str = NULL;
18744
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018745 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018746 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018747 "The value '%s' of the facet does not validate "
18748 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018749 facet->value,
18750 xmlSchemaFormatQName(&str,
18751 base->targetNamespace, base->name));
18752 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018753 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018754 goto exit;
18755 } else if (facet->val == NULL) {
18756 if (ctxtGiven) {
18757 PERROR_INT("xmlSchemaCheckFacet",
18758 "value was not computed");
18759 }
18760 TODO
18761 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018762 break;
18763 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018764 case XML_SCHEMA_FACET_PATTERN:
18765 facet->regexp = xmlRegexpCompile(facet->value);
18766 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018767 ret = XML_SCHEMAP_REGEXP_INVALID;
18768 /* No error message for RelaxNG. */
18769 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018770 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018771 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018772 "The value '%s' of the facet 'pattern' is not a "
18773 "valid regular expression",
18774 facet->value, NULL);
18775 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018776 }
18777 break;
18778 case XML_SCHEMA_FACET_TOTALDIGITS:
18779 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18780 case XML_SCHEMA_FACET_LENGTH:
18781 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018782 case XML_SCHEMA_FACET_MINLENGTH:
18783
18784 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18785 ret = xmlSchemaValidatePredefinedType(
18786 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18787 facet->value, &(facet->val));
18788 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018789 ret = xmlSchemaValidatePredefinedType(
18790 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18791 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018792 }
18793 if (ret != 0) {
18794 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018795 /* No error message for RelaxNG. */
18796 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018797 PERROR_INT("xmlSchemaCheckFacet",
18798 "validating facet value");
18799 }
18800 goto internal_error;
18801 }
18802 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18803 /* No error message for RelaxNG. */
18804 if (ctxtGiven) {
18805 /* error code */
18806 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18807 ret, facet->node, WXS_BASIC_CAST typeDecl,
Daniel Veillarddee23482008-04-11 12:58:43 +000018808 "The value '%s' of the facet '%s' is not a valid '%s'",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018809 facet->value,
18810 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillarddee23482008-04-11 12:58:43 +000018811 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018812 BAD_CAST "nonNegativeInteger" :
18813 BAD_CAST "positiveInteger",
18814 NULL);
18815 }
18816 }
18817 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000018818
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018819 case XML_SCHEMA_FACET_WHITESPACE:{
18820 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18821 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18822 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18823 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18824 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18825 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18826 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018827 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18828 /* No error message for RelaxNG. */
18829 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018830 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018831 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018832 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018833 "The value '%s' of the facet 'whitespace' is not "
18834 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018835 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018836 }
18837 }
18838 default:
18839 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018840 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018841exit:
18842 if ((! ctxtGiven) && (pctxt != NULL))
18843 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018844 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018845internal_error:
18846 if ((! ctxtGiven) && (pctxt != NULL))
18847 xmlSchemaFreeParserCtxt(pctxt);
18848 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018849}
18850
18851/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018852 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018853 * @typeDecl: the schema type definition
18854 * @ctxt: the schema parser context
18855 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018856 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018857 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018858static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018859xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018860 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018861{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018862 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018863 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018864 /*
18865 * NOTE: It is intended to use the facets list, instead
18866 * of facetSet.
18867 */
18868 if (typeDecl->facets != NULL) {
18869 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018870
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018871 /*
18872 * Temporarily assign the "schema" to the validation context
18873 * of the parser context. This is needed for NOTATION validation.
18874 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018875 if (pctxt->vctxt == NULL) {
18876 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18877 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018878 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018879 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018880 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018881 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18882 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018883 facet = facet->next;
18884 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018885 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018886 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018887 if (olderrs != pctxt->nberrors)
18888 return(pctxt->err);
18889 return(0);
18890exit_failure:
18891 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018892}
18893
18894/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018895 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018896 * @ctxtMGroup: the searched model group
18897 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018898 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018899 *
18900 * This one is intended to be used by
18901 * xmlSchemaCheckGroupDefCircular only.
18902 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018903 * Returns the particle with the circular model group definition reference,
18904 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018905 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018906static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018907xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018908 xmlSchemaTreeItemPtr particle)
18909{
18910 xmlSchemaTreeItemPtr circ = NULL;
18911 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018912 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018913
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018914 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018915 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018916 if (term == NULL)
18917 continue;
18918 switch (term->type) {
18919 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018920 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018921 if (gdef == groupDef)
18922 return (particle);
18923 /*
18924 * Mark this model group definition to avoid infinite
18925 * recursion on circular references not yet examined.
18926 */
18927 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18928 continue;
18929 if (gdef->children != NULL) {
18930 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18931 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18932 gdef->children->children);
18933 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18934 if (circ != NULL)
18935 return (circ);
18936 }
18937 break;
18938 case XML_SCHEMA_TYPE_SEQUENCE:
18939 case XML_SCHEMA_TYPE_CHOICE:
18940 case XML_SCHEMA_TYPE_ALL:
18941 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18942 if (circ != NULL)
18943 return (circ);
18944 break;
18945 default:
18946 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018947 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018948 }
18949 return (NULL);
18950}
18951
18952/**
18953 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018954 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018955 * @ctxt: the parser context
18956 * @name: the name
18957 *
18958 * Checks for circular references to model group definitions.
18959 */
18960static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018961xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018962 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018963{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018964 /*
18965 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018966 * 2 Circular groups are disallowed. That is, within the {particles}
18967 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018968 * is the group itself.
18969 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018970 if ((item == NULL) ||
18971 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18972 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018973 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018974 {
18975 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018976
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018977 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018978 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018979 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018980 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018981 * TODO: The error report is not adequate: this constraint
18982 * is defined for model groups but not definitions, but since
18983 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018984 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018985 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018986 */
18987 xmlSchemaPCustomErr(ctxt,
18988 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018989 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018990 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018991 "defined", xmlSchemaFormatQName(&str,
18992 item->targetNamespace, item->name));
18993 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018994 /*
18995 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018996 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018997 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018998 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018999 }
19000 }
19001}
19002
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019003/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019004 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019005 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019006 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019007 *
19008 * Assigns the model group of model group definitions to the "term"
19009 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019010 * In xmlSchemaResolveModelGroupParticleReferences the model group
19011 * definitions were assigned to the "term", since needed for the
19012 * circularity check.
19013 *
19014 * Schema Component Constraint:
19015 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019016 */
19017static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019018xmlSchemaModelGroupToModelGroupDefFixup(
19019 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19020 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019021{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019022 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19023
19024 while (particle != NULL) {
19025 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19026 ((WXS_PARTICLE_TERM(particle))->type !=
19027 XML_SCHEMA_TYPE_GROUP))
19028 {
19029 particle = WXS_PTC_CAST particle->next;
19030 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000019031 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019032 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19033 /*
19034 * TODO: Remove the particle.
19035 */
19036 WXS_PARTICLE_TERM(particle) = NULL;
19037 particle = WXS_PTC_CAST particle->next;
19038 continue;
19039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019040 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019041 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019042 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019043 WXS_PARTICLE_TERM(particle) =
19044 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19045
19046 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019047 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019048}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019049
19050/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019051 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019052 * @ctxtGr: the searched attribute group
19053 * @attr: the current attribute list to be processed
19054 *
19055 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019056 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019057 *
19058 * Returns the circular attribute grou reference, otherwise NULL.
19059 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019060static xmlSchemaQNameRefPtr
19061xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19062 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019063{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019064 xmlSchemaAttributeGroupPtr gr;
19065 xmlSchemaQNameRefPtr ref, circ;
19066 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019067 /*
19068 * We will search for an attribute group reference which
19069 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019070 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019071 for (i = 0; i < list->nbItems; i++) {
19072 ref = list->items[i];
19073 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19074 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19075 (ref->item != NULL))
19076 {
19077 gr = WXS_ATTR_GROUP_CAST ref->item;
19078 if (gr == ctxtGr)
19079 return(ref);
19080 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
Daniel Veillarddee23482008-04-11 12:58:43 +000019081 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019082 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019083 * Mark as visited to avoid infinite recursion on
19084 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019085 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019086 if ((gr->attrUses) &&
19087 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19088 {
19089 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19090 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019091 (xmlSchemaItemListPtr) gr->attrUses);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019092 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19093 if (circ != NULL)
19094 return (circ);
19095 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019096
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019097 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019098 }
19099 return (NULL);
19100}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019101
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019102/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019103 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019104 * attrGr: the attribute group definition
19105 * @ctxt: the parser context
19106 * @name: the name
19107 *
19108 * Checks for circular references of attribute groups.
19109 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019110static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019111xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019112 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019113{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019114 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019115 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019116 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019117 * 3 Circular group reference is disallowed outside <redefine>.
19118 * That is, unless this element information item's parent is
19119 * <redefine>, then among the [children], if any, there must
19120 * not be an <attributeGroup> with ref [attribute] which resolves
19121 * to the component corresponding to this <attributeGroup>. Indirect
19122 * circularity is also ruled out. That is, when QName resolution
Jan Pokorný761c9e92013-11-29 23:26:27 +010019123 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019124 * any <attributeGroup>s with a ref [attribute] among the [children],
Jan Pokorný761c9e92013-11-29 23:26:27 +010019125 * it must not be the case that a `QName` is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019126 * which resolves to the component corresponding to this <attributeGroup>.
19127 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019128 if (attrGr->attrUses == NULL)
19129 return(0);
19130 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19131 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019132 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019133 xmlSchemaQNameRefPtr circ;
Daniel Veillarddee23482008-04-11 12:58:43 +000019134
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019135 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019136 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019137 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019138 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019139 /*
19140 * TODO: Report the referenced attr group as QName.
19141 */
19142 xmlSchemaPCustomErr(ctxt,
19143 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019144 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019145 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019146 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19147 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019148 /*
19149 * NOTE: We will cut the reference to avoid further
19150 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019151 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019152 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019153 circ->item = NULL;
19154 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019155 }
19156 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019157 return(0);
19158}
19159
19160static int
19161xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19162 xmlSchemaAttributeGroupPtr attrGr);
19163
19164/**
19165 * xmlSchemaExpandAttributeGroupRefs:
19166 * @pctxt: the parser context
19167 * @node: the node of the component holding the attribute uses
Daniel Veillarddee23482008-04-11 12:58:43 +000019168 * @completeWild: the intersected wildcard to be returned
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019169 * @list: the attribute uses
19170 *
19171 * Substitutes contained attribute group references
19172 * for their attribute uses. Wilcards are intersected.
19173 * Attribute use prohibitions are removed from the list
19174 * and returned via the @prohibs list.
19175 * Pointlessness of attr. prohibs, if a matching attr. decl
19176 * is existent a well, are checked.
19177 */
19178static int
19179xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19180 xmlSchemaBasicItemPtr item,
19181 xmlSchemaWildcardPtr *completeWild,
19182 xmlSchemaItemListPtr list,
19183 xmlSchemaItemListPtr prohibs)
19184{
19185 xmlSchemaAttributeGroupPtr gr;
19186 xmlSchemaAttributeUsePtr use;
19187 xmlSchemaItemListPtr sublist;
19188 int i, j;
19189 int created = (*completeWild == NULL) ? 0 : 1;
19190
19191 if (prohibs)
19192 prohibs->nbItems = 0;
19193
19194 for (i = 0; i < list->nbItems; i++) {
19195 use = list->items[i];
19196
Daniel Veillarddee23482008-04-11 12:58:43 +000019197 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019198 if (prohibs == NULL) {
19199 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19200 "unexpected attr prohibition found");
19201 return(-1);
19202 }
19203 /*
19204 * Remove from attribute uses.
19205 */
19206 if (xmlSchemaItemListRemove(list, i) == -1)
19207 return(-1);
19208 i--;
19209 /*
19210 * Note that duplicate prohibitions were already
19211 * handled at parsing time.
Daniel Veillarddee23482008-04-11 12:58:43 +000019212 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019213 /*
19214 * Add to list of prohibitions.
19215 */
19216 xmlSchemaItemListAddSize(prohibs, 2, use);
19217 continue;
19218 }
19219 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19220 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19221 {
19222 if ((WXS_QNAME_CAST use)->item == NULL)
19223 return(-1);
19224 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19225 /*
19226 * Expand the referenced attr. group.
19227 * TODO: remove this, this is done in a previous step, so
19228 * already done here.
19229 */
19230 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19231 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19232 return(-1);
19233 }
19234 /*
19235 * Build the 'complete' wildcard; i.e. intersect multiple
19236 * wildcards.
19237 */
19238 if (gr->attributeWildcard != NULL) {
19239 if (*completeWild == NULL) {
19240 *completeWild = gr->attributeWildcard;
19241 } else {
19242 if (! created) {
19243 xmlSchemaWildcardPtr tmpWild;
19244
19245 /*
19246 * Copy the first encountered wildcard as context,
19247 * except for the annotation.
19248 *
19249 * Although the complete wildcard might not correspond
19250 * to any node in the schema, we will anchor it on
19251 * the node of the owner component.
19252 */
19253 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19254 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19255 WXS_ITEM_NODE(item));
19256 if (tmpWild == NULL)
19257 return(-1);
19258 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19259 tmpWild, *completeWild) == -1)
19260 return (-1);
19261 tmpWild->processContents = (*completeWild)->processContents;
19262 *completeWild = tmpWild;
19263 created = 1;
19264 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019265
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019266 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19267 gr->attributeWildcard) == -1)
19268 return(-1);
19269 }
19270 }
19271 /*
19272 * Just remove the reference if the referenced group does not
19273 * contain any attribute uses.
19274 */
William M. Brack06559b32007-03-14 09:34:15 +000019275 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19276 if ((sublist == NULL) || sublist->nbItems == 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019277 if (xmlSchemaItemListRemove(list, i) == -1)
19278 return(-1);
19279 i--;
19280 continue;
19281 }
19282 /*
19283 * Add the attribute uses.
19284 */
William M. Brack06559b32007-03-14 09:34:15 +000019285 list->items[i] = sublist->items[0];
19286 if (sublist->nbItems != 1) {
19287 for (j = 1; j < sublist->nbItems; j++) {
19288 i++;
19289 if (xmlSchemaItemListInsert(list,
19290 sublist->items[j], i) == -1)
19291 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019292 }
William M. Brack06559b32007-03-14 09:34:15 +000019293 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019294 }
19295
19296 }
19297 /*
19298 * Handle pointless prohibitions of declared attributes.
19299 */
19300 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19301 xmlSchemaAttributeUseProhibPtr prohib;
19302
19303 for (i = prohibs->nbItems -1; i >= 0; i--) {
19304 prohib = prohibs->items[i];
19305 for (j = 0; j < list->nbItems; j++) {
19306 use = list->items[j];
19307
19308 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19309 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19310 {
19311 xmlChar *str = NULL;
19312
19313 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19314 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19315 prohib->node, NULL,
19316 "Skipping pointless attribute use prohibition "
19317 "'%s', since a corresponding attribute use "
19318 "exists already in the type definition",
19319 xmlSchemaFormatQName(&str,
19320 prohib->targetNamespace, prohib->name),
19321 NULL, NULL);
19322 FREE_AND_NULL(str);
19323 /*
19324 * Remove the prohibition.
19325 */
19326 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19327 return(-1);
19328 break;
19329 }
19330 }
19331 }
19332 }
19333 return(0);
19334}
19335
19336/**
19337 * xmlSchemaAttributeGroupExpandRefs:
19338 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019339 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019340 *
19341 * Computation of:
19342 * {attribute uses} property
19343 * {attribute wildcard} property
19344 *
19345 * Substitutes contained attribute group references
19346 * for their attribute uses. Wilcards are intersected.
19347 */
19348static int
19349xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19350 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019351{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019352 if ((attrGr->attrUses == NULL) ||
19353 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19354 return(0);
19355
19356 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19357 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19358 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000019359 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019360 return(0);
19361}
19362
19363/**
19364 * xmlSchemaAttributeGroupExpandRefs:
19365 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019366 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019367 *
19368 * Substitutes contained attribute group references
19369 * for their attribute uses. Wilcards are intersected.
Daniel Veillarddee23482008-04-11 12:58:43 +000019370 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019371 * Schema Component Constraint:
Daniel Veillarddee23482008-04-11 12:58:43 +000019372 * Attribute Group Definition Properties Correct (ag-props-correct)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019373 */
19374static int
19375xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19376 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019377{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019378 /*
19379 * SPEC ag-props-correct
19380 * (1) "The values of the properties of an attribute group definition
19381 * must be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019382 * Group Definition Schema Component ($3.6.1), modulo the impact of
19383 * Missing Sub-components ($5.3);"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019384 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019385
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019386 if ((attrGr->attrUses != NULL) &&
19387 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19388 {
19389 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19390 xmlSchemaAttributeUsePtr use, tmp;
19391 int i, j, hasId = 0;
19392
19393 for (i = uses->nbItems -1; i >= 0; i--) {
Daniel Veillarddee23482008-04-11 12:58:43 +000019394 use = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019395 /*
19396 * SPEC ag-props-correct
19397 * (2) "Two distinct members of the {attribute uses} must not have
19398 * {attribute declaration}s both of whose {name}s match and whose
19399 * {target namespace}s are identical."
19400 */
19401 if (i > 0) {
19402 for (j = i -1; j >= 0; j--) {
19403 tmp = uses->items[j];
19404 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19405 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19406 (WXS_ATTRUSE_DECL_TNS(use) ==
19407 WXS_ATTRUSE_DECL_TNS(tmp)))
19408 {
19409 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019410
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019411 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19412 XML_SCHEMAP_AG_PROPS_CORRECT,
19413 attrGr->node, WXS_BASIC_CAST attrGr,
19414 "Duplicate %s",
19415 xmlSchemaGetComponentDesignation(&str, use),
19416 NULL);
19417 FREE_AND_NULL(str);
19418 /*
19419 * Remove the duplicate.
19420 */
19421 if (xmlSchemaItemListRemove(uses, i) == -1)
19422 return(-1);
19423 goto next_use;
19424 }
19425 }
19426 }
19427 /*
19428 * SPEC ag-props-correct
19429 * (3) "Two distinct members of the {attribute uses} must not have
19430 * {attribute declaration}s both of whose {type definition}s are or
19431 * are derived from ID."
19432 * TODO: Does 'derived' include member-types of unions?
19433 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019434 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019435 if (xmlSchemaIsDerivedFromBuiltInType(
19436 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000019437 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019438 if (hasId) {
19439 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019440
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019441 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19442 XML_SCHEMAP_AG_PROPS_CORRECT,
19443 attrGr->node, WXS_BASIC_CAST attrGr,
19444 "There must not exist more than one attribute "
19445 "declaration of type 'xs:ID' "
19446 "(or derived from 'xs:ID'). The %s violates this "
19447 "constraint",
19448 xmlSchemaGetComponentDesignation(&str, use),
19449 NULL);
19450 FREE_AND_NULL(str);
19451 if (xmlSchemaItemListRemove(uses, i) == -1)
19452 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000019453 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019454 hasId = 1;
19455 }
19456 }
19457next_use: {}
19458 }
19459 }
19460 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019461}
19462
19463/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019464 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019465 * @attrgrpDecl: the schema attribute definition
19466 * @ctxt: the schema parser context
19467 * @name: the attribute name
19468 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019469 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019470 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019471static int
19472xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19473 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019474{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019475 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019476
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019477 if (ref->item != NULL)
19478 return(0);
19479 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19480 ref->name,
19481 ref->targetNamespace);
19482 if (group == NULL) {
19483 xmlSchemaPResCompAttrErr(ctxt,
19484 XML_SCHEMAP_SRC_RESOLVE,
19485 NULL, ref->node,
19486 "ref", ref->name, ref->targetNamespace,
19487 ref->itemType, NULL);
19488 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019489 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019490 ref->item = WXS_BASIC_CAST group;
19491 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019492}
19493
19494/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019495 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019496 * @item: an schema attribute declaration/use
19497 * @ctxt: a schema parser context
19498 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019499 *
19500 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019501 * Schema Component Constraint:
19502 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019503 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019504 * Validates the value constraints of an attribute declaration/use.
19505 * NOTE that this needs the simle type definitions to be already
19506 * builded and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019507 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019508static int
19509xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19510 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019511{
19512
19513 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019514 * SPEC a-props-correct (1)
19515 * "The values of the properties of an attribute declaration must
19516 * be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019517 * Declaration Schema Component ($3.2.1), modulo the impact of
19518 * Missing Sub-components ($5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019519 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019520
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019521 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19522 return(0);
19523
19524 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019525 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019526
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019527 /*
19528 * SPEC a-props-correct (3)
19529 * "If the {type definition} is or is derived from ID then there
19530 * must not be a {value constraint}."
19531 */
19532 if (xmlSchemaIsDerivedFromBuiltInType(
19533 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19534 {
19535 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19536 XML_SCHEMAP_A_PROPS_CORRECT_3,
19537 NULL, WXS_BASIC_CAST attr,
19538 "Value constraints are not allowed if the type definition "
19539 "is or is derived from xs:ID",
19540 NULL, NULL);
19541 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019542 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019543 /*
19544 * SPEC a-props-correct (2)
19545 * "if there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019546 * representation of its value must be `valid` with respect
19547 * to the {type definition} as defined in String Valid ($3.14.4)."
Jan Pokorný7a7cad62013-11-29 23:26:26 +010019548 * TODO: Don't care about the *canonical* stuff here, this requirement
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019549 * will be removed in WXS 1.1 anyway.
19550 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019551 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019552 attr->node, WXS_ATTR_TYPEDEF(attr),
19553 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019554 1, 1, 0);
19555 if (ret != 0) {
19556 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019557 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019558 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019559 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019560 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019561 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019562 XML_SCHEMAP_A_PROPS_CORRECT_2,
19563 NULL, WXS_BASIC_CAST attr,
19564 "The value of the value constraint is not valid",
19565 NULL, NULL);
19566 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019567 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019568 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019569
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019570 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019571}
19572
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019573static xmlSchemaElementPtr
19574xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19575 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019576{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019577 xmlSchemaElementPtr ret;
19578
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019579 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019580 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019581 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019582 return (ancestor);
19583
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019584 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019585 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019586 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019587 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019588 WXS_SUBST_HEAD(ancestor));
19589 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019590
19591 return (ret);
19592}
19593
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019594/**
19595 * xmlSchemaCheckElemPropsCorrect:
19596 * @ctxt: a schema parser context
19597 * @decl: the element declaration
19598 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019599 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019600 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019601 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019602 *
19603 * STATUS:
19604 * missing: (6)
19605 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019606static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019607xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19608 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019609{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019610 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019611 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019612 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019613 * SPEC (1) "The values of the properties of an element declaration
19614 * must be as described in the property tableau in The Element
Jan Pokorný761c9e92013-11-29 23:26:27 +010019615 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19616 * Sub-components ($5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019617 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019618 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19619 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019620
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019621 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019622 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010019623 * SPEC (3) "If there is a non-`absent` {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019624 * affiliation}, then {scope} must be global."
19625 */
19626 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19627 xmlSchemaPCustomErr(pctxt,
19628 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019629 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019630 "Only global element declarations can have a "
19631 "substitution group affiliation", NULL);
19632 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019633 }
19634 /*
19635 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19636 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019637 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019638 * property."
19639 */
19640 if (head == elemDecl)
19641 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019642 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019643 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19644 else
19645 circ = NULL;
19646 if (circ != NULL) {
19647 xmlChar *strA = NULL, *strB = NULL;
19648
19649 xmlSchemaPCustomErrExt(pctxt,
19650 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019651 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019652 "The element declaration '%s' defines a circular "
19653 "substitution group to element declaration '%s'",
19654 xmlSchemaGetComponentQName(&strA, circ),
19655 xmlSchemaGetComponentQName(&strB, head),
19656 NULL);
19657 FREE_AND_NULL(strA)
19658 FREE_AND_NULL(strB)
19659 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19660 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019661 /*
19662 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019663 * the {type definition}
19664 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019665 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019666 * of the {substitution group exclusions} of the {substitution group
Jan Pokorný761c9e92013-11-29 23:26:27 +010019667 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019668 * (if the {type definition} is complex) or as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019669 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019670 * simple)."
19671 *
19672 * NOTE: {substitution group exclusions} means the values of the
19673 * attribute "final".
19674 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019675
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019676 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019677 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019678
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019679 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19680 set |= SUBSET_EXTENSION;
19681 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19682 set |= SUBSET_RESTRICTION;
19683
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019684 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019685 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019686 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19687
19688 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019689 xmlSchemaPCustomErrExt(pctxt,
19690 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019691 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019692 "The type definition '%s' was "
19693 "either rejected by the substitution group "
19694 "affiliation '%s', or not validly derived from its type "
19695 "definition '%s'",
19696 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019697 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019698 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019699 FREE_AND_NULL(strA)
19700 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019701 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019702 }
19703 }
19704 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019705 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019706 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019707 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019708 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019709 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019710 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019711 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019712 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019713 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019714 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019715 (WXS_IS_COMPLEX(typeDef) &&
19716 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019717 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19718 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019719
19720 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19721 xmlSchemaPCustomErr(pctxt,
19722 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019723 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019724 "The type definition (or type definition's content type) is or "
19725 "is derived from ID; value constraints are not allowed in "
19726 "conjunction with such a type definition", NULL);
19727 } else if (elemDecl->value != NULL) {
19728 int vcret;
19729 xmlNodePtr node = NULL;
19730
19731 /*
19732 * SPEC (2) "If there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019733 * representation of its value must be `valid` with respect to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019734 * {type definition} as defined in Element Default Valid (Immediate)
Jan Pokorný761c9e92013-11-29 23:26:27 +010019735 * ($3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019736 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019737 if (typeDef == NULL) {
19738 xmlSchemaPErr(pctxt, elemDecl->node,
19739 XML_SCHEMAP_INTERNAL,
19740 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19741 "type is missing... skipping validation of "
19742 "the value constraint", NULL, NULL);
19743 return (-1);
19744 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019745 if (elemDecl->node != NULL) {
19746 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19747 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19748 BAD_CAST "fixed");
19749 else
19750 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19751 BAD_CAST "default");
19752 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019753 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19754 typeDef, elemDecl->value, &(elemDecl->defVal));
19755 if (vcret != 0) {
19756 if (vcret < 0) {
19757 PERROR_INT("xmlSchemaElemCheckValConstr",
19758 "failed to validate the value constraint of an "
19759 "element declaration");
19760 return (-1);
19761 }
19762 return (vcret);
19763 }
19764 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019765
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019766 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019767}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019768
19769/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019770 * xmlSchemaCheckElemSubstGroup:
19771 * @ctxt: a schema parser context
19772 * @decl: the element declaration
19773 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019774 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019775 * Schema Component Constraint:
19776 * Substitution Group (cos-equiv-class)
19777 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019778 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019779 * a list will be built for each subst. group head, holding all direct
19780 * referents to this head.
19781 * NOTE that this function needs:
19782 * 1. circular subst. groups to be checked beforehand
19783 * 2. the declaration's type to be derived from the head's type
19784 *
19785 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019786 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019787 */
19788static void
19789xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19790 xmlSchemaElementPtr elemDecl)
19791{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019792 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019793 /* SPEC (1) "Its {abstract} is false." */
19794 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19795 return;
19796 {
19797 xmlSchemaElementPtr head;
19798 xmlSchemaTypePtr headType, type;
19799 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019800 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019801 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19802 * {disallowed substitutions} as the blocking constraint, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019803 * Substitution Group OK (Transitive) ($3.3.6)."
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019804 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019805 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19806 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019807 set = 0;
19808 methSet = 0;
19809 /*
19810 * The blocking constraints.
19811 */
19812 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19813 continue;
19814 headType = head->subtypes;
19815 type = elemDecl->subtypes;
19816 if (headType == type)
19817 goto add_member;
19818 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19819 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19820 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19821 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019823 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019824 * "The set of all {derivation method}s involved in the
19825 * derivation of D's {type definition} from C's {type definition}
19826 * does not intersect with the union of the blocking constraint,
19827 * C's {prohibited substitutions} (if C is complex, otherwise the
19828 * empty set) and the {prohibited substitutions} (respectively the
19829 * empty set) of any intermediate {type definition}s in the
19830 * derivation of D's {type definition} from C's {type definition}."
19831 */
19832 /*
19833 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19834 * subst.head axis, the methSet does not need to be computed for
19835 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019836 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019837 /*
19838 * The set of all {derivation method}s involved in the derivation
19839 */
19840 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019841 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019842 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19843 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019844
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019845 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019846 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19847 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19848
19849 type = type->baseType;
19850 }
19851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019852 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019853 * the head's type.
19854 */
19855 type = elemDecl->subtypes->baseType;
19856 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019857 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019858 if ((type->flags &
19859 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19860 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19861 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19862 if ((type->flags &
19863 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19864 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19865 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19866 } else
19867 break;
19868 if (type == headType)
19869 break;
19870 type = type->baseType;
19871 }
19872 if ((set != 0) &&
19873 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19874 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19875 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19876 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19877 continue;
19878 }
19879add_member:
19880 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19881 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19882 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19883 }
19884 }
19885}
19886
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019887#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19888/**
19889 * xmlSchemaCheckElementDeclComponent
19890 * @pctxt: the schema parser context
19891 * @ctxtComponent: the context component (an element declaration)
19892 * @ctxtParticle: the first particle of the context component
19893 * @searchParticle: the element declaration particle to be analysed
19894 *
Daniel Veillarddee23482008-04-11 12:58:43 +000019895 * Schema Component Constraint: Element Declarations Consistent
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019896 */
19897static int
19898xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19899 xmlSchemaBasicItemPtr ctxtComponent,
Daniel Veillarddee23482008-04-11 12:58:43 +000019900 xmlSchemaParticlePtr ctxtParticle,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019901 xmlSchemaParticlePtr searchParticle,
19902 xmlSchemaParticlePtr curParticle,
19903 int search)
19904{
19905 return(0);
19906
19907 int ret = 0;
19908 xmlSchemaParticlePtr cur = curParticle;
Daniel Veillarddee23482008-04-11 12:58:43 +000019909 if (curParticle == NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019910 return(0);
19911 }
19912 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19913 /*
19914 * Just return in this case. A missing "term" of the particle
19915 * might arise due to an invalid "term" component.
19916 */
19917 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000019918 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019919 while (cur != NULL) {
19920 switch (WXS_PARTICLE_TERM(cur)->type) {
19921 case XML_SCHEMA_TYPE_ANY:
19922 break;
19923 case XML_SCHEMA_TYPE_ELEMENT:
19924 if (search == 0) {
19925 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19926 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19927 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000019928 return(ret);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019929 } else {
19930 xmlSchemaElementPtr elem =
19931 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19932 /*
19933 * SPEC Element Declarations Consistent:
19934 * "If the {particles} contains, either directly,
19935 * indirectly (that is, within the {particles} of a
Jan Pokorný761c9e92013-11-29 23:26:27 +010019936 * contained model group, recursively) or `implicitly`
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019937 * two or more element declaration particles with
19938 * the same {name} and {target namespace}, then
19939 * all their type definitions must be the same
19940 * top-level definition [...]"
19941 */
19942 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19943 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19944 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19945 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19946 {
19947 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019948
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019949 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19950 /* TODO: error code */
19951 XML_SCHEMAP_COS_NONAMBIG,
19952 WXS_ITEM_NODE(cur), NULL,
19953 "In the content model of %s, there are multiple "
19954 "element declarations for '%s' with different "
19955 "type definitions",
19956 xmlSchemaGetComponentDesignation(&strA,
19957 ctxtComponent),
19958 xmlSchemaFormatQName(&strB,
19959 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19960 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19961 FREE_AND_NULL(strA);
19962 FREE_AND_NULL(strB);
19963 return(XML_SCHEMAP_COS_NONAMBIG);
19964 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019965 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019966 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000019967 case XML_SCHEMA_TYPE_SEQUENCE: {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019968 break;
19969 }
19970 case XML_SCHEMA_TYPE_CHOICE:{
19971 /*
19972 xmlSchemaTreeItemPtr sub;
Daniel Veillarddee23482008-04-11 12:58:43 +000019973
19974 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019975 while (sub != NULL) {
19976 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19977 ctxtParticle, ctxtElem);
19978 if (ret != 0)
19979 return(ret);
19980 sub = sub->next;
19981 }
19982 */
19983 break;
19984 }
19985 case XML_SCHEMA_TYPE_ALL:
19986 break;
19987 case XML_SCHEMA_TYPE_GROUP:
19988 break;
19989 default:
19990 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19991 "xmlSchemaCheckElementDeclConsistent",
19992 "found unexpected term of type '%s' in content model",
19993 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19994 return(-1);
19995 }
19996 cur = (xmlSchemaParticlePtr) cur->next;
19997 }
19998
19999exit:
20000 return(ret);
20001}
20002#endif
20003
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000020004/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020005 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020006 * @item: an schema element declaration/particle
20007 * @ctxt: a schema parser context
20008 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020009 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020010 * Validates the value constraints of an element declaration.
Daniel Veillarddee23482008-04-11 12:58:43 +000020011 * Adds substitution group members.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020012 */
20013static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020014xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020015 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020016{
20017 if (elemDecl == NULL)
20018 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020019 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20020 return;
20021 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020022 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20023 /*
20024 * Adds substitution group members.
20025 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020026 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020027 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020028}
20029
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020030/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020031 * xmlSchemaResolveModelGroupParticleReferences:
20032 * @particle: a particle component
20033 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020034 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020035 * Resolves references of a model group's {particles} to
20036 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020037 */
20038static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020039xmlSchemaResolveModelGroupParticleReferences(
20040 xmlSchemaParserCtxtPtr ctxt,
20041 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020042{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020043 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20044 xmlSchemaQNameRefPtr ref;
20045 xmlSchemaBasicItemPtr refItem;
20046
20047 /*
20048 * URGENT TODO: Test this.
20049 */
20050 while (particle != NULL) {
20051 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20052 ((WXS_PARTICLE_TERM(particle))->type !=
20053 XML_SCHEMA_EXTRA_QNAMEREF))
20054 {
20055 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020056 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020057 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020058 /*
20059 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020060 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020061 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020062 particle->children = NULL;
20063
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020064 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20065 ref->itemType, ref->name, ref->targetNamespace);
20066 if (refItem == NULL) {
20067 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020068 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020069 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020070 /* TODO: remove the particle. */
20071 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020072 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020073 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20074 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20075 /* TODO: remove the particle. */
20076 goto next_particle;
20077 /*
20078 * NOTE that we will assign the model group definition
20079 * itself to the "term" of the particle. This will ease
20080 * the check for circular model group definitions. After
20081 * that the "term" will be assigned the model group of the
20082 * model group definition.
20083 */
20084 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20085 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020086 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020087 * SPEC cos-all-limited (1)
20088 * SPEC cos-all-limited (1.2)
20089 * "It appears only as the value of one or both of the
20090 * following properties:"
20091 * (1.1) "the {model group} property of a model group
20092 * definition."
20093 * (1.2) "the {term} property of a particle [... of] the "
20094 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020095 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020096 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20097 /* TODO: error code */
20098 XML_SCHEMAP_COS_ALL_LIMITED,
20099 WXS_ITEM_NODE(particle), NULL,
20100 "A model group definition is referenced, but "
20101 "it contains an 'all' model group, which "
20102 "cannot be contained by model groups",
20103 NULL, NULL);
20104 /* TODO: remove the particle. */
20105 goto next_particle;
20106 }
20107 particle->children = (xmlSchemaTreeItemPtr) refItem;
20108 } else {
20109 /*
20110 * TODO: Are referenced element declarations the only
20111 * other components we expect here?
20112 */
20113 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020114 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020115next_particle:
20116 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020117 }
20118}
20119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020120static int
20121xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
Daniel Veillarddee23482008-04-11 12:58:43 +000020122 xmlSchemaValPtr y)
20123{
20124 xmlSchemaTypePtr tx, ty, ptx, pty;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020125 int ret;
20126
20127 while (x != NULL) {
20128 /* Same types. */
20129 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20130 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20131 ptx = xmlSchemaGetPrimitiveType(tx);
20132 pty = xmlSchemaGetPrimitiveType(ty);
20133 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020134 * (1) if a datatype T' is `derived` by `restriction` from an
20135 * atomic datatype T then the `value space` of T' is a subset of
20136 * the `value space` of T. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020137 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020138 * (2) if datatypes T' and T'' are `derived` by `restriction`
20139 * from a common atomic ancestor T then the `value space`s of T'
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020140 * and T'' may overlap.
20141 */
20142 if (ptx != pty)
20143 return(0);
20144 /*
20145 * We assume computed values to be normalized, so do a fast
20146 * string comparison for string based types.
20147 */
20148 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020149 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020150 if (! xmlStrEqual(
20151 xmlSchemaValueGetAsString(x),
20152 xmlSchemaValueGetAsString(y)))
20153 return (0);
20154 } else {
20155 ret = xmlSchemaCompareValuesWhtsp(
20156 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20157 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20158 if (ret == -2)
20159 return(-1);
20160 if (ret != 0)
20161 return(0);
20162 }
20163 /*
20164 * Lists.
20165 */
20166 x = xmlSchemaValueGetNext(x);
20167 if (x != NULL) {
20168 y = xmlSchemaValueGetNext(y);
20169 if (y == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020170 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020171 } else if (xmlSchemaValueGetNext(y) != NULL)
20172 return (0);
20173 else
20174 return (1);
20175 }
20176 return (0);
20177}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020178
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020179/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020180 * xmlSchemaResolveAttrUseReferences:
20181 * @item: an attribute use
20182 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020183 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020184 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020185 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020186static int
20187xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20188 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000020189{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020190 if ((ctxt == NULL) || (ause == NULL))
20191 return(-1);
20192 if ((ause->attrDecl == NULL) ||
20193 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20194 return(0);
20195
20196 {
20197 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20198
20199 /*
20200 * TODO: Evaluate, what errors could occur if the declaration is not
20201 * found.
20202 */
20203 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20204 ref->name, ref->targetNamespace);
20205 if (ause->attrDecl == NULL) {
20206 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardf8e3db02012-09-11 13:26:36 +080020207 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020208 WXS_BASIC_CAST ause, ause->node,
20209 "ref", ref->name, ref->targetNamespace,
20210 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20211 return(ctxt->err);;
20212 }
20213 }
20214 return(0);
20215}
20216
20217/**
20218 * xmlSchemaCheckAttrUsePropsCorrect:
20219 * @ctxt: a parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000020220 * @use: an attribute use
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020221 *
20222 * Schema Component Constraint:
20223 * Attribute Use Correct (au-props-correct)
Daniel Veillarddee23482008-04-11 12:58:43 +000020224 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020225 */
20226static int
20227xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20228 xmlSchemaAttributeUsePtr use)
20229{
20230 if ((ctxt == NULL) || (use == NULL))
20231 return(-1);
20232 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20233 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
Daniel Veillarddee23482008-04-11 12:58:43 +000020234 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020235
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020236 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020237 * SPEC au-props-correct (1)
20238 * "The values of the properties of an attribute use must be as
20239 * described in the property tableau in The Attribute Use Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020240 * Component ($3.5.1), modulo the impact of Missing
20241 * Sub-components ($5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000020242 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020243
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020244 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20245 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20246 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20247 {
20248 xmlSchemaPCustomErr(ctxt,
20249 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20250 WXS_BASIC_CAST use, NULL,
20251 "The attribute declaration has a 'fixed' value constraint "
20252 ", thus the attribute use must also have a 'fixed' value "
20253 "constraint",
20254 NULL);
20255 return(ctxt->err);
20256 }
20257 /*
20258 * Compute and check the value constraint's value.
20259 */
20260 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20261 int ret;
20262 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000020263 * TODO: The spec seems to be missing a check of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020264 * value constraint of the attribute use. We will do it here.
20265 */
20266 /*
20267 * SPEC a-props-correct (3)
20268 */
20269 if (xmlSchemaIsDerivedFromBuiltInType(
20270 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20271 {
20272 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20273 XML_SCHEMAP_AU_PROPS_CORRECT,
20274 NULL, WXS_BASIC_CAST use,
20275 "Value constraints are not allowed if the type definition "
20276 "is or is derived from xs:ID",
20277 NULL, NULL);
20278 return(ctxt->err);
20279 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020280
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020281 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20282 use->node, WXS_ATTRUSE_TYPEDEF(use),
20283 use->defValue, &(use->defVal),
20284 1, 1, 0);
20285 if (ret != 0) {
20286 if (ret < 0) {
20287 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20288 "calling xmlSchemaVCheckCVCSimpleType()");
20289 return(-1);
20290 }
20291 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20292 XML_SCHEMAP_AU_PROPS_CORRECT,
20293 NULL, WXS_BASIC_CAST use,
20294 "The value of the value constraint is not valid",
20295 NULL, NULL);
20296 return(ctxt->err);
20297 }
20298 }
20299 /*
20300 * SPEC au-props-correct (2)
20301 * "If the {attribute declaration} has a fixed
20302 * {value constraint}, then if the attribute use itself has a
20303 * {value constraint}, it must also be fixed and its value must match
20304 * that of the {attribute declaration}'s {value constraint}."
20305 */
20306 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20307 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20308 {
20309 if (! xmlSchemaAreValuesEqual(use->defVal,
20310 (WXS_ATTRUSE_DECL(use))->defVal))
20311 {
20312 xmlSchemaPCustomErr(ctxt,
20313 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20314 WXS_BASIC_CAST use, NULL,
20315 "The 'fixed' value constraint of the attribute use "
20316 "must match the attribute declaration's value "
20317 "constraint '%s'",
20318 (WXS_ATTRUSE_DECL(use))->defValue);
20319 }
20320 return(ctxt->err);
20321 }
20322 return(0);
20323}
20324
20325
20326
20327
20328/**
20329 * xmlSchemaResolveAttrTypeReferences:
20330 * @item: an attribute declaration
Daniel Veillarddee23482008-04-11 12:58:43 +000020331 * @ctxt: a parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020332 *
20333 * Resolves the referenced type definition component.
20334 */
20335static int
20336xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20337 xmlSchemaParserCtxtPtr ctxt)
20338{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020339 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020340 * The simple type definition corresponding to the <simpleType> element
20341 * information item in the [children], if present, otherwise the simple
Jan Pokorný761c9e92013-11-29 23:26:27 +010020342 * type definition `resolved` to by the `actual value` of the type
20343 * [attribute], if present, otherwise the `simple ur-type definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000020344 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020345 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020346 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020347 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20348 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020349 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020350 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020351 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020352
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020353 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20354 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020355 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020356 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020357 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020358 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020359 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020360 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020361 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020362 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020363 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020364
Daniel Veillard3646d642004-06-02 19:19:14 +000020365 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020366 /*
20367 * The type defaults to the xs:anySimpleType.
20368 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020369 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20370 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020371 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020372}
20373
20374/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020375 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020376 * @idc: the identity-constraint definition
20377 * @ctxt: the schema parser context
20378 * @name: the attribute name
20379 *
20380 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020381 * Schema Component Constraint:
20382 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020383 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020384static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020385xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020386 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020387{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020388 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020389 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020390 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020391 idc->ref->item = (xmlSchemaBasicItemPtr)
20392 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20393 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020394 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020395 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020396 * TODO: It is actually not an error to fail to resolve
20397 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020398 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020399 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020400 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020401 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020402 "refer", idc->ref->name,
20403 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020404 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020405 return(pctxt->err);
20406 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20407 /*
20408 * SPEC c-props-correct (1)
20409 */
20410 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20411 XML_SCHEMAP_C_PROPS_CORRECT,
20412 NULL, WXS_BASIC_CAST idc,
20413 "The keyref references a keyref",
20414 NULL, NULL);
20415 idc->ref->item = NULL;
20416 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020417 } else {
20418 if (idc->nbFields !=
20419 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20420 xmlChar *str = NULL;
20421 xmlSchemaIDCPtr refer;
Daniel Veillarddee23482008-04-11 12:58:43 +000020422
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020423 refer = (xmlSchemaIDCPtr) idc->ref->item;
20424 /*
20425 * SPEC c-props-correct(2)
20426 * "If the {identity-constraint category} is keyref,
20427 * the cardinality of the {fields} must equal that of
20428 * the {fields} of the {referenced key}.
20429 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020430 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020431 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020432 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020433 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020434 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020435 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020436 refer->name),
20437 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020438 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020439 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020441 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020442 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020443 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020444}
20445
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020446static int
20447xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20448 xmlSchemaParserCtxtPtr pctxt)
20449{
20450 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20451 prohib->targetNamespace) == NULL) {
20452
20453 xmlSchemaPResCompAttrErr(pctxt,
20454 XML_SCHEMAP_SRC_RESOLVE,
20455 NULL, prohib->node,
20456 "ref", prohib->name, prohib->targetNamespace,
20457 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20458 return(XML_SCHEMAP_SRC_RESOLVE);
20459 }
20460 return(0);
20461}
20462
20463#define WXS_REDEFINED_TYPE(c) \
20464(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20465
20466#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20467(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20468
20469#define WXS_REDEFINED_ATTR_GROUP(c) \
20470(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20471
20472static int
20473xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20474{
20475 int err = 0;
20476 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20477 xmlSchemaBasicItemPtr prev, item;
20478 int wasRedefined;
20479
20480 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020481 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020482
20483 do {
20484 item = redef->item;
20485 /*
20486 * First try to locate the redefined component in the
20487 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020488 * NOTE: According to this schema bug entry:
20489 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20490 * it's not clear if the referenced component needs to originate
20491 * from the <redefine>d schema _document_ or the schema; the latter
20492 * would include all imported and included sub-schemas of the
20493 * <redefine>d schema. Currenlty we latter approach is used.
20494 * SUPPLEMENT: It seems that the WG moves towards the latter
20495 * approach, so we are doing it right.
Daniel Veillarddee23482008-04-11 12:58:43 +000020496 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020497 */
20498 prev = xmlSchemaFindRedefCompInGraph(
20499 redef->targetBucket, item->type,
20500 redef->refName, redef->refTargetNs);
20501 if (prev == NULL) {
20502 xmlChar *str = NULL;
20503 xmlNodePtr node;
20504
20505 /*
20506 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010020507 * (6.2.1) "The `actual value` of its own name attribute plus
20508 * target namespace must successfully `resolve` to a model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020509 * group definition in I."
Jan Pokorný761c9e92013-11-29 23:26:27 +010020510 * (7.2.1) "The `actual value` of its own name attribute plus
20511 * target namespace must successfully `resolve` to an attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020512 * group definition in I."
20513
20514 *
20515 * Note that, if we are redefining with the use of references
20516 * to components, the spec assumes the src-resolve to be used;
20517 * but this won't assure that we search only *inside* the
20518 * redefined schema.
20519 */
20520 if (redef->reference)
20521 node = WXS_ITEM_NODE(redef->reference);
20522 else
20523 node = WXS_ITEM_NODE(item);
20524 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20525 /*
20526 * TODO: error code.
20527 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
Daniel Veillarddee23482008-04-11 12:58:43 +000020528 * reference kind.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020529 */
20530 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020531 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020532 "the redefined schema",
20533 WXS_ITEM_TYPE_NAME(item),
20534 xmlSchemaFormatQName(&str, redef->refTargetNs,
20535 redef->refName));
Daniel Veillarddee23482008-04-11 12:58:43 +000020536 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020537 err = pctxt->err;
20538 redef = redef->next;
20539 continue;
20540 }
20541 /*
20542 * TODO: Obtaining and setting the redefinition state is really
20543 * clumsy.
20544 */
20545 wasRedefined = 0;
20546 switch (item->type) {
20547 case XML_SCHEMA_TYPE_COMPLEX:
20548 case XML_SCHEMA_TYPE_SIMPLE:
20549 if ((WXS_TYPE_CAST prev)->flags &
20550 XML_SCHEMAS_TYPE_REDEFINED)
20551 {
20552 wasRedefined = 1;
20553 break;
20554 }
20555 /* Mark it as redefined. */
20556 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20557 /*
20558 * Assign the redefined type to the
20559 * base type of the redefining type.
20560 * TODO: How
20561 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020562 ((xmlSchemaTypePtr) item)->baseType =
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020563 (xmlSchemaTypePtr) prev;
20564 break;
20565 case XML_SCHEMA_TYPE_GROUP:
20566 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20567 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20568 {
20569 wasRedefined = 1;
20570 break;
20571 }
20572 /* Mark it as redefined. */
20573 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20574 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20575 if (redef->reference != NULL) {
20576 /*
20577 * Overwrite the QName-reference with the
20578 * referenced model group def.
20579 */
20580 (WXS_PTC_CAST redef->reference)->children =
20581 WXS_TREE_CAST prev;
20582 }
20583 redef->target = prev;
20584 break;
20585 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20586 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20587 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20588 {
20589 wasRedefined = 1;
20590 break;
20591 }
20592 (WXS_ATTR_GROUP_CAST prev)->flags |=
20593 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20594 if (redef->reference != NULL) {
20595 /*
20596 * Assign the redefined attribute group to the
20597 * QName-reference component.
20598 * This is the easy case, since we will just
20599 * expand the redefined group.
20600 */
20601 (WXS_QNAME_CAST redef->reference)->item = prev;
20602 redef->target = NULL;
20603 } else {
20604 /*
20605 * This is the complicated case: we need
20606 * to apply src-redefine (7.2.2) at a later
20607 * stage, i.e. when attribute group references
20608 * have beed expanded and simple types have
20609 * beed fixed.
20610 */
20611 redef->target = prev;
20612 }
20613 break;
20614 default:
20615 PERROR_INT("xmlSchemaResolveRedefReferences",
20616 "Unexpected redefined component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020617 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020618 }
20619 if (wasRedefined) {
20620 xmlChar *str = NULL;
20621 xmlNodePtr node;
20622
20623 if (redef->reference)
20624 node = WXS_ITEM_NODE(redef->reference);
20625 else
20626 node = WXS_ITEM_NODE(redef->item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020627
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020628 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20629 /* TODO: error code. */
20630 XML_SCHEMAP_SRC_REDEFINE,
20631 node, NULL,
20632 "The referenced %s was already redefined. Multiple "
20633 "redefinition of the same component is not supported",
20634 xmlSchemaGetComponentDesignation(&str, prev),
20635 NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000020636 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020637 err = pctxt->err;
20638 redef = redef->next;
20639 continue;
20640 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020641 redef = redef->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020642 } while (redef != NULL);
20643
20644 return(err);
20645}
20646
20647static int
20648xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20649{
20650 int err = 0;
20651 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20652 xmlSchemaBasicItemPtr item;
20653
20654 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020655 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020656
20657 do {
20658 if (redef->target == NULL) {
20659 redef = redef->next;
20660 continue;
20661 }
20662 item = redef->item;
Daniel Veillarddee23482008-04-11 12:58:43 +000020663
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020664 switch (item->type) {
20665 case XML_SCHEMA_TYPE_SIMPLE:
20666 case XML_SCHEMA_TYPE_COMPLEX:
20667 /*
20668 * Since the spec wants the {name} of the redefined
20669 * type to be 'absent', we'll NULL it.
20670 */
20671 (WXS_TYPE_CAST redef->target)->name = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020672
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020673 /*
20674 * TODO: Seems like there's nothing more to do. The normal
20675 * inheritance mechanism is used. But not 100% sure.
20676 */
20677 break;
20678 case XML_SCHEMA_TYPE_GROUP:
20679 /*
20680 * URGENT TODO:
20681 * SPEC src-redefine:
20682 * (6.2.2) "The {model group} of the model group definition
20683 * which corresponds to it per XML Representation of Model
Jan Pokorný761c9e92013-11-29 23:26:27 +010020684 * Group Definition Schema Components ($3.7.2) must be a
20685 * `valid restriction` of the {model group} of that model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020686 * group definition in I, as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010020687 * (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020688 */
20689 break;
20690 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20691 /*
20692 * SPEC src-redefine:
20693 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20694 * the attribute group definition which corresponds to it
20695 * per XML Representation of Attribute Group Definition Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020696 * Components ($3.6.2) must be `valid restrictions` of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020697 * {attribute uses} and {attribute wildcard} of that attribute
20698 * group definition in I, as defined in clause 2, clause 3 and
20699 * clause 4 of Derivation Valid (Restriction, Complex)
Jan Pokorný761c9e92013-11-29 23:26:27 +010020700 * ($3.4.6) (where references to the base type definition are
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020701 * understood as references to the attribute group definition
20702 * in I)."
20703 */
20704 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20705 XML_SCHEMA_ACTION_REDEFINE,
20706 item, redef->target,
20707 (WXS_ATTR_GROUP_CAST item)->attrUses,
20708 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20709 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20710 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20711 if (err == -1)
20712 return(-1);
20713 break;
20714 default:
20715 break;
20716 }
20717 redef = redef->next;
20718 } while (redef != NULL);
20719 return(0);
20720}
Daniel Veillarddee23482008-04-11 12:58:43 +000020721
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020722
20723static int
20724xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20725 xmlSchemaBucketPtr bucket)
20726{
20727 xmlSchemaBasicItemPtr item;
20728 int err;
20729 xmlHashTablePtr *table;
20730 const xmlChar *name;
20731 int i;
20732
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020733#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020734 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20735 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20736 else \
20737 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20738
20739 /*
20740 * Add global components to the schema's hash tables.
20741 * This is the place where duplicate components will be
20742 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020743 * TODO: I think normally we should support imports of the
20744 * same namespace from multiple locations. We don't do currently,
20745 * but if we do then according to:
20746 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20747 * we would need, if imported directly, to import redefined
20748 * components as well to be able to catch clashing components.
20749 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020750 */
20751 if (bucket == NULL)
20752 return(-1);
20753 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20754 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000020755 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20756
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020757 for (i = 0; i < bucket->globals->nbItems; i++) {
20758 item = bucket->globals->items[i];
20759 table = NULL;
20760 switch (item->type) {
20761 case XML_SCHEMA_TYPE_COMPLEX:
20762 case XML_SCHEMA_TYPE_SIMPLE:
20763 if (WXS_REDEFINED_TYPE(item))
20764 continue;
20765 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020766 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020767 break;
20768 case XML_SCHEMA_TYPE_ELEMENT:
20769 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020770 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020771 break;
20772 case XML_SCHEMA_TYPE_ATTRIBUTE:
20773 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020774 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020775 break;
20776 case XML_SCHEMA_TYPE_GROUP:
20777 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20778 continue;
20779 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020780 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020781 break;
20782 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20783 if (WXS_REDEFINED_ATTR_GROUP(item))
20784 continue;
20785 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020786 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020787 break;
20788 case XML_SCHEMA_TYPE_IDC_KEY:
20789 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20790 case XML_SCHEMA_TYPE_IDC_KEYREF:
20791 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020792 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020793 break;
20794 case XML_SCHEMA_TYPE_NOTATION:
20795 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020796 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +000020797 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020798 default:
20799 PERROR_INT("xmlSchemaAddComponents",
20800 "Unexpected global component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020801 continue;
20802 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020803 if (*table == NULL) {
20804 *table = xmlHashCreateDict(10, pctxt->dict);
20805 if (*table == NULL) {
20806 PERROR_INT("xmlSchemaAddComponents",
20807 "failed to create a component hash table");
20808 return(-1);
20809 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020810 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020811 err = xmlHashAddEntry(*table, name, item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020812 if (err != 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020813 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020814
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020815 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20816 XML_SCHEMAP_REDEFINED_TYPE,
20817 WXS_ITEM_NODE(item),
20818 WXS_BASIC_CAST item,
20819 "A global %s '%s' does already exist",
20820 WXS_ITEM_TYPE_NAME(item),
20821 xmlSchemaGetComponentQName(&str, item));
Daniel Veillarddee23482008-04-11 12:58:43 +000020822 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020823 }
20824 }
20825 /*
20826 * Process imported/included schemas.
20827 */
20828 if (bucket->relations != NULL) {
20829 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20830 do {
20831 if ((rel->bucket != NULL) &&
20832 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20833 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20834 return(-1);
20835 }
20836 rel = rel->next;
20837 } while (rel != NULL);
20838 }
20839 return(0);
20840}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020841
20842static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020843xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20844 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020845{
20846 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20847 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020848 int nbItems, i, ret = 0;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020849 xmlSchemaBucketPtr oldbucket = con->bucket;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020850 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020851
20852#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20853
20854 if ((con->pending == NULL) ||
20855 (con->pending->nbItems == 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000020856 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020857
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020858 /*
20859 * Since xmlSchemaFixupComplexType() will create new particles
20860 * (local components), and those particle components need a bucket
20861 * on the constructor, we'll assure here that the constructor has
20862 * a bucket.
Daniel Veillarddee23482008-04-11 12:58:43 +000020863 * TODO: Think about storing locals _only_ on the main bucket.
20864 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020865 if (con->bucket == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020866 con->bucket = rootBucket;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020867
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020868 /* TODO:
20869 * SPEC (src-redefine):
20870 * (6.2) "If it has no such self-reference, then all of the
20871 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000020872
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020873 * (6.2.2) The {model group} of the model group definition which
20874 * corresponds to it per XML Representation of Model Group
Jan Pokorný761c9e92013-11-29 23:26:27 +010020875 * Definition Schema Components ($3.7.2) must be a `valid
20876 * restriction` of the {model group} of that model group definition
20877 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020878 */
20879 xmlSchemaCheckSRCRedefineFirst(pctxt);
20880
20881 /*
20882 * Add global components to the schemata's hash tables.
Daniel Veillarddee23482008-04-11 12:58:43 +000020883 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020884 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020885
20886 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020887 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20888 nbItems = con->pending->nbItems;
20889 /*
20890 * Now that we have parsed *all* the schema document(s) and converted
20891 * them to schema components, we can resolve references, apply component
20892 * constraints, create the FSA from the content model, etc.
Daniel Veillarddee23482008-04-11 12:58:43 +000020893 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020894 /*
20895 * Resolve references of..
20896 *
20897 * 1. element declarations:
20898 * - the type definition
20899 * - the substitution group affiliation
20900 * 2. simple/complex types:
20901 * - the base type definition
20902 * - the memberTypes of union types
20903 * - the itemType of list types
20904 * 3. attributes declarations and attribute uses:
20905 * - the type definition
20906 * - if an attribute use, then the attribute declaration
20907 * 4. attribute group references:
20908 * - the attribute group definition
20909 * 5. particles:
20910 * - the term of the particle (e.g. a model group)
20911 * 6. IDC key-references:
20912 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020913 * 7. Attribute prohibitions which had a "ref" attribute.
Daniel Veillarddee23482008-04-11 12:58:43 +000020914 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020915 for (i = 0; i < nbItems; i++) {
20916 item = items[i];
20917 switch (item->type) {
20918 case XML_SCHEMA_TYPE_ELEMENT:
20919 xmlSchemaResolveElementReferences(
20920 (xmlSchemaElementPtr) item, pctxt);
20921 FIXHFAILURE;
20922 break;
20923 case XML_SCHEMA_TYPE_COMPLEX:
20924 case XML_SCHEMA_TYPE_SIMPLE:
20925 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020926 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020927 FIXHFAILURE;
20928 break;
20929 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020930 xmlSchemaResolveAttrTypeReferences(
20931 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020932 FIXHFAILURE;
20933 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020934 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20935 xmlSchemaResolveAttrUseReferences(
20936 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020937 FIXHFAILURE;
20938 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020939 case XML_SCHEMA_EXTRA_QNAMEREF:
Daniel Veillarddee23482008-04-11 12:58:43 +000020940 if ((WXS_QNAME_CAST item)->itemType ==
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020941 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20942 {
20943 xmlSchemaResolveAttrGroupReferences(
20944 WXS_QNAME_CAST item, pctxt);
20945 }
20946 FIXHFAILURE;
20947 break;
20948 case XML_SCHEMA_TYPE_SEQUENCE:
20949 case XML_SCHEMA_TYPE_CHOICE:
20950 case XML_SCHEMA_TYPE_ALL:
20951 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20952 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020953 FIXHFAILURE;
20954 break;
20955 case XML_SCHEMA_TYPE_IDC_KEY:
20956 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20957 case XML_SCHEMA_TYPE_IDC_KEYREF:
20958 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020959 (xmlSchemaIDCPtr) item, pctxt);
20960 FIXHFAILURE;
20961 break;
20962 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20963 /*
20964 * Handle attribue prohibition which had a
20965 * "ref" attribute.
20966 */
20967 xmlSchemaResolveAttrUseProhibReferences(
20968 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020969 FIXHFAILURE;
20970 break;
20971 default:
20972 break;
20973 }
20974 }
20975 if (pctxt->nberrors != 0)
20976 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000020977
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020978 /*
20979 * Now that all references are resolved we
20980 * can check for circularity of...
Daniel Veillarddee23482008-04-11 12:58:43 +000020981 * 1. the base axis of type definitions
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020982 * 2. nested model group definitions
20983 * 3. nested attribute group definitions
20984 * TODO: check for circual substitution groups.
20985 */
20986 for (i = 0; i < nbItems; i++) {
20987 item = items[i];
20988 /*
20989 * Let's better stop on the first error here.
20990 */
20991 switch (item->type) {
20992 case XML_SCHEMA_TYPE_COMPLEX:
20993 case XML_SCHEMA_TYPE_SIMPLE:
20994 xmlSchemaCheckTypeDefCircular(
20995 (xmlSchemaTypePtr) item, pctxt);
20996 FIXHFAILURE;
20997 if (pctxt->nberrors != 0)
20998 goto exit_error;
20999 break;
21000 case XML_SCHEMA_TYPE_GROUP:
21001 xmlSchemaCheckGroupDefCircular(
21002 (xmlSchemaModelGroupDefPtr) item, pctxt);
21003 FIXHFAILURE;
21004 if (pctxt->nberrors != 0)
21005 goto exit_error;
21006 break;
21007 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21008 xmlSchemaCheckAttrGroupCircular(
21009 (xmlSchemaAttributeGroupPtr) item, pctxt);
21010 FIXHFAILURE;
21011 if (pctxt->nberrors != 0)
21012 goto exit_error;
21013 break;
21014 default:
21015 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000021016 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021017 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021018 if (pctxt->nberrors != 0)
21019 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021020 /*
21021 * Model group definition references:
21022 * Such a reference is reflected by a particle at the component
21023 * level. Until now the 'term' of such particles pointed
21024 * to the model group definition; this was done, in order to
21025 * ease circularity checks. Now we need to set the 'term' of
21026 * such particles to the model group of the model group definition.
21027 */
21028 for (i = 0; i < nbItems; i++) {
21029 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021030 switch (item->type) {
21031 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillarddee23482008-04-11 12:58:43 +000021032 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021033 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21034 WXS_MODEL_GROUP_CAST item);
21035 break;
21036 default:
21037 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021038 }
21039 }
21040 if (pctxt->nberrors != 0)
21041 goto exit_error;
21042 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021043 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021044 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021045 for (i = 0; i < nbItems; i++) {
21046 item = items[i];
21047 switch (item->type) {
21048 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21049 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21050 WXS_ATTR_GROUP_HAS_REFS(item))
21051 {
21052 xmlSchemaAttributeGroupExpandRefs(pctxt,
21053 WXS_ATTR_GROUP_CAST item);
21054 FIXHFAILURE;
21055 }
21056 break;
21057 default:
21058 break;
21059 }
21060 }
21061 if (pctxt->nberrors != 0)
21062 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021063 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021064 * First compute the variety of simple types. This is needed as
21065 * a seperate step, since otherwise we won't be able to detect
21066 * circular union types in all cases.
21067 */
21068 for (i = 0; i < nbItems; i++) {
21069 item = items[i];
21070 switch (item->type) {
21071 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021072 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021073 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21074 (xmlSchemaTypePtr) item);
21075 FIXHFAILURE;
21076 }
21077 break;
21078 default:
21079 break;
21080 }
21081 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021082 if (pctxt->nberrors != 0)
21083 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021084 /*
21085 * Detect circular union types. Note that this needs the variety to
21086 * be already computed.
21087 */
21088 for (i = 0; i < nbItems; i++) {
21089 item = items[i];
21090 switch (item->type) {
21091 case XML_SCHEMA_TYPE_SIMPLE:
21092 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021093 xmlSchemaCheckUnionTypeDefCircular(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021094 (xmlSchemaTypePtr) item);
21095 FIXHFAILURE;
21096 }
21097 break;
21098 default:
21099 break;
21100 }
21101 }
21102 if (pctxt->nberrors != 0)
21103 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021104
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021105 /*
21106 * Do the complete type fixup for simple types.
21107 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021108 for (i = 0; i < nbItems; i++) {
21109 item = items[i];
21110 switch (item->type) {
21111 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021112 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21113 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21114 FIXHFAILURE;
21115 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021116 break;
21117 default:
21118 break;
21119 }
21120 }
21121 if (pctxt->nberrors != 0)
21122 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021123 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021124 * At this point we need build and check all simple types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021125 */
21126 /*
21127 * Apply contraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021128 */
21129 for (i = 0; i < nbItems; i++) {
21130 item = items[i];
21131 switch (item->type) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021132 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021133 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21134 FIXHFAILURE;
Daniel Veillarddee23482008-04-11 12:58:43 +000021135 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021136 default:
21137 break;
21138 }
21139 }
21140 if (pctxt->nberrors != 0)
21141 goto exit_error;
21142 /*
21143 * Apply constraints for attribute uses.
Daniel Veillarddee23482008-04-11 12:58:43 +000021144 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021145 for (i = 0; i < nbItems; i++) {
21146 item = items[i];
21147 switch (item->type) {
21148 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21149 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21150 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21151 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021152 FIXHFAILURE;
21153 }
21154 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021155 default:
21156 break;
21157 }
21158 }
21159 if (pctxt->nberrors != 0)
21160 goto exit_error;
21161
21162 /*
21163 * Apply constraints for attribute group definitions.
21164 */
21165 for (i = 0; i < nbItems; i++) {
21166 item = items[i];
21167 switch (item->type) {
21168 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21169 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21170 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21171 {
21172 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21173 FIXHFAILURE;
21174 }
21175 break;
21176 default:
21177 break;
21178 }
21179 }
21180 if (pctxt->nberrors != 0)
21181 goto exit_error;
21182
21183 /*
21184 * Apply constraints for redefinitions.
21185 */
21186 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21187 xmlSchemaCheckSRCRedefineSecond(pctxt);
21188 if (pctxt->nberrors != 0)
21189 goto exit_error;
21190
Daniel Veillarddee23482008-04-11 12:58:43 +000021191 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021192 * Complex types are builded and checked.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021193 */
21194 for (i = 0; i < nbItems; i++) {
21195 item = con->pending->items[i];
21196 switch (item->type) {
21197 case XML_SCHEMA_TYPE_COMPLEX:
21198 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21199 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21200 FIXHFAILURE;
21201 }
21202 break;
21203 default:
21204 break;
21205 }
21206 }
21207 if (pctxt->nberrors != 0)
21208 goto exit_error;
21209
21210 /*
21211 * The list could have changed, since xmlSchemaFixupComplexType()
21212 * will create particles and model groups in some cases.
21213 */
21214 items = (xmlSchemaTreeItemPtr *) con->pending->items;
Daniel Veillarddee23482008-04-11 12:58:43 +000021215 nbItems = con->pending->nbItems;
21216
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021217 /*
21218 * Apply some constraints for element declarations.
21219 */
21220 for (i = 0; i < nbItems; i++) {
21221 item = items[i];
21222 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021223 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021224 elemDecl = (xmlSchemaElementPtr) item;
Daniel Veillarddee23482008-04-11 12:58:43 +000021225
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021226 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21227 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021228 xmlSchemaCheckElementDeclComponent(
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021229 (xmlSchemaElementPtr) elemDecl, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021230 FIXHFAILURE;
21231 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021232
21233#ifdef WXS_ELEM_DECL_CONS_ENABLED
21234 /*
21235 * Schema Component Constraint: Element Declarations Consistent
21236 * Apply this constraint to local types of element declarations.
21237 */
21238 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21239 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21240 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21241 {
21242 xmlSchemaCheckElementDeclConsistent(pctxt,
21243 WXS_BASIC_CAST elemDecl,
21244 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21245 NULL, NULL, 0);
21246 }
21247#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021248 break;
21249 default:
21250 break;
21251 }
21252 }
21253 if (pctxt->nberrors != 0)
21254 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021255
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021256 /*
21257 * Finally we can build the automaton from the content model of
21258 * complex types.
21259 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021260
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021261 for (i = 0; i < nbItems; i++) {
21262 item = items[i];
21263 switch (item->type) {
21264 case XML_SCHEMA_TYPE_COMPLEX:
21265 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021266 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021267 break;
21268 default:
21269 break;
21270 }
21271 }
21272 if (pctxt->nberrors != 0)
21273 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021274 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021275 * URGENT TODO: cos-element-consistent
Daniel Veillarddee23482008-04-11 12:58:43 +000021276 */
21277 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021278
Daniel Veillarddee23482008-04-11 12:58:43 +000021279exit_error:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021280 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021281 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021282
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021283exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021284 ret = -1;
21285
21286exit:
21287 /*
21288 * Reset the constructor. This is needed for XSI acquisition, since
21289 * those items will be processed over and over again for every XSI
21290 * if not cleared here.
21291 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021292 con->bucket = oldbucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000021293 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021294 if (con->substGroups != NULL) {
21295 xmlHashFree(con->substGroups,
21296 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21297 con->substGroups = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000021298 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021299 if (con->redefs != NULL) {
21300 xmlSchemaRedefListFree(con->redefs);
21301 con->redefs = NULL;
21302 }
21303 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021304}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021305/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021306 * xmlSchemaParse:
21307 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021308 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021309 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000021310 * XML Shema struture which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000021311 *
21312 * Returns the internal XML Schema structure built from the resource or
21313 * NULL in case of error
21314 */
21315xmlSchemaPtr
21316xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21317{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021318 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021319 xmlSchemaBucketPtr bucket = NULL;
21320 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021321
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021322 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021323 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021324 * the API; i.e. not automatically by the validated instance document.
21325 */
21326
Daniel Veillard4255d502002-04-16 15:50:10 +000021327 xmlSchemaInitTypes();
21328
Daniel Veillard6045c902002-10-09 21:13:59 +000021329 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021330 return (NULL);
21331
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021332 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021333 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021334 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021335 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021336
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021337 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021338 mainSchema = xmlSchemaNewSchema(ctxt);
21339 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021340 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021341 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021342 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021343 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021344 if (ctxt->constructor == NULL) {
21345 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21346 if (ctxt->constructor == NULL)
21347 return(NULL);
21348 /* Take ownership of the constructor to be able to free it. */
21349 ctxt->ownsConstructor = 1;
21350 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021351 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021352 /*
21353 * Locate and add the schema document.
21354 */
21355 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21356 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21357 NULL, NULL, &bucket);
21358 if (res == -1)
21359 goto exit_failure;
21360 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021361 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021362
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021363 if (bucket == NULL) {
21364 /* TODO: Error code, actually we failed to *locate* the schema. */
Daniel Veillarddee23482008-04-11 12:58:43 +000021365 if (ctxt->URL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021366 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21367 NULL, NULL,
21368 "Failed to locate the main schema resource at '%s'",
21369 ctxt->URL, NULL);
21370 else
21371 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21372 NULL, NULL,
21373 "Failed to locate the main schema resource",
21374 NULL, NULL);
21375 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021376 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021377 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021378 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021379 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021380 if (ctxt->nberrors != 0)
21381 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021382
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021383 mainSchema->doc = bucket->doc;
21384 mainSchema->preserve = ctxt->preserve;
Daniel Veillarddee23482008-04-11 12:58:43 +000021385
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021386 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021387
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021388 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021389 goto exit_failure;
21390
21391 /*
21392 * TODO: This is not nice, since we cannot distinguish from the
21393 * result if there was an internal error or not.
21394 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021395exit:
21396 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021397 if (mainSchema) {
21398 xmlSchemaFree(mainSchema);
21399 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021400 }
21401 if (ctxt->constructor) {
21402 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21403 ctxt->constructor = NULL;
21404 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021405 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021406 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021407 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021408 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021409exit_failure:
Daniel Veillarddee23482008-04-11 12:58:43 +000021410 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021411 * Quite verbose, but should catch internal errors, which were
21412 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021413 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021414 if (mainSchema) {
21415 xmlSchemaFree(mainSchema);
21416 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021417 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021418 if (ctxt->constructor) {
21419 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21420 ctxt->constructor = NULL;
21421 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021422 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021423 PERROR_INT2("xmlSchemaParse",
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020021424 "An internal error occurred");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021425 ctxt->schema = NULL;
21426 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021427}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021428
Daniel Veillard4255d502002-04-16 15:50:10 +000021429/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021430 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021431 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021432 * @err: the error callback
21433 * @warn: the warning callback
21434 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021435 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021436 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021437 */
21438void
21439xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021440 xmlSchemaValidityErrorFunc err,
21441 xmlSchemaValidityWarningFunc warn, void *ctx)
21442{
Daniel Veillard4255d502002-04-16 15:50:10 +000021443 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021444 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021445 ctxt->error = err;
21446 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021447 ctxt->errCtxt = ctx;
21448 if (ctxt->vctxt != NULL)
21449 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21450}
21451
21452/**
21453 * xmlSchemaSetParserStructuredErrors:
21454 * @ctxt: a schema parser context
21455 * @serror: the structured error function
21456 * @ctx: the functions context
21457 *
21458 * Set the structured error callback
21459 */
21460void
21461xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21462 xmlStructuredErrorFunc serror,
21463 void *ctx)
21464{
21465 if (ctxt == NULL)
21466 return;
21467 ctxt->serror = serror;
21468 ctxt->errCtxt = ctx;
21469 if (ctxt->vctxt != NULL)
21470 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021471}
21472
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021473/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021474 * xmlSchemaGetParserErrors:
21475 * @ctxt: a XMl-Schema parser context
21476 * @err: the error callback result
21477 * @warn: the warning callback result
21478 * @ctx: contextual data for the callbacks result
21479 *
21480 * Get the callback information used to handle errors for a parser context
21481 *
21482 * Returns -1 in case of failure, 0 otherwise
21483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021484int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021485xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021486 xmlSchemaValidityErrorFunc * err,
21487 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021488{
21489 if (ctxt == NULL)
21490 return(-1);
21491 if (err != NULL)
21492 *err = ctxt->error;
21493 if (warn != NULL)
21494 *warn = ctxt->warning;
21495 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021496 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021497 return(0);
21498}
21499
21500/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021501 * xmlSchemaFacetTypeToString:
21502 * @type: the facet type
21503 *
21504 * Convert the xmlSchemaTypeType to a char string.
21505 *
21506 * Returns the char string representation of the facet type if the
21507 * type is a facet and an "Internal Error" string otherwise.
21508 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021509static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021510xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21511{
21512 switch (type) {
21513 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021514 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021515 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021516 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021517 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021518 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021519 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021520 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021521 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021522 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021523 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021524 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021525 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021526 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021527 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021528 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021529 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021530 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021531 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021532 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021533 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021534 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021535 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021536 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021537 default:
21538 break;
21539 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021540 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021541}
21542
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021543static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021544xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21545{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021546 /*
21547 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021548 * from xsd:string.
21549 */
21550 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021551 /*
21552 * Note that we assume a whitespace of preserve for anySimpleType.
21553 */
21554 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21555 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21556 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021557 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021558 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021559 else {
21560 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010021561 * For all `atomic` datatypes other than string (and types `derived`
21562 * by `restriction` from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021563 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021564 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021566 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021567 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021568 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021569 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021570 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021571 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021572 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021573 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021574 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021575 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021576 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21577 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21578 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21579 return (XML_SCHEMA_WHITESPACE_REPLACE);
21580 else
21581 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021582 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021583 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021584}
21585
Daniel Veillard4255d502002-04-16 15:50:10 +000021586/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021587 * *
21588 * Simple type validation *
21589 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021590 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021591
Daniel Veillard4255d502002-04-16 15:50:10 +000021592
21593/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021594 * *
21595 * DOM Validation code *
21596 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021597 ************************************************************************/
21598
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021599/**
21600 * xmlSchemaAssembleByLocation:
21601 * @pctxt: a schema parser context
21602 * @vctxt: a schema validation context
21603 * @schema: the existing schema
21604 * @node: the node that fired the assembling
21605 * @nsName: the namespace name of the new schema
21606 * @location: the location of the schema
21607 *
21608 * Expands an existing schema by an additional schema.
21609 *
21610 * Returns 0 if the new schema is correct, a positive error code
21611 * number otherwise and -1 in case of an internal or API error.
21612 */
21613static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021614xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021615 xmlSchemaPtr schema,
21616 xmlNodePtr node,
21617 const xmlChar *nsName,
21618 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021619{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021620 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021621 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021622 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021623
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021624 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021625 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021626
21627 if (vctxt->pctxt == NULL) {
21628 VERROR_INT("xmlSchemaAssembleByLocation",
21629 "no parser context available");
21630 return(-1);
21631 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021632 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021633 if (pctxt->constructor == NULL) {
21634 PERROR_INT("xmlSchemaAssembleByLocation",
21635 "no constructor");
21636 return(-1);
21637 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021638 /*
21639 * Acquire the schema document.
21640 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021641 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21642 location, node);
21643 /*
21644 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21645 * the process will automatically change this to
21646 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21647 */
21648 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Daniel Veillarddee23482008-04-11 12:58:43 +000021649 location, NULL, NULL, 0, node, NULL, nsName,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021650 &bucket);
21651 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021652 return(ret);
21653 if (bucket == NULL) {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021654 /*
21655 * Generate a warning that the document could not be located.
21656 */
21657 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21658 node, NULL,
21659 "The document at location '%s' could not be acquired",
21660 location, NULL, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021661 return(ret);
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021662 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021663 /*
21664 * The first located schema will be handled as if all other
21665 * schemas imported by XSI were imported by this first schema.
21666 */
21667 if ((bucket != NULL) &&
21668 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21669 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21670 /*
21671 * TODO: Is this handled like an import? I.e. is it not an error
21672 * if the schema cannot be located?
21673 */
21674 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21675 return(0);
21676 /*
21677 * We will reuse the parser context for every schema imported
21678 * directly via XSI. So reset the context.
21679 */
21680 pctxt->nberrors = 0;
21681 pctxt->err = 0;
21682 pctxt->doc = bucket->doc;
Daniel Veillarddee23482008-04-11 12:58:43 +000021683
21684 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021685 if (ret == -1) {
21686 pctxt->doc = NULL;
21687 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021688 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021689 /* Paranoid error channelling. */
21690 if ((ret == 0) && (pctxt->nberrors != 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000021691 ret = pctxt->err;
21692 if (pctxt->nberrors == 0) {
21693 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021694 * Only bother to fixup pending components, if there was
21695 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021696 * For every XSI acquired schema (and its sub-schemata) we will
21697 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021698 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021699 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021700 ret = pctxt->err;
21701 /*
21702 * Not nice, but we need somehow to channel the schema parser
21703 * error to the validation context.
21704 */
21705 if ((ret != 0) && (vctxt->err == 0))
21706 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021707 vctxt->nberrors += pctxt->nberrors;
21708 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000021709 /* Add to validation error sum. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021710 vctxt->nberrors += pctxt->nberrors;
21711 }
21712 pctxt->doc = NULL;
21713 return(ret);
21714exit_failure:
21715 pctxt->doc = NULL;
21716 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021717}
21718
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021719static xmlSchemaAttrInfoPtr
Daniel Veillarddee23482008-04-11 12:58:43 +000021720xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021721 int metaType)
21722{
21723 if (vctxt->nbAttrInfos == 0)
21724 return (NULL);
21725 {
21726 int i;
21727 xmlSchemaAttrInfoPtr iattr;
21728
21729 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21730 iattr = vctxt->attrInfos[i];
21731 if (iattr->metaType == metaType)
21732 return (iattr);
21733 }
21734
21735 }
21736 return (NULL);
21737}
21738
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021739/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021740 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021741 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021742 *
21743 * Expands an existing schema by an additional schema using
21744 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21745 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21746 * must be set to 1.
21747 *
21748 * Returns 0 if the new schema is correct, a positive error code
21749 * number otherwise and -1 in case of an internal or API error.
21750 */
21751static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021752xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021753{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021754 const xmlChar *cur, *end;
21755 const xmlChar *nsname = NULL, *location;
21756 int count = 0;
21757 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021758 xmlSchemaAttrInfoPtr iattr;
21759
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021760 /*
21761 * Parse the value; we will assume an even number of values
21762 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021763 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021764 * URGENT TODO: !! This needs to work for both
21765 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21766 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021767 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021768 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21769 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21770 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021771 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021772 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21773 if (iattr == NULL)
21774 return (0);
21775 cur = iattr->value;
21776 do {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021777 /*
21778 * TODO: Move the string parsing mechanism away from here.
21779 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021780 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021781 /*
21782 * Get the namespace name.
21783 */
21784 while (IS_BLANK_CH(*cur))
21785 cur++;
21786 end = cur;
21787 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21788 end++;
21789 if (end == cur)
21790 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021791 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021792 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021793 cur = end;
21794 }
21795 /*
21796 * Get the URI.
21797 */
21798 while (IS_BLANK_CH(*cur))
21799 cur++;
21800 end = cur;
21801 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21802 end++;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021803 if (end == cur) {
21804 if (iattr->metaType ==
21805 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21806 {
21807 /*
21808 * If using @schemaLocation then tuples are expected.
21809 * I.e. the namespace name *and* the document's URI.
Daniel Veillarddee23482008-04-11 12:58:43 +000021810 */
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021811 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21812 iattr->node, NULL,
21813 "The value must consist of tuples: the target namespace "
21814 "name and the document's URI", NULL, NULL, NULL);
21815 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021816 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021817 }
21818 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021819 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021820 cur = end;
21821 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21822 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021823 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021824 VERROR_INT("xmlSchemaAssembleByXSI",
21825 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021826 return (-1);
21827 }
21828 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021829 return (ret);
21830}
21831
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021832static const xmlChar *
21833xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21834 const xmlChar *prefix)
21835{
21836 if (vctxt->sax != NULL) {
21837 int i, j;
21838 xmlSchemaNodeInfoPtr inode;
Daniel Veillarddee23482008-04-11 12:58:43 +000021839
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021840 for (i = vctxt->depth; i >= 0; i--) {
21841 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21842 inode = vctxt->elemInfos[i];
21843 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21844 if (((prefix == NULL) &&
21845 (inode->nsBindings[j] == NULL)) ||
21846 ((prefix != NULL) && xmlStrEqual(prefix,
21847 inode->nsBindings[j]))) {
21848
21849 /*
21850 * Note that the namespace bindings are already
21851 * in a string dict.
21852 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021853 return (inode->nsBindings[j+1]);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021854 }
21855 }
21856 }
21857 }
21858 return (NULL);
Daniel Veillard438ebbd2008-05-12 12:58:46 +000021859#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021860 } else if (vctxt->reader != NULL) {
21861 xmlChar *nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +000021862
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021863 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21864 if (nsName != NULL) {
21865 const xmlChar *ret;
21866
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021867 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21868 xmlFree(nsName);
21869 return (ret);
21870 } else
21871 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021872#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021873 } else {
21874 xmlNsPtr ns;
21875
21876 if ((vctxt->inode->node == NULL) ||
21877 (vctxt->inode->node->doc == NULL)) {
21878 VERROR_INT("xmlSchemaLookupNamespace",
21879 "no node or node's doc avaliable");
21880 return (NULL);
21881 }
21882 ns = xmlSearchNs(vctxt->inode->node->doc,
21883 vctxt->inode->node, prefix);
21884 if (ns != NULL)
21885 return (ns->href);
21886 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021887 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021888}
21889
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021890/*
21891* This one works on the schema of the validation context.
21892*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021893static int
Daniel Veillarddee23482008-04-11 12:58:43 +000021894xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021895 xmlSchemaPtr schema,
21896 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021897 const xmlChar *value,
21898 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021899 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021900{
21901 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021902
21903 if (vctxt && (vctxt->schema == NULL)) {
21904 VERROR_INT("xmlSchemaValidateNotation",
21905 "a schema is needed on the validation context");
21906 return (-1);
21907 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021908 ret = xmlValidateQName(value, 1);
21909 if (ret != 0)
21910 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021911 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021912 xmlChar *localName = NULL;
21913 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021915 localName = xmlSplitQName2(value, &prefix);
21916 if (prefix != NULL) {
21917 const xmlChar *nsName = NULL;
21918
Daniel Veillarddee23482008-04-11 12:58:43 +000021919 if (vctxt != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021920 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21921 else if (node != NULL) {
21922 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21923 if (ns != NULL)
21924 nsName = ns->href;
21925 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021926 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021927 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021928 return (1);
21929 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021930 if (nsName == NULL) {
21931 xmlFree(prefix);
21932 xmlFree(localName);
21933 return (1);
21934 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021935 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Daniel Veillard77fbc3e2008-03-24 14:06:19 +000021936 if ((valNeeded) && (val != NULL)) {
21937 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21938 xmlStrdup(nsName));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021939 if (*val == NULL)
21940 ret = -1;
21941 }
21942 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021943 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021944 xmlFree(prefix);
21945 xmlFree(localName);
21946 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021947 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021948 if (valNeeded && (val != NULL)) {
21949 (*val) = xmlSchemaNewNOTATIONValue(
21950 BAD_CAST xmlStrdup(value), NULL);
21951 if (*val == NULL)
21952 ret = -1;
21953 }
21954 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021955 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021956 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021957 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021958 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021959}
21960
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021961static int
21962xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21963 const xmlChar* lname,
21964 const xmlChar* nsname)
21965{
21966 int i;
21967
21968 lname = xmlDictLookup(vctxt->dict, lname, -1);
21969 if (lname == NULL)
21970 return(-1);
21971 if (nsname != NULL) {
21972 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21973 if (nsname == NULL)
21974 return(-1);
21975 }
21976 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21977 if ((vctxt->nodeQNames->items [i] == lname) &&
21978 (vctxt->nodeQNames->items[i +1] == nsname))
21979 /* Already there */
21980 return(i);
21981 }
21982 /* Add new entry. */
21983 i = vctxt->nodeQNames->nbItems;
21984 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21985 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21986 return(i);
21987}
21988
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021989/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021990 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021991 * Validation of identity-constraints (IDC) *
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021992 * *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021993 ************************************************************************/
21994
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021995/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021996 * xmlSchemaAugmentIDC:
21997 * @idcDef: the IDC definition
21998 *
21999 * Creates an augmented IDC definition item.
22000 *
22001 * Returns the item, or NULL on internal errors.
22002 */
22003static void
22004xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
22005 xmlSchemaValidCtxtPtr vctxt)
22006{
22007 xmlSchemaIDCAugPtr aidc;
22008
22009 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22010 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022011 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022012 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22013 NULL);
22014 return;
22015 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022016 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022017 aidc->def = idcDef;
22018 aidc->next = NULL;
22019 if (vctxt->aidcs == NULL)
22020 vctxt->aidcs = aidc;
22021 else {
22022 aidc->next = vctxt->aidcs;
22023 vctxt->aidcs = aidc;
22024 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022025 /*
22026 * Save if we have keyrefs at all.
22027 */
22028 if ((vctxt->hasKeyrefs == 0) &&
22029 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22030 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022031}
22032
22033/**
Daniel Veillard3888f472007-08-23 09:29:03 +000022034 * xmlSchemaAugmentImportedIDC:
22035 * @imported: the imported schema
22036 *
22037 * Creates an augmented IDC definition for the imported schema.
22038 */
22039static void
Daniel Veillard27f310d2017-07-27 14:06:44 +080022040xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt, xmlChar *name ATTRIBUTE_UNUSED) {
Daniel Veillard3888f472007-08-23 09:29:03 +000022041 if (imported->schema->idcDef != NULL) {
22042 xmlHashScan(imported->schema->idcDef ,
22043 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22044 }
22045}
22046
22047/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022048 * xmlSchemaIDCNewBinding:
22049 * @idcDef: the IDC definition of this binding
22050 *
22051 * Creates a new IDC binding.
22052 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022053 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022054 */
22055static xmlSchemaPSVIIDCBindingPtr
22056xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22057{
22058 xmlSchemaPSVIIDCBindingPtr ret;
22059
22060 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22061 sizeof(xmlSchemaPSVIIDCBinding));
22062 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022063 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022064 "allocating a PSVI IDC binding item", NULL);
22065 return (NULL);
22066 }
22067 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22068 ret->definition = idcDef;
22069 return (ret);
22070}
22071
22072/**
22073 * xmlSchemaIDCStoreNodeTableItem:
22074 * @vctxt: the WXS validation context
22075 * @item: the IDC node table item
22076 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022077 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022078 * They are stored to avoid copying them if IDC node-tables are merged
22079 * with corresponding parent IDC node-tables (bubbling).
22080 *
22081 * Returns 0 if succeeded, -1 on internal errors.
22082 */
22083static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022084xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022085 xmlSchemaPSVIIDCNodePtr item)
22086{
22087 /*
22088 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022089 */
22090 if (vctxt->idcNodes == NULL) {
22091 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022092 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22093 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022094 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022095 "allocating the IDC node table item list", NULL);
22096 return (-1);
22097 }
22098 vctxt->sizeIdcNodes = 20;
22099 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22100 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022101 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22102 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022103 sizeof(xmlSchemaPSVIIDCNodePtr));
22104 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022105 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022106 "re-allocating the IDC node table item list", NULL);
22107 return (-1);
22108 }
22109 }
22110 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022111
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022112 return (0);
22113}
22114
22115/**
22116 * xmlSchemaIDCStoreKey:
22117 * @vctxt: the WXS validation context
22118 * @item: the IDC key
22119 *
22120 * The validation context is used to store an IDC key.
22121 *
22122 * Returns 0 if succeeded, -1 on internal errors.
22123 */
22124static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022125xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022126 xmlSchemaPSVIIDCKeyPtr key)
22127{
22128 /*
22129 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022130 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022131 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022132 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022133 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22134 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022135 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022136 "allocating the IDC key storage list", NULL);
22137 return (-1);
22138 }
22139 vctxt->sizeIdcKeys = 40;
22140 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22141 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022142 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22143 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022144 sizeof(xmlSchemaPSVIIDCKeyPtr));
22145 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022146 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022147 "re-allocating the IDC key storage list", NULL);
22148 return (-1);
22149 }
22150 }
22151 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022152
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022153 return (0);
22154}
22155
22156/**
22157 * xmlSchemaIDCAppendNodeTableItem:
22158 * @bind: the IDC binding
22159 * @ntItem: the node-table item
22160 *
22161 * Appends the IDC node-table item to the binding.
22162 *
22163 * Returns 0 on success and -1 on internal errors.
22164 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022165static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022166xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22167 xmlSchemaPSVIIDCNodePtr ntItem)
22168{
22169 if (bind->nodeTable == NULL) {
22170 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022171 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022172 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22173 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022174 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022175 "allocating an array of IDC node-table items", NULL);
22176 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022177 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022178 } else if (bind->sizeNodes <= bind->nbNodes) {
22179 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022180 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22181 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022182 sizeof(xmlSchemaPSVIIDCNodePtr));
22183 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022184 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022185 "re-allocating an array of IDC node-table items", NULL);
22186 return(-1);
22187 }
22188 }
22189 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022190 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022191}
22192
22193/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022194 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022195 * @vctxt: the WXS validation context
22196 * @matcher: the IDC matcher
22197 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022198 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022199 * of the given matcher. If none found, a new one is created
22200 * and added to the IDC table.
22201 *
22202 * Returns an IDC binding or NULL on internal errors.
22203 */
22204static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022205xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022206 xmlSchemaIDCMatcherPtr matcher)
22207{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022208 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022209
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022210 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022211
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022212 if (ielem->idcTable == NULL) {
22213 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22214 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022215 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022216 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022217 } else {
22218 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022219
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022220 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022221 do {
22222 if (bind->definition == matcher->aidc->def)
22223 return(bind);
22224 if (bind->next == NULL) {
22225 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22226 if (bind->next == NULL)
22227 return (NULL);
22228 return(bind->next);
22229 }
22230 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022231 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022232 }
22233 return (NULL);
22234}
22235
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022236static xmlSchemaItemListPtr
22237xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22238 xmlSchemaIDCMatcherPtr matcher)
22239{
22240 if (matcher->targets == NULL)
22241 matcher->targets = xmlSchemaItemListCreate();
22242 return(matcher->targets);
22243}
22244
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022245/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022246 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022247 * @key: the IDC key
22248 *
22249 * Frees an IDC key together with its compiled value.
22250 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022251static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022252xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22253{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022254 if (key->val != NULL)
22255 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022256 xmlFree(key);
22257}
22258
22259/**
22260 * xmlSchemaIDCFreeBinding:
22261 *
22262 * Frees an IDC binding. Note that the node table-items
22263 * are not freed.
22264 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022265static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022266xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22267{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022268 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022269 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022270 if (bind->dupls != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000022271 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022272 xmlFree(bind);
22273}
22274
22275/**
22276 * xmlSchemaIDCFreeIDCTable:
22277 * @bind: the first IDC binding in the list
22278 *
22279 * Frees an IDC table, i.e. all the IDC bindings in the list.
22280 */
22281static void
22282xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22283{
22284 xmlSchemaPSVIIDCBindingPtr prev;
22285
22286 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022287 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022288 bind = bind->next;
22289 xmlSchemaIDCFreeBinding(prev);
22290 }
22291}
22292
22293/**
22294 * xmlSchemaIDCFreeMatcherList:
22295 * @matcher: the first IDC matcher in the list
22296 *
22297 * Frees a list of IDC matchers.
22298 */
22299static void
22300xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22301{
22302 xmlSchemaIDCMatcherPtr next;
22303
22304 while (matcher != NULL) {
22305 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022306 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022307 int i;
22308 for (i = 0; i < matcher->sizeKeySeqs; i++)
22309 if (matcher->keySeqs[i] != NULL)
22310 xmlFree(matcher->keySeqs[i]);
Daniel Veillarddee23482008-04-11 12:58:43 +000022311 xmlFree(matcher->keySeqs);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022312 }
22313 if (matcher->targets != NULL) {
22314 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22315 int i;
22316 xmlSchemaPSVIIDCNodePtr idcNode;
22317 /*
22318 * Node-table items for keyrefs are not stored globally
22319 * to the validation context, since they are not bubbled.
22320 * We need to free them here.
22321 */
22322 for (i = 0; i < matcher->targets->nbItems; i++) {
22323 idcNode =
22324 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22325 xmlFree(idcNode->keys);
22326 xmlFree(idcNode);
22327 }
22328 }
22329 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022330 }
22331 xmlFree(matcher);
22332 matcher = next;
22333 }
22334}
22335
22336/**
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022337 * xmlSchemaIDCReleaseMatcherList:
22338 * @vctxt: the WXS validation context
22339 * @matcher: the first IDC matcher in the list
22340 *
22341 * Caches a list of IDC matchers for reuse.
22342 */
22343static void
22344xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22345 xmlSchemaIDCMatcherPtr matcher)
22346{
22347 xmlSchemaIDCMatcherPtr next;
22348
22349 while (matcher != NULL) {
22350 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022351 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022352 int i;
22353 /*
22354 * Don't free the array, but only the content.
22355 */
22356 for (i = 0; i < matcher->sizeKeySeqs; i++)
22357 if (matcher->keySeqs[i] != NULL) {
22358 xmlFree(matcher->keySeqs[i]);
22359 matcher->keySeqs[i] = NULL;
22360 }
22361 }
22362 if (matcher->targets) {
22363 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22364 int i;
22365 xmlSchemaPSVIIDCNodePtr idcNode;
22366 /*
22367 * Node-table items for keyrefs are not stored globally
22368 * to the validation context, since they are not bubbled.
22369 * We need to free them here.
22370 */
22371 for (i = 0; i < matcher->targets->nbItems; i++) {
22372 idcNode =
22373 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22374 xmlFree(idcNode->keys);
22375 xmlFree(idcNode);
22376 }
22377 }
22378 xmlSchemaItemListFree(matcher->targets);
22379 matcher->targets = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022380 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022381 matcher->next = NULL;
22382 /*
22383 * Cache the matcher.
22384 */
22385 if (vctxt->idcMatcherCache != NULL)
22386 matcher->nextCached = vctxt->idcMatcherCache;
22387 vctxt->idcMatcherCache = matcher;
22388
22389 matcher = next;
22390 }
22391}
22392
22393/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022394 * xmlSchemaIDCAddStateObject:
22395 * @vctxt: the WXS validation context
22396 * @matcher: the IDC matcher
22397 * @sel: the XPath information
22398 * @parent: the parent "selector" state object if any
22399 * @type: "selector" or "field"
22400 *
22401 * Creates/reuses and activates state objects for the given
22402 * XPath information; if the XPath expression consists of unions,
22403 * multiple state objects are created for every unioned expression.
22404 *
22405 * Returns 0 on success and -1 on internal errors.
22406 */
22407static int
22408xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22409 xmlSchemaIDCMatcherPtr matcher,
22410 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022411 int type)
22412{
22413 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022414
22415 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022416 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022417 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022418 if (vctxt->xpathStatePool != NULL) {
22419 sto = vctxt->xpathStatePool;
22420 vctxt->xpathStatePool = sto->next;
22421 sto->next = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022422 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022423 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022424 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022425 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022426 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22427 if (sto == NULL) {
22428 xmlSchemaVErrMemory(NULL,
22429 "allocating an IDC state object", NULL);
22430 return (-1);
22431 }
22432 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
Daniel Veillarddee23482008-04-11 12:58:43 +000022433 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022434 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000022435 * Add to global list.
22436 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022437 if (vctxt->xpathStates != NULL)
22438 sto->next = vctxt->xpathStates;
22439 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022440
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022441 /*
22442 * Free the old xpath validation context.
22443 */
22444 if (sto->xpathCtxt != NULL)
22445 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22446
22447 /*
22448 * Create a new XPath (pattern) validation context.
22449 */
22450 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22451 (xmlPatternPtr) sel->xpathComp);
22452 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022453 VERROR_INT("xmlSchemaIDCAddStateObject",
22454 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022455 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000022456 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022457 sto->type = type;
22458 sto->depth = vctxt->depth;
22459 sto->matcher = matcher;
22460 sto->sel = sel;
22461 sto->nbHistory = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000022462
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022463#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022464 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22465 sto->sel->xpath);
22466#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022467 return (0);
22468}
22469
22470/**
22471 * xmlSchemaXPathEvaluate:
22472 * @vctxt: the WXS validation context
22473 * @nodeType: the nodeType of the current node
22474 *
22475 * Evaluates all active XPath state objects.
22476 *
22477 * Returns the number of IC "field" state objects which resolved to
22478 * this node, 0 if none resolved and -1 on internal errors.
22479 */
22480static int
22481xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022482 xmlElementType nodeType)
22483{
22484 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022485 int res, resolved = 0, depth = vctxt->depth;
Daniel Veillarddee23482008-04-11 12:58:43 +000022486
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022487 if (vctxt->xpathStates == NULL)
22488 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022489
22490 if (nodeType == XML_ATTRIBUTE_NODE)
22491 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022492#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022493 {
22494 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022495 xmlGenericError(xmlGenericErrorContext,
22496 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022497 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22498 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022499 FREE_AND_NULL(str)
22500 }
22501#endif
22502 /*
22503 * Process all active XPath state objects.
22504 */
22505 first = vctxt->xpathStates;
22506 sto = first;
22507 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022508#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022509 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Daniel Veillarddee23482008-04-11 12:58:43 +000022510 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022511 sto->matcher->aidc->def->name, sto->sel->xpath);
22512 else
Daniel Veillarddee23482008-04-11 12:58:43 +000022513 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022514 sto->matcher->aidc->def->name, sto->sel->xpath);
22515#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022516 if (nodeType == XML_ELEMENT_NODE)
22517 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022518 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022519 else
22520 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022522
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022523 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022524 VERROR_INT("xmlSchemaXPathEvaluate",
22525 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022526 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022527 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022528 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022529 goto next_sto;
22530 /*
22531 * Full match.
22532 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022533#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022534 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022535 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022536#endif
22537 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022538 * Register a match in the state object history.
22539 */
22540 if (sto->history == NULL) {
22541 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22542 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022543 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022544 "allocating the state object history", NULL);
22545 return(-1);
22546 }
Daniel Veillard6f9b0872006-08-12 14:09:01 +000022547 sto->sizeHistory = 5;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022548 } else if (sto->sizeHistory <= sto->nbHistory) {
22549 sto->sizeHistory *= 2;
22550 sto->history = (int *) xmlRealloc(sto->history,
22551 sto->sizeHistory * sizeof(int));
22552 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022553 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022554 "re-allocating the state object history", NULL);
22555 return(-1);
22556 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022557 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022558 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022559
22560#ifdef DEBUG_IDC
22561 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22562 vctxt->depth);
22563#endif
22564
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022565 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22566 xmlSchemaIDCSelectPtr sel;
22567 /*
22568 * Activate state objects for the IDC fields of
22569 * the IDC selector.
22570 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022571#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022572 xmlGenericError(xmlGenericErrorContext, "IDC: "
22573 "activating field states\n");
22574#endif
22575 sel = sto->matcher->aidc->def->fields;
22576 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022577 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22578 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22579 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022580 sel = sel->next;
22581 }
22582 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22583 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022584 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022585 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022586#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022587 xmlGenericError(xmlGenericErrorContext,
22588 "IDC: key found\n");
22589#endif
22590 /*
22591 * Notify that the character value of this node is
22592 * needed.
22593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022594 if (resolved == 0) {
22595 if ((vctxt->inode->flags &
22596 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22597 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22598 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022599 resolved++;
22600 }
22601next_sto:
22602 if (sto->next == NULL) {
22603 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022604 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022605 */
22606 head = first;
22607 sto = vctxt->xpathStates;
22608 } else
22609 sto = sto->next;
22610 }
22611 return (resolved);
22612}
22613
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022614static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022615xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022616 xmlChar **buf,
22617 xmlSchemaPSVIIDCKeyPtr *seq,
22618 int count)
22619{
22620 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022621 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022622
22623 *buf = xmlStrdup(BAD_CAST "[");
22624 for (i = 0; i < count; i++) {
22625 *buf = xmlStrcat(*buf, BAD_CAST "'");
Daniel Veillarddee23482008-04-11 12:58:43 +000022626 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022627 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22628 &value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022629 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022630 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022631 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022632 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22633 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022634 *buf = xmlStrcat(*buf, BAD_CAST "???");
22635 }
22636 if (i < count -1)
22637 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22638 else
22639 *buf = xmlStrcat(*buf, BAD_CAST "'");
22640 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022641 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022642 value = NULL;
22643 }
22644 }
22645 *buf = xmlStrcat(*buf, BAD_CAST "]");
22646
22647 return (BAD_CAST *buf);
22648}
22649
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022650/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022651 * xmlSchemaXPathPop:
22652 * @vctxt: the WXS validation context
22653 *
22654 * Pops all XPath states.
22655 *
22656 * Returns 0 on success and -1 on internal errors.
22657 */
22658static int
22659xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22660{
22661 xmlSchemaIDCStateObjPtr sto;
22662 int res;
22663
22664 if (vctxt->xpathStates == NULL)
22665 return(0);
22666 sto = vctxt->xpathStates;
22667 do {
22668 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22669 if (res == -1)
22670 return (-1);
22671 sto = sto->next;
22672 } while (sto != NULL);
22673 return(0);
22674}
22675
22676/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022677 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022678 * @vctxt: the WXS validation context
22679 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022680 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022681 *
22682 * Processes and pops the history items of the IDC state objects.
22683 * IDC key-sequences are validated/created on IDC bindings.
Daniel Veillarddee23482008-04-11 12:58:43 +000022684 *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022685 * Returns 0 on success and -1 on internal errors.
22686 */
22687static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022688xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022689 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022690{
22691 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022692 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022693 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022694 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022695
22696 if (vctxt->xpathStates == NULL)
22697 return (0);
22698 sto = vctxt->xpathStates;
22699
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022700#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022701 {
22702 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022703 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022704 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022705 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22706 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022707 FREE_AND_NULL(str)
22708 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022709#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022710 /*
22711 * Evaluate the state objects.
22712 */
22713 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022714 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22715 if (res == -1) {
22716 VERROR_INT("xmlSchemaXPathProcessHistory",
22717 "calling xmlStreamPop()");
22718 return (-1);
22719 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022720#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022721 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22722 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022723#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022724 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022725 goto deregister_check;
22726
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022727 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022728
22729 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022730 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022731 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022732 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022733 sto = sto->next;
22734 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000022735 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022736 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022737 /*
22738 * NOTE: According to
22739 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22740 * ... the simple-content of complex types is also allowed.
22741 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022742
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022743 if (WXS_IS_COMPLEX(type)) {
22744 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22745 /*
22746 * Sanity check for complex types with simple content.
22747 */
22748 simpleType = type->contentTypeDef;
22749 if (simpleType == NULL) {
22750 VERROR_INT("xmlSchemaXPathProcessHistory",
22751 "field resolves to a CT with simple content "
22752 "but the CT is missing the ST definition");
22753 return (-1);
22754 }
22755 } else
22756 simpleType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022757 } else
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022758 simpleType = type;
22759 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022760 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022761
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022762 /*
22763 * Not qualified if the field resolves to a node of non
22764 * simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000022765 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022766 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +000022767 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022768 WXS_BASIC_CAST sto->matcher->aidc->def,
22769 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022770 "non-simple type",
22771 sto->sel->xpath,
22772 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22773 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022774 sto->nbHistory--;
22775 goto deregister_check;
22776 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022778 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022779 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022780 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022781 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022783 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022784 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022785 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022786 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022787 sto->nbHistory--;
22788 goto deregister_check;
22789 } else {
22790 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22791 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022792 int pos, idx;
Daniel Veillarddee23482008-04-11 12:58:43 +000022793
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022794 /*
22795 * The key will be anchored on the matcher's list of
22796 * key-sequences. The position in this list is determined
22797 * by the target node's depth relative to the matcher's
22798 * depth of creation (i.e. the depth of the scope element).
Daniel Veillarddee23482008-04-11 12:58:43 +000022799 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022800 * Element Depth Pos List-entries
22801 * <scope> 0 NULL
22802 * <bar> 1 NULL
22803 * <target/> 2 2 target
22804 * <bar>
22805 * </scope>
22806 *
22807 * The size of the list is only dependant on the depth of
22808 * the tree.
22809 * An entry will be NULLed in selector_leave, i.e. when
Daniel Veillarddee23482008-04-11 12:58:43 +000022810 * we hit the target's
22811 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022812 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022813 idx = sto->sel->index;
Daniel Veillarddee23482008-04-11 12:58:43 +000022814
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022815 /*
22816 * Create/grow the array of key-sequences.
22817 */
22818 if (matcher->keySeqs == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022819 if (pos > 9)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022820 matcher->sizeKeySeqs = pos * 2;
22821 else
22822 matcher->sizeKeySeqs = 10;
Daniel Veillarddee23482008-04-11 12:58:43 +000022823 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022824 xmlMalloc(matcher->sizeKeySeqs *
Daniel Veillarddee23482008-04-11 12:58:43 +000022825 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22826 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022827 xmlSchemaVErrMemory(NULL,
22828 "allocating an array of key-sequences",
22829 NULL);
22830 return(-1);
22831 }
22832 memset(matcher->keySeqs, 0,
22833 matcher->sizeKeySeqs *
22834 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Daniel Veillarddee23482008-04-11 12:58:43 +000022835 } else if (pos >= matcher->sizeKeySeqs) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022836 int i = matcher->sizeKeySeqs;
Daniel Veillarddee23482008-04-11 12:58:43 +000022837
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022838 matcher->sizeKeySeqs *= 2;
22839 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22840 xmlRealloc(matcher->keySeqs,
22841 matcher->sizeKeySeqs *
22842 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022843 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022844 xmlSchemaVErrMemory(NULL,
22845 "reallocating an array of key-sequences",
22846 NULL);
22847 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022848 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022849 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022850 * The array needs to be NULLed.
22851 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022852 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022853 for (; i < matcher->sizeKeySeqs; i++)
22854 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022855 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022856
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022857 /*
22858 * Get/create the key-sequence.
22859 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022860 keySeq = matcher->keySeqs[pos];
22861 if (keySeq == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022862 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022863 } else if (keySeq[idx] != NULL) {
22864 xmlChar *str = NULL;
22865 /*
22866 * cvc-identity-constraint:
Jan Pokorný761c9e92013-11-29 23:26:27 +010022867 * 3 For each node in the `target node set` all
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022868 * of the {fields}, with that node as the context
22869 * node, evaluate to either an empty node-set or
22870 * a node-set with exactly one member, which must
22871 * have a simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000022872 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022873 * The key was already set; report an error.
22874 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022875 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022876 XML_SCHEMAV_CVC_IDC, NULL,
22877 WXS_BASIC_CAST matcher->aidc->def,
22878 "The XPath '%s' of a field of %s evaluates to a "
22879 "node-set with more than one member",
22880 sto->sel->xpath,
22881 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22882 FREE_AND_NULL(str);
22883 sto->nbHistory--;
22884 goto deregister_check;
22885 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000022886 goto create_key;
22887
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022888create_sequence:
22889 /*
22890 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022891 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022892 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
Daniel Veillarddee23482008-04-11 12:58:43 +000022893 matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022894 sizeof(xmlSchemaPSVIIDCKeyPtr));
22895 if (keySeq == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022896 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022897 "allocating an IDC key-sequence", NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000022898 return(-1);
22899 }
22900 memset(keySeq, 0, matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022901 sizeof(xmlSchemaPSVIIDCKeyPtr));
22902 matcher->keySeqs[pos] = keySeq;
22903create_key:
22904 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022905 * Create a key once per node only.
Daniel Veillarddee23482008-04-11 12:58:43 +000022906 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022907 if (key == NULL) {
22908 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22909 sizeof(xmlSchemaPSVIIDCKey));
22910 if (key == NULL) {
22911 xmlSchemaVErrMemory(NULL,
22912 "allocating a IDC key", NULL);
22913 xmlFree(keySeq);
22914 matcher->keySeqs[pos] = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022915 return(-1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022916 }
22917 /*
22918 * Consume the compiled value.
22919 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022920 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022921 key->val = vctxt->inode->val;
22922 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022923 /*
22924 * Store the key in a global list.
22925 */
22926 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22927 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022928 return (-1);
22929 }
22930 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022931 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022932 }
22933 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022934
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022935 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022936 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022937 xmlSchemaPSVIIDCNodePtr ntItem;
22938 xmlSchemaIDCMatcherPtr matcher;
22939 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022940 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022941 int pos, i, j, nbKeys;
22942 /*
22943 * Here we have the following scenario:
22944 * An IDC 'selector' state object resolved to a target node,
Daniel Veillarddee23482008-04-11 12:58:43 +000022945 * during the time this target node was in the
22946 * ancestor-or-self axis, the 'field' state object(s) looked
22947 * out for matching nodes to create a key-sequence for this
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022948 * target node. Now we are back to this target node and need
Daniel Veillarddee23482008-04-11 12:58:43 +000022949 * to put the key-sequence, together with the target node
22950 * itself, into the node-table of the corresponding IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022951 * binding.
22952 */
22953 matcher = sto->matcher;
22954 idc = matcher->aidc->def;
22955 nbKeys = idc->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000022956 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022957 /*
22958 * Check if the matcher has any key-sequences at all, plus
22959 * if it has a key-sequence for the current target node.
Daniel Veillarddee23482008-04-11 12:58:43 +000022960 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022961 if ((matcher->keySeqs == NULL) ||
22962 (matcher->sizeKeySeqs <= pos)) {
22963 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22964 goto selector_key_error;
22965 else
22966 goto selector_leave;
22967 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022968
22969 keySeq = &(matcher->keySeqs[pos]);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022970 if (*keySeq == NULL) {
22971 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22972 goto selector_key_error;
22973 else
22974 goto selector_leave;
22975 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022976
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022977 for (i = 0; i < nbKeys; i++) {
22978 if ((*keySeq)[i] == NULL) {
22979 /*
22980 * Not qualified, if not all fields did resolve.
22981 */
22982 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22983 /*
22984 * All fields of a "key" IDC must resolve.
22985 */
22986 goto selector_key_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000022987 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022988 goto selector_leave;
22989 }
22990 }
22991 /*
22992 * All fields did resolve.
22993 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022994
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022995 /*
22996 * 4.1 If the {identity-constraint category} is unique(/key),
Jan Pokorný761c9e92013-11-29 23:26:27 +010022997 * then no two members of the `qualified node set` have
22998 * `key-sequences` whose members are pairwise equal, as
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022999 * defined by Equal in [XML Schemas: Datatypes].
23000 *
23001 * Get the IDC binding from the matcher and check for
23002 * duplicate key-sequences.
23003 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023004#if 0
23005 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23006#endif
23007 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Daniel Veillarddee23482008-04-11 12:58:43 +000023008 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023009 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023010 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Daniel Veillarddee23482008-04-11 12:58:43 +000023011
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023012 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023013 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023014 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023015 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023016 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023017 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023018 bkeySeq =
23019 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023020 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023021 ckey = (*keySeq)[j];
Daniel Veillarddee23482008-04-11 12:58:43 +000023022 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023023 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023024 if (res == -1) {
23025 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023026 } else if (res == 0) {
23027 /*
23028 * One of the keys differs, so the key-sequence
23029 * won't be equal; get out.
23030 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023031 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023032 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023033 }
23034 if (res == 1) {
23035 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023036 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023037 */
23038 break;
23039 }
23040 i++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023041 } while (i < targets->nbItems);
23042 if (i != targets->nbItems) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023043 xmlChar *str = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023044 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023045 * TODO: Try to report the key-sequence.
23046 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023047 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023048 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023049 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023050 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023051 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023052 (*keySeq), nbKeys),
23053 xmlSchemaGetIDCDesignation(&strB, idc));
23054 FREE_AND_NULL(str);
23055 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023056 goto selector_leave;
23057 }
23058 }
23059 /*
23060 * Add a node-table item to the IDC binding.
23061 */
23062 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23063 sizeof(xmlSchemaPSVIIDCNode));
23064 if (ntItem == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023065 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023066 "allocating an IDC node-table item", NULL);
23067 xmlFree(*keySeq);
23068 *keySeq = NULL;
23069 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023070 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023071 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Daniel Veillarddee23482008-04-11 12:58:43 +000023072
23073 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023074 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023075 */
23076 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23077 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23078 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023079 xmlFree(*keySeq);
23080 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023081 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023082 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023083 ntItem->nodeQNameID = -1;
23084 } else {
23085 /*
23086 * Save a cached QName for this node on the IDC node, to be
23087 * able to report it, even if the node is not saved.
23088 */
23089 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23090 vctxt->inode->localName, vctxt->inode->nsName);
23091 if (ntItem->nodeQNameID == -1) {
23092 xmlFree(ntItem);
23093 xmlFree(*keySeq);
23094 *keySeq = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023095 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023096 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023097 }
23098 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023099 * Init the node-table item: Save the node, position and
23100 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023101 */
23102 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023103 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023104 ntItem->keys = *keySeq;
23105 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023106#if 0
Daniel Veillarddee23482008-04-11 12:58:43 +000023107 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023108#endif
23109 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023110 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023111 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023112 * Free the item, since keyref items won't be
23113 * put on a global list.
23114 */
23115 xmlFree(ntItem->keys);
23116 xmlFree(ntItem);
23117 }
23118 return (-1);
23119 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023120
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023121 goto selector_leave;
23122selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023123 {
23124 xmlChar *str = NULL;
23125 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010023126 * 4.2.1 (KEY) The `target node set` and the
23127 * `qualified node set` are equal, that is, every
23128 * member of the `target node set` is also a member
23129 * of the `qualified node set` and vice versa.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023130 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023131 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023132 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023133 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023134 "Not all fields of %s evaluate to a node",
23135 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23136 FREE_AND_NULL(str);
23137 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023138selector_leave:
23139 /*
23140 * Free the key-sequence if not added to the IDC table.
23141 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023142 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023143 xmlFree(*keySeq);
23144 *keySeq = NULL;
23145 }
23146 } /* if selector */
Daniel Veillarddee23482008-04-11 12:58:43 +000023147
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023148 sto->nbHistory--;
23149
23150deregister_check:
23151 /*
23152 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023153 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023154 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023155#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023156 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23157 sto->sel->xpath);
23158#endif
23159 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023160 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023161 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023162 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023163 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023164 nextsto = sto->next;
23165 /*
23166 * Unlink from the list of active XPath state objects.
23167 */
23168 vctxt->xpathStates = sto->next;
23169 sto->next = vctxt->xpathStatePool;
23170 /*
23171 * Link it to the pool of reusable state objects.
23172 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023173 vctxt->xpathStatePool = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023174 sto = nextsto;
23175 } else
23176 sto = sto->next;
23177 } /* while (sto != NULL) */
23178 return (0);
23179}
23180
23181/**
23182 * xmlSchemaIDCRegisterMatchers:
23183 * @vctxt: the WXS validation context
23184 * @elemDecl: the element declaration
23185 *
23186 * Creates helper objects to evaluate IDC selectors/fields
23187 * successively.
23188 *
23189 * Returns 0 if OK and -1 on internal errors.
23190 */
23191static int
23192xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23193 xmlSchemaElementPtr elemDecl)
23194{
23195 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23196 xmlSchemaIDCPtr idc, refIdc;
23197 xmlSchemaIDCAugPtr aidc;
Daniel Veillarddee23482008-04-11 12:58:43 +000023198
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023199 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23200 if (idc == NULL)
23201 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000023202
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023203#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023204 {
23205 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023206 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023207 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023208 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23209 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023210 FREE_AND_NULL(str)
23211 }
23212#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023213 if (vctxt->inode->idcMatchers != NULL) {
23214 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23215 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023216 return (-1);
23217 }
23218 do {
23219 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23220 /*
23221 * Since IDCs bubbles are expensive we need to know the
23222 * depth at which the bubbles should stop; this will be
23223 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023224 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023225 * be -1, indicating that no bubbles are needed.
23226 */
23227 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23228 if (refIdc != NULL) {
23229 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023230 * Remember that we have keyrefs on this node.
23231 */
23232 vctxt->inode->hasKeyrefs = 1;
23233 /*
23234 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023235 */
23236 aidc = vctxt->aidcs;
23237 while (aidc != NULL) {
23238 if (aidc->def == refIdc)
23239 break;
23240 aidc = aidc->next;
23241 }
23242 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023243 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023244 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023245 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023246 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023247 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023248 if ((aidc->keyrefDepth == -1) ||
23249 (vctxt->depth < aidc->keyrefDepth))
23250 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023251 }
23252 }
23253 /*
23254 * Lookup the augmented IDC item for the IDC definition.
23255 */
23256 aidc = vctxt->aidcs;
23257 while (aidc != NULL) {
23258 if (aidc->def == idc)
23259 break;
23260 aidc = aidc->next;
23261 }
23262 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023263 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23264 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023265 return (-1);
23266 }
23267 /*
23268 * Create an IDC matcher for every IDC definition.
23269 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023270 if (vctxt->idcMatcherCache != NULL) {
23271 /*
23272 * Reuse a cached matcher.
23273 */
23274 matcher = vctxt->idcMatcherCache;
23275 vctxt->idcMatcherCache = matcher->nextCached;
23276 matcher->nextCached = NULL;
23277 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000023278 matcher = (xmlSchemaIDCMatcherPtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023279 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23280 if (matcher == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023281 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023282 "allocating an IDC matcher", NULL);
23283 return (-1);
23284 }
23285 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023286 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023287 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023288 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023289 else
23290 last->next = matcher;
23291 last = matcher;
23292
23293 matcher->type = IDC_MATCHER;
Daniel Veillarddee23482008-04-11 12:58:43 +000023294 matcher->depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023295 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023296 matcher->idcType = aidc->def->type;
Daniel Veillarddee23482008-04-11 12:58:43 +000023297#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023298 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
Daniel Veillarddee23482008-04-11 12:58:43 +000023299#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023300 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023301 * Init the automaton state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023302 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023303 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023304 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023305 return (-1);
23306
23307 idc = idc->next;
23308 } while (idc != NULL);
23309 return (0);
23310}
23311
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023312static int
23313xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23314 xmlSchemaNodeInfoPtr ielem)
23315{
23316 xmlSchemaPSVIIDCBindingPtr bind;
23317 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23318 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23319 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023320
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023321 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23322 /* vctxt->createIDCNodeTables */
23323 while (matcher != NULL) {
23324 /*
23325 * Skip keyref IDCs and empty IDC target-lists.
23326 */
23327 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23328 WXS_ILIST_IS_EMPTY(matcher->targets))
23329 {
23330 matcher = matcher->next;
23331 continue;
23332 }
23333 /*
23334 * If we _want_ the IDC node-table to be created in any case
23335 * then do so. Otherwise create them only if keyrefs need them.
23336 */
23337 if ((! vctxt->createIDCNodeTables) &&
23338 ((matcher->aidc->keyrefDepth == -1) ||
23339 (matcher->aidc->keyrefDepth > vctxt->depth)))
23340 {
23341 matcher = matcher->next;
23342 continue;
23343 }
23344 /*
23345 * Get/create the IDC binding on this element for the IDC definition.
23346 */
23347 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23348
23349 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23350 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23351 nbDupls = bind->dupls->nbItems;
23352 } else {
23353 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023354 nbDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023355 }
23356 if (bind->nodeTable != NULL) {
23357 nbNodeTable = bind->nbNodes;
23358 } else {
23359 nbNodeTable = 0;
23360 }
23361
23362 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23363 /*
23364 * Transfer all IDC target-nodes to the IDC node-table.
23365 */
23366 bind->nodeTable =
Daniel Veillarddee23482008-04-11 12:58:43 +000023367 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023368 bind->sizeNodes = matcher->targets->sizeItems;
23369 bind->nbNodes = matcher->targets->nbItems;
23370
23371 matcher->targets->items = NULL;
23372 matcher->targets->sizeItems = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023373 matcher->targets->nbItems = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023374 } else {
23375 /*
23376 * Compare the key-sequences and add to the IDC node-table.
23377 */
23378 nbTargets = matcher->targets->nbItems;
Daniel Veillarddee23482008-04-11 12:58:43 +000023379 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023380 nbFields = matcher->aidc->def->nbFields;
23381 i = 0;
23382 do {
23383 keys = targets[i]->keys;
Daniel Veillarddee23482008-04-11 12:58:43 +000023384 if (nbDupls) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023385 /*
23386 * Search in already found duplicates first.
23387 */
23388 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023389 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023390 if (nbFields == 1) {
23391 res = xmlSchemaAreValuesEqual(keys[0]->val,
23392 dupls[j]->keys[0]->val);
23393 if (res == -1)
23394 goto internal_error;
23395 if (res == 1) {
23396 /*
23397 * Equal key-sequence.
23398 */
23399 goto next_target;
23400 }
23401 } else {
23402 res = 0;
23403 ntkeys = dupls[j]->keys;
23404 for (k = 0; k < nbFields; k++) {
23405 res = xmlSchemaAreValuesEqual(keys[k]->val,
23406 ntkeys[k]->val);
23407 if (res == -1)
23408 goto internal_error;
23409 if (res == 0) {
23410 /*
23411 * One of the keys differs.
23412 */
23413 break;
23414 }
23415 }
23416 if (res == 1) {
23417 /*
23418 * Equal key-sequence found.
23419 */
23420 goto next_target;
23421 }
23422 }
23423 j++;
Daniel Veillarddee23482008-04-11 12:58:43 +000023424 } while (j < nbDupls);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023425 }
23426 if (nbNodeTable) {
23427 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023428 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023429 if (nbFields == 1) {
23430 res = xmlSchemaAreValuesEqual(keys[0]->val,
23431 bind->nodeTable[j]->keys[0]->val);
23432 if (res == -1)
23433 goto internal_error;
23434 if (res == 0) {
23435 /*
23436 * The key-sequence differs.
23437 */
23438 goto next_node_table_entry;
23439 }
23440 } else {
23441 res = 0;
23442 ntkeys = bind->nodeTable[j]->keys;
23443 for (k = 0; k < nbFields; k++) {
23444 res = xmlSchemaAreValuesEqual(keys[k]->val,
23445 ntkeys[k]->val);
23446 if (res == -1)
23447 goto internal_error;
23448 if (res == 0) {
23449 /*
23450 * One of the keys differs.
23451 */
23452 goto next_node_table_entry;
23453 }
23454 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023455 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023456 /*
23457 * Add the duplicate to the list of duplicates.
23458 */
23459 if (bind->dupls == NULL) {
23460 bind->dupls = xmlSchemaItemListCreate();
23461 if (bind->dupls == NULL)
23462 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023463 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023464 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23465 goto internal_error;
23466 /*
23467 * Remove the duplicate entry from the IDC node-table.
23468 */
23469 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23470 bind->nbNodes--;
23471
23472 goto next_target;
23473
23474next_node_table_entry:
23475 j++;
23476 } while (j < nbNodeTable);
23477 }
23478 /*
23479 * If everything is fine, then add the IDC target-node to
23480 * the IDC node-table.
23481 */
23482 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23483 goto internal_error;
23484
23485next_target:
23486 i++;
23487 } while (i < nbTargets);
23488 }
23489 matcher = matcher->next;
23490 }
23491 return(0);
23492
23493internal_error:
23494 return(-1);
23495}
23496
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023497/**
Daniel Veillarddee23482008-04-11 12:58:43 +000023498 * xmlSchemaBubbleIDCNodeTables:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023499 * @depth: the current tree depth
23500 *
Daniel Veillarddee23482008-04-11 12:58:43 +000023501 * Merges IDC bindings of an element at @depth into the corresponding IDC
23502 * bindings of its parent element. If a duplicate note-table entry is found,
23503 * both, the parent node-table entry and child entry are discarded from the
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023504 * node-table of the parent.
23505 *
23506 * Returns 0 if OK and -1 on internal errors.
23507 */
23508static int
23509xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23510{
23511 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023512 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23513 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023514 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023515 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023516
Daniel Veillarddee23482008-04-11 12:58:43 +000023517 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023518 if (bind == NULL) {
23519 /* Fine, no table, no bubbles. */
23520 return (0);
23521 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023522
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023523 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23524 /*
23525 * Walk all bindings; create new or add to existing bindings.
23526 * Remove duplicate key-sequences.
23527 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023528 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023529
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023530 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23531 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023532 /*
23533 * Check if the key/unique IDC table needs to be bubbled.
23534 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023535 if (! vctxt->createIDCNodeTables) {
23536 aidc = vctxt->aidcs;
23537 do {
23538 if (aidc->def == bind->definition) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023539 if ((aidc->keyrefDepth == -1) ||
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023540 (aidc->keyrefDepth >= vctxt->depth)) {
23541 goto next_binding;
23542 }
23543 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023544 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023545 aidc = aidc->next;
23546 } while (aidc != NULL);
23547 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023548
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023549 if (parTable != NULL)
23550 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023551 /*
23552 * Search a matching parent binding for the
23553 * IDC definition.
23554 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023555 while (parBind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023556 if (parBind->definition == bind->definition)
23557 break;
23558 parBind = parBind->next;
23559 }
23560
23561 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023562 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023563 * Compare every node-table entry of the child node,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023564 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023565 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023566 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023567
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023568 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23569 oldDupls = parBind->dupls->nbItems;
23570 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23571 } else {
23572 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023573 oldDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023574 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023575
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023576 parNodes = parBind->nodeTable;
23577 nbFields = bind->definition->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000023578
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023579 for (i = 0; i < bind->nbNodes; i++) {
23580 node = bind->nodeTable[i];
23581 if (node == NULL)
23582 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023583 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023584 * ...with every key-sequence of the parent node, already
23585 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023586 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023587 if (oldDupls) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023588 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023589 while (j < oldDupls) {
23590 if (nbFields == 1) {
23591 ret = xmlSchemaAreValuesEqual(
23592 node->keys[0]->val,
23593 dupls[j]->keys[0]->val);
23594 if (ret == -1)
23595 goto internal_error;
23596 if (ret == 0) {
23597 j++;
23598 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023599 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023600 } else {
23601 parNode = dupls[j];
23602 for (k = 0; k < nbFields; k++) {
23603 ret = xmlSchemaAreValuesEqual(
23604 node->keys[k]->val,
23605 parNode->keys[k]->val);
23606 if (ret == -1)
23607 goto internal_error;
23608 if (ret == 0)
23609 break;
23610 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023611 }
23612 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023613 /* Duplicate found. */
23614 break;
23615 j++;
23616 }
23617 if (j != oldDupls) {
23618 /* Duplicate found. Skip this entry. */
23619 continue;
23620 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023621 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023622 /*
23623 * ... and with every key-sequence of the parent node.
23624 */
23625 if (oldNum) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023626 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023627 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023628 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023629 if (nbFields == 1) {
23630 ret = xmlSchemaAreValuesEqual(
23631 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023632 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023633 if (ret == -1)
23634 goto internal_error;
23635 if (ret == 0) {
23636 j++;
23637 continue;
23638 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023639 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023640 for (k = 0; k < nbFields; k++) {
23641 ret = xmlSchemaAreValuesEqual(
23642 node->keys[k]->val,
23643 parNode->keys[k]->val);
23644 if (ret == -1)
23645 goto internal_error;
23646 if (ret == 0)
23647 break;
23648 }
23649 }
23650 if (ret == 1)
23651 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023652 break;
23653 j++;
23654 }
23655 if (j != oldNum) {
23656 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023657 * Handle duplicates. Move the duplicate in
23658 * the parent's node-table to the list of
23659 * duplicates.
Daniel Veillarddee23482008-04-11 12:58:43 +000023660 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023661 oldNum--;
23662 parBind->nbNodes--;
23663 /*
23664 * Move last old item to pos of duplicate.
23665 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023666 parNodes[j] = parNodes[oldNum];
Daniel Veillarddee23482008-04-11 12:58:43 +000023667
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023668 if (parBind->nbNodes != oldNum) {
23669 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023670 * If new items exist, move last new item to
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023671 * last of old items.
23672 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023673 parNodes[oldNum] =
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023674 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023675 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023676 if (parBind->dupls == NULL) {
23677 parBind->dupls = xmlSchemaItemListCreate();
23678 if (parBind->dupls == NULL)
23679 goto internal_error;
23680 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023681 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023682 } else {
23683 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023684 * Add the node-table entry (node and key-sequence) of
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023685 * the child node to the node table of the parent node.
23686 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023687 if (parBind->nodeTable == NULL) {
23688 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023689 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023690 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023691 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023692 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023693 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023694 }
23695 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023696 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023697 parBind->sizeNodes *= 2;
Daniel Veillarddee23482008-04-11 12:58:43 +000023698 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23699 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023700 sizeof(xmlSchemaPSVIIDCNodePtr));
23701 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023702 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023703 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023704 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023705 }
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023706 }
23707 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023708 /*
23709 * Append the new node-table entry to the 'new node-table
23710 * entries' section.
23711 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023712 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023713 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023714
Daniel Veillarddee23482008-04-11 12:58:43 +000023715 }
23716
23717 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023718 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023719 /*
23720 * No binding for the IDC was found: create a new one and
23721 * copy all node-tables.
23722 */
23723 parBind = xmlSchemaIDCNewBinding(bind->definition);
23724 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023725 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023726
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023727 /*
23728 * TODO: Hmm, how to optimize the initial number of
23729 * allocated entries?
23730 */
23731 if (bind->nbNodes != 0) {
23732 /*
23733 * Add all IDC node-table entries.
23734 */
23735 if (! vctxt->psviExposeIDCNodeTables) {
23736 /*
23737 * Just move the entries.
23738 * NOTE: this is quite save here, since
23739 * all the keyref lookups have already been
23740 * performed.
23741 */
23742 parBind->nodeTable = bind->nodeTable;
23743 bind->nodeTable = NULL;
23744 parBind->sizeNodes = bind->sizeNodes;
23745 bind->sizeNodes = 0;
23746 parBind->nbNodes = bind->nbNodes;
23747 bind->nbNodes = 0;
23748 } else {
23749 /*
23750 * Copy the entries.
23751 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023752 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023753 xmlMalloc(bind->nbNodes *
23754 sizeof(xmlSchemaPSVIIDCNodePtr));
23755 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023756 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023757 "allocating an array of IDC node-table "
23758 "items", NULL);
23759 xmlSchemaIDCFreeBinding(parBind);
23760 goto internal_error;
23761 }
23762 parBind->sizeNodes = bind->nbNodes;
23763 parBind->nbNodes = bind->nbNodes;
23764 memcpy(parBind->nodeTable, bind->nodeTable,
23765 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23766 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023767 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023768 if (bind->dupls) {
23769 /*
23770 * Move the duplicates.
23771 */
23772 if (parBind->dupls != NULL)
23773 xmlSchemaItemListFree(parBind->dupls);
23774 parBind->dupls = bind->dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023775 bind->dupls = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023776 }
Daniel Veillard76d36452009-09-07 11:19:33 +020023777 if (parTable != NULL) {
23778 if (*parTable == NULL)
23779 *parTable = parBind;
23780 else {
23781 parBind->next = *parTable;
23782 *parTable = parBind;
23783 }
23784 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023785 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023786
23787next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023788 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023789 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023790 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023791
23792internal_error:
23793 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023794}
23795
23796/**
23797 * xmlSchemaCheckCVCIDCKeyRef:
23798 * @vctxt: the WXS validation context
23799 * @elemDecl: the element declaration
23800 *
23801 * Check the cvc-idc-keyref constraints.
23802 */
23803static int
23804xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23805{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023806 xmlSchemaIDCMatcherPtr matcher;
23807 xmlSchemaPSVIIDCBindingPtr bind;
Daniel Veillarddee23482008-04-11 12:58:43 +000023808
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023809 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023810 /*
23811 * Find a keyref.
23812 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023813 while (matcher != NULL) {
23814 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23815 matcher->targets &&
23816 matcher->targets->nbItems)
23817 {
23818 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023819 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023820 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023821
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023822 nbFields = matcher->aidc->def->nbFields;
23823
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023824 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023825 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023826 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023827 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023828 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023829 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023830 bind->definition)
23831 break;
23832 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023833 }
23834 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023835 /*
23836 * Search for a matching key-sequences.
23837 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023838 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023839 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023840 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023841 if (bind != NULL) {
23842 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023843 for (j = 0; j < bind->nbNodes; j++) {
23844 keys = bind->nodeTable[j]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023845 for (k = 0; k < nbFields; k++) {
23846 res = xmlSchemaAreValuesEqual(keys[k]->val,
23847 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023848 if (res == 0)
23849 break;
23850 else if (res == -1) {
23851 return (-1);
23852 }
23853 }
23854 if (res == 1) {
23855 /*
23856 * Match found.
23857 */
23858 break;
23859 }
23860 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023861 if ((res == 0) && hasDupls) {
23862 /*
23863 * Search in duplicates
23864 */
23865 for (j = 0; j < bind->dupls->nbItems; j++) {
23866 keys = ((xmlSchemaPSVIIDCNodePtr)
23867 bind->dupls->items[j])->keys;
23868 for (k = 0; k < nbFields; k++) {
23869 res = xmlSchemaAreValuesEqual(keys[k]->val,
23870 refKeys[k]->val);
23871 if (res == 0)
23872 break;
23873 else if (res == -1) {
23874 return (-1);
23875 }
23876 }
23877 if (res == 1) {
23878 /*
23879 * Match in duplicates found.
23880 */
23881 xmlChar *str = NULL, *strB = NULL;
23882 xmlSchemaKeyrefErr(vctxt,
23883 XML_SCHEMAV_CVC_IDC, refNode,
23884 (xmlSchemaTypePtr) matcher->aidc->def,
23885 "More than one match found for "
23886 "key-sequence %s of keyref '%s'",
23887 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23888 refNode->keys, nbFields),
23889 xmlSchemaGetComponentQName(&strB,
23890 matcher->aidc->def));
23891 FREE_AND_NULL(str);
23892 FREE_AND_NULL(strB);
23893 break;
23894 }
23895 }
23896 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023897 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023898
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023899 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023900 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023901 xmlSchemaKeyrefErr(vctxt,
23902 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023903 (xmlSchemaTypePtr) matcher->aidc->def,
23904 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023905 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023906 refNode->keys, nbFields),
23907 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023908 FREE_AND_NULL(str);
23909 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023910 }
23911 }
23912 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023913 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023914 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023915 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023916 return (0);
23917}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023918
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023919/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080023920 * *
23921 * XML Reader validation code *
23922 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023923 ************************************************************************/
23924
23925static xmlSchemaAttrInfoPtr
23926xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023927{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023928 xmlSchemaAttrInfoPtr iattr;
23929 /*
23930 * Grow/create list of attribute infos.
23931 */
23932 if (vctxt->attrInfos == NULL) {
23933 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23934 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23935 vctxt->sizeAttrInfos = 1;
23936 if (vctxt->attrInfos == NULL) {
23937 xmlSchemaVErrMemory(vctxt,
23938 "allocating attribute info list", NULL);
23939 return (NULL);
23940 }
23941 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23942 vctxt->sizeAttrInfos++;
23943 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23944 xmlRealloc(vctxt->attrInfos,
23945 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23946 if (vctxt->attrInfos == NULL) {
23947 xmlSchemaVErrMemory(vctxt,
23948 "re-allocating attribute info list", NULL);
23949 return (NULL);
23950 }
23951 } else {
23952 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23953 if (iattr->localName != NULL) {
23954 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23955 "attr info not cleared");
23956 return (NULL);
23957 }
23958 iattr->nodeType = XML_ATTRIBUTE_NODE;
23959 return (iattr);
23960 }
23961 /*
23962 * Create an attribute info.
23963 */
23964 iattr = (xmlSchemaAttrInfoPtr)
23965 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23966 if (iattr == NULL) {
23967 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23968 return (NULL);
23969 }
23970 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23971 iattr->nodeType = XML_ATTRIBUTE_NODE;
23972 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23973
23974 return (iattr);
23975}
23976
23977static int
23978xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23979 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023980 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023981 const xmlChar *localName,
Daniel Veillarddee23482008-04-11 12:58:43 +000023982 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023983 int ownedNames,
23984 xmlChar *value,
23985 int ownedValue)
23986{
23987 xmlSchemaAttrInfoPtr attr;
23988
23989 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23990 if (attr == NULL) {
23991 VERROR_INT("xmlSchemaPushAttribute",
23992 "calling xmlSchemaGetFreshAttrInfo()");
23993 return (-1);
23994 }
23995 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023996 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023997 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23998 attr->localName = localName;
23999 attr->nsName = nsName;
24000 if (ownedNames)
24001 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24002 /*
24003 * Evaluate if it's an XSI attribute.
24004 */
24005 if (nsName != NULL) {
24006 if (xmlStrEqual(localName, BAD_CAST "nil")) {
24007 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024008 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024009 }
24010 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24011 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24012 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24013 }
24014 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24015 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24016 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24017 }
24018 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24019 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24020 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24021 }
24022 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24023 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24024 }
24025 }
24026 attr->value = value;
24027 if (ownedValue)
24028 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24029 if (attr->metaType != 0)
24030 attr->state = XML_SCHEMAS_ATTR_META;
24031 return (0);
24032}
24033
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024034/**
24035 * xmlSchemaClearElemInfo:
24036 * @vctxt: the WXS validation context
24037 * @ielem: the element information item
24038 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024039static void
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024040xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24041 xmlSchemaNodeInfoPtr ielem)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024042{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024043 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000024044 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024045 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24046 FREE_AND_NULL(ielem->localName);
24047 FREE_AND_NULL(ielem->nsName);
24048 } else {
24049 ielem->localName = NULL;
24050 ielem->nsName = NULL;
24051 }
24052 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24053 FREE_AND_NULL(ielem->value);
24054 } else {
24055 ielem->value = NULL;
24056 }
24057 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024058 /*
24059 * PSVI TODO: Be careful not to free it when the value is
24060 * exposed via PSVI.
24061 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024062 xmlSchemaFreeValue(ielem->val);
24063 ielem->val = NULL;
24064 }
24065 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024066 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024067 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24068 * Does it work?
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024069 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024070 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24071#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024072 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024073#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024074 ielem->idcMatchers = NULL;
24075 }
24076 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024077 /*
24078 * OPTIMIZE TODO: Use a pool of IDC tables??.
24079 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024080 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24081 ielem->idcTable = NULL;
24082 }
24083 if (ielem->regexCtxt != NULL) {
24084 xmlRegFreeExecCtxt(ielem->regexCtxt);
24085 ielem->regexCtxt = NULL;
24086 }
24087 if (ielem->nsBindings != NULL) {
24088 xmlFree((xmlChar **)ielem->nsBindings);
24089 ielem->nsBindings = NULL;
24090 ielem->nbNsBindings = 0;
24091 ielem->sizeNsBindings = 0;
24092 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024093}
24094
24095/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024096 * xmlSchemaGetFreshElemInfo:
24097 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024098 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024099 * Creates/reuses and initializes the element info item for
24100 * the currect tree depth.
24101 *
24102 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024103 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024104static xmlSchemaNodeInfoPtr
24105xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024106{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024107 xmlSchemaNodeInfoPtr info = NULL;
24108
24109 if (vctxt->depth > vctxt->sizeElemInfos) {
24110 VERROR_INT("xmlSchemaGetFreshElemInfo",
24111 "inconsistent depth encountered");
24112 return (NULL);
24113 }
24114 if (vctxt->elemInfos == NULL) {
24115 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24116 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24117 if (vctxt->elemInfos == NULL) {
24118 xmlSchemaVErrMemory(vctxt,
24119 "allocating the element info array", NULL);
24120 return (NULL);
24121 }
24122 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24123 vctxt->sizeElemInfos = 10;
24124 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24125 int i = vctxt->sizeElemInfos;
24126
24127 vctxt->sizeElemInfos *= 2;
24128 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24129 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24130 sizeof(xmlSchemaNodeInfoPtr));
24131 if (vctxt->elemInfos == NULL) {
24132 xmlSchemaVErrMemory(vctxt,
24133 "re-allocating the element info array", NULL);
24134 return (NULL);
24135 }
24136 /*
24137 * We need the new memory to be NULLed.
24138 * TODO: Use memset instead?
24139 */
24140 for (; i < vctxt->sizeElemInfos; i++)
24141 vctxt->elemInfos[i] = NULL;
24142 } else
24143 info = vctxt->elemInfos[vctxt->depth];
24144
24145 if (info == NULL) {
24146 info = (xmlSchemaNodeInfoPtr)
24147 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24148 if (info == NULL) {
24149 xmlSchemaVErrMemory(vctxt,
24150 "allocating an element info", NULL);
24151 return (NULL);
24152 }
24153 vctxt->elemInfos[vctxt->depth] = info;
24154 } else {
24155 if (info->localName != NULL) {
24156 VERROR_INT("xmlSchemaGetFreshElemInfo",
24157 "elem info has not been cleared");
24158 return (NULL);
24159 }
24160 }
24161 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24162 info->nodeType = XML_ELEMENT_NODE;
24163 info->depth = vctxt->depth;
24164
24165 return (info);
24166}
24167
24168#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24169#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24170#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24171
24172static int
24173xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24174 xmlNodePtr node,
24175 xmlSchemaTypePtr type,
24176 xmlSchemaValType valType,
24177 const xmlChar * value,
24178 xmlSchemaValPtr val,
24179 unsigned long length,
24180 int fireErrors)
24181{
24182 int ret, error = 0;
24183
24184 xmlSchemaTypePtr tmpType;
24185 xmlSchemaFacetLinkPtr facetLink;
24186 xmlSchemaFacetPtr facet;
24187 unsigned long len = 0;
24188 xmlSchemaWhitespaceValueType ws;
24189
24190 /*
24191 * In Libxml2, derived built-in types have currently no explicit facets.
24192 */
24193 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024194 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024195
24196 /*
24197 * NOTE: Do not jump away, if the facetSet of the given type is
24198 * empty: until now, "pattern" and "enumeration" facets of the
24199 * *base types* need to be checked as well.
24200 */
24201 if (type->facetSet == NULL)
24202 goto pattern_and_enum;
24203
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024204 if (! WXS_IS_ATOMIC(type)) {
24205 if (WXS_IS_LIST(type))
24206 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024207 else
24208 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024209 }
Scott Graham58b84e12015-06-30 10:47:16 +080024210
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024211 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024212 * Whitespace handling is only of importance for string-based
24213 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024214 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024215 tmpType = xmlSchemaGetPrimitiveType(type);
24216 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024217 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024218 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24219 } else
24220 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
Scott Graham58b84e12015-06-30 10:47:16 +080024221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024222 /*
24223 * If the value was not computed (for string or
24224 * anySimpleType based types), then use the provided
24225 * type.
24226 */
Scott Graham58b84e12015-06-30 10:47:16 +080024227 if (val != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024228 valType = xmlSchemaGetValType(val);
Daniel Veillarddee23482008-04-11 12:58:43 +000024229
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024230 ret = 0;
24231 for (facetLink = type->facetSet; facetLink != NULL;
24232 facetLink = facetLink->next) {
24233 /*
24234 * Skip the pattern "whiteSpace": it is used to
24235 * format the character content beforehand.
24236 */
24237 switch (facetLink->facet->type) {
24238 case XML_SCHEMA_FACET_WHITESPACE:
24239 case XML_SCHEMA_FACET_PATTERN:
24240 case XML_SCHEMA_FACET_ENUMERATION:
24241 continue;
24242 case XML_SCHEMA_FACET_LENGTH:
24243 case XML_SCHEMA_FACET_MINLENGTH:
24244 case XML_SCHEMA_FACET_MAXLENGTH:
24245 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24246 valType, value, val, &len, ws);
24247 break;
24248 default:
24249 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24250 valType, value, val, ws);
24251 break;
24252 }
24253 if (ret < 0) {
24254 AERROR_INT("xmlSchemaValidateFacets",
24255 "validating against a atomic type facet");
24256 return (-1);
24257 } else if (ret > 0) {
24258 if (fireErrors)
24259 xmlSchemaFacetErr(actxt, ret, node,
24260 value, len, type, facetLink->facet, NULL, NULL, NULL);
24261 else
24262 return (ret);
24263 if (error == 0)
24264 error = ret;
24265 }
24266 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024267 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024268
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024269WXS_IS_LIST:
24270 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024271 goto pattern_and_enum;
24272 /*
24273 * "length", "minLength" and "maxLength" of list types.
24274 */
24275 ret = 0;
24276 for (facetLink = type->facetSet; facetLink != NULL;
24277 facetLink = facetLink->next) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024278
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024279 switch (facetLink->facet->type) {
24280 case XML_SCHEMA_FACET_LENGTH:
24281 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillarddee23482008-04-11 12:58:43 +000024282 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024283 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24284 value, length, NULL);
24285 break;
24286 default:
24287 continue;
24288 }
24289 if (ret < 0) {
24290 AERROR_INT("xmlSchemaValidateFacets",
24291 "validating against a list type facet");
24292 return (-1);
24293 } else if (ret > 0) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024294 if (fireErrors)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024295 xmlSchemaFacetErr(actxt, ret, node,
24296 value, length, type, facetLink->facet, NULL, NULL, NULL);
24297 else
24298 return (ret);
24299 if (error == 0)
24300 error = ret;
24301 }
24302 ret = 0;
24303 }
24304
24305pattern_and_enum:
24306 if (error >= 0) {
24307 int found = 0;
24308 /*
24309 * Process enumerations. Facet values are in the value space
24310 * of the defining type's base type. This seems to be a bug in the
24311 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24312 * Only the first set of enumerations in the ancestor-or-self axis
24313 * is used for validation.
24314 */
24315 ret = 0;
24316 tmpType = type;
24317 do {
24318 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24319 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24320 continue;
24321 found = 1;
24322 ret = xmlSchemaAreValuesEqual(facet->val, val);
24323 if (ret == 1)
24324 break;
24325 else if (ret < 0) {
24326 AERROR_INT("xmlSchemaValidateFacets",
24327 "validating against an enumeration facet");
24328 return (-1);
24329 }
24330 }
24331 if (ret != 0)
24332 break;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +000024333 /*
24334 * Break on the first set of enumerations. Any additional
24335 * enumerations which might be existent on the ancestors
24336 * of the current type are restricted by this set; thus
24337 * *must* *not* be taken into account.
24338 */
24339 if (found)
24340 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024341 tmpType = tmpType->baseType;
24342 } while ((tmpType != NULL) &&
24343 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24344 if (found && (ret == 0)) {
24345 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24346 if (fireErrors) {
24347 xmlSchemaFacetErr(actxt, ret, node,
24348 value, 0, type, NULL, NULL, NULL, NULL);
24349 } else
24350 return (ret);
24351 if (error == 0)
24352 error = ret;
24353 }
24354 }
24355
24356 if (error >= 0) {
24357 int found;
24358 /*
24359 * Process patters. Pattern facets are ORed at type level
24360 * and ANDed if derived. Walk the base type axis.
24361 */
24362 tmpType = type;
24363 facet = NULL;
24364 do {
24365 found = 0;
24366 for (facetLink = tmpType->facetSet; facetLink != NULL;
24367 facetLink = facetLink->next) {
24368 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24369 continue;
24370 found = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000024371 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024372 * NOTE that for patterns, @value needs to be the
24373 * normalized vaule.
24374 */
24375 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24376 if (ret == 1)
24377 break;
24378 else if (ret < 0) {
24379 AERROR_INT("xmlSchemaValidateFacets",
24380 "validating against a pattern facet");
24381 return (-1);
24382 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000024383 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024384 * Save the last non-validating facet.
24385 */
24386 facet = facetLink->facet;
24387 }
24388 }
24389 if (found && (ret != 1)) {
24390 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24391 if (fireErrors) {
24392 xmlSchemaFacetErr(actxt, ret, node,
24393 value, 0, type, facet, NULL, NULL, NULL);
24394 } else
24395 return (ret);
24396 if (error == 0)
24397 error = ret;
24398 break;
24399 }
24400 tmpType = tmpType->baseType;
24401 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24402 }
24403
24404 return (error);
24405}
Daniel Veillarddee23482008-04-11 12:58:43 +000024406
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024407static xmlChar *
24408xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24409 const xmlChar *value)
24410{
Daniel Veillarddee23482008-04-11 12:58:43 +000024411 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024412 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24413 return (xmlSchemaCollapseString(value));
24414 case XML_SCHEMA_WHITESPACE_REPLACE:
24415 return (xmlSchemaWhiteSpaceReplace(value));
24416 default:
24417 return (NULL);
24418 }
24419}
24420
24421static int
24422xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24423 const xmlChar *value,
24424 xmlSchemaValPtr *val,
24425 int valNeeded)
24426{
24427 int ret;
24428 const xmlChar *nsName;
24429 xmlChar *local, *prefix = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000024430
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024431 ret = xmlValidateQName(value, 1);
24432 if (ret != 0) {
24433 if (ret == -1) {
24434 VERROR_INT("xmlSchemaValidateQName",
24435 "calling xmlValidateQName()");
24436 return (-1);
24437 }
24438 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24439 }
24440 /*
24441 * NOTE: xmlSplitQName2 will always return a duplicated
24442 * strings.
24443 */
24444 local = xmlSplitQName2(value, &prefix);
24445 if (local == NULL)
24446 local = xmlStrdup(value);
24447 /*
24448 * OPTIMIZE TODO: Use flags for:
24449 * - is there any namespace binding?
24450 * - is there a default namespace?
24451 */
24452 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
Daniel Veillarddee23482008-04-11 12:58:43 +000024453
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024454 if (prefix != NULL) {
24455 xmlFree(prefix);
24456 /*
24457 * A namespace must be found if the prefix is
24458 * NOT NULL.
24459 */
24460 if (nsName == NULL) {
24461 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024462 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024463 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024464 "The QName value '%s' has no "
24465 "corresponding namespace declaration in "
24466 "scope", value, NULL);
24467 if (local != NULL)
24468 xmlFree(local);
24469 return (ret);
24470 }
24471 }
24472 if (valNeeded && val) {
24473 if (nsName != NULL)
24474 *val = xmlSchemaNewQNameValue(
24475 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24476 else
24477 *val = xmlSchemaNewQNameValue(NULL,
24478 BAD_CAST local);
24479 } else
24480 xmlFree(local);
24481 return (0);
24482}
24483
24484/*
24485* cvc-simple-type
24486*/
24487static int
24488xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24489 xmlNodePtr node,
24490 xmlSchemaTypePtr type,
24491 const xmlChar *value,
24492 xmlSchemaValPtr *retVal,
24493 int fireErrors,
24494 int normalize,
24495 int isNormalized)
24496{
24497 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24498 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024499 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024500 xmlChar *normValue = NULL;
24501
24502#define NORMALIZE(atype) \
24503 if ((! isNormalized) && \
24504 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24505 normValue = xmlSchemaNormalizeValue(atype, value); \
24506 if (normValue != NULL) \
24507 value = normValue; \
24508 isNormalized = 1; \
24509 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024510
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024511 if ((retVal != NULL) && (*retVal != NULL)) {
24512 xmlSchemaFreeValue(*retVal);
24513 *retVal = NULL;
24514 }
24515 /*
24516 * 3.14.4 Simple Type Definition Validation Rules
24517 * Validation Rule: String Valid
24518 */
24519 /*
24520 * 1 It is schema-valid with respect to that definition as defined
24521 * by Datatype Valid in [XML Schemas: Datatypes].
24522 */
24523 /*
24524 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
Jan Pokorný761c9e92013-11-29 23:26:27 +010024525 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24526 * the string must be a `declared entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024527 */
24528 /*
24529 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
Jan Pokorný761c9e92013-11-29 23:26:27 +010024530 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24531 * then every whitespace-delimited substring of the string must be a `declared
24532 * entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024533 */
24534 /*
24535 * 2.3 otherwise no further condition applies.
24536 */
24537 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24538 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024539 if (value == NULL)
24540 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024541 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024542 xmlSchemaTypePtr biType; /* The built-in type. */
24543 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024544 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24545 * a literal in the `lexical space` of {base type definition}"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024546 */
24547 /*
24548 * Whitespace-normalize.
24549 */
24550 NORMALIZE(type);
24551 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24552 /*
24553 * Get the built-in type.
24554 */
24555 biType = type->baseType;
24556 while ((biType != NULL) &&
24557 (biType->type != XML_SCHEMA_TYPE_BASIC))
24558 biType = biType->baseType;
24559
24560 if (biType == NULL) {
24561 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24562 "could not get the built-in type");
24563 goto internal_error;
24564 }
24565 } else
24566 biType = type;
24567 /*
24568 * NOTATIONs need to be processed here, since they need
24569 * to lookup in the hashtable of NOTATION declarations of the schema.
24570 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024571 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24572 switch (biType->builtInType) {
24573 case XML_SCHEMAS_NOTATION:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024574 ret = xmlSchemaValidateNotation(
24575 (xmlSchemaValidCtxtPtr) actxt,
24576 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24577 NULL, value, &val, valNeeded);
24578 break;
24579 case XML_SCHEMAS_QNAME:
24580 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24581 value, &val, valNeeded);
24582 break;
24583 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024584 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024585 if (valNeeded)
24586 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024587 value, &val, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024588 else
24589 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024590 value, NULL, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024591 break;
24592 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024593 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24594 switch (biType->builtInType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024595 case XML_SCHEMAS_NOTATION:
24596 ret = xmlSchemaValidateNotation(NULL,
24597 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24598 value, &val, valNeeded);
24599 break;
24600 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024601 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024602 if (valNeeded)
24603 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24604 value, &val, node);
24605 else
24606 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24607 value, NULL, node);
24608 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024610 } else {
24611 /*
24612 * Validation via a public API is not implemented yet.
24613 */
24614 TODO
24615 goto internal_error;
24616 }
24617 if (ret != 0) {
24618 if (ret < 0) {
24619 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24620 "validating against a built-in type");
24621 goto internal_error;
24622 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024623 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024624 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24625 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024626 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024627 }
24628 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24629 /*
24630 * Check facets.
24631 */
24632 ret = xmlSchemaValidateFacets(actxt, node, type,
24633 (xmlSchemaValType) biType->builtInType, value, val,
24634 0, fireErrors);
24635 if (ret != 0) {
24636 if (ret < 0) {
24637 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24638 "validating facets of atomic simple type");
24639 goto internal_error;
24640 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024641 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024642 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24643 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024644 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024645 }
24646 }
24647 if (fireErrors && (ret > 0))
24648 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024649 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024650
24651 xmlSchemaTypePtr itemType;
24652 const xmlChar *cur, *end;
24653 xmlChar *tmpValue = NULL;
24654 unsigned long len = 0;
24655 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
Jan Pokorný761c9e92013-11-29 23:26:27 +010024656 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24657 * of white space separated tokens, each of which `match`es a literal
24658 * in the `lexical space` of {item type definition}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024659 */
24660 /*
24661 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24662 * the list type has an enum or pattern facet.
24663 */
24664 NORMALIZE(type);
24665 /*
24666 * VAL TODO: Optimize validation of empty values.
24667 * VAL TODO: We do not have computed values for lists.
24668 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024669 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024670 cur = value;
24671 do {
24672 while (IS_BLANK_CH(*cur))
24673 cur++;
24674 end = cur;
24675 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24676 end++;
24677 if (end == cur)
24678 break;
24679 tmpValue = xmlStrndup(cur, end - cur);
24680 len++;
24681
24682 if (valNeeded)
24683 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24684 tmpValue, &curVal, fireErrors, 0, 1);
24685 else
24686 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24687 tmpValue, NULL, fireErrors, 0, 1);
24688 FREE_AND_NULL(tmpValue);
24689 if (curVal != NULL) {
24690 /*
24691 * Add to list of computed values.
24692 */
24693 if (val == NULL)
24694 val = curVal;
24695 else
24696 xmlSchemaValueAppend(prevVal, curVal);
24697 prevVal = curVal;
24698 curVal = NULL;
24699 }
24700 if (ret != 0) {
24701 if (ret < 0) {
24702 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24703 "validating an item of list simple type");
24704 goto internal_error;
24705 }
24706 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24707 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024708 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024709 cur = end;
24710 } while (*cur != 0);
24711 FREE_AND_NULL(tmpValue);
24712 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24713 /*
24714 * Apply facets (pattern, enumeration).
24715 */
24716 ret = xmlSchemaValidateFacets(actxt, node, type,
24717 XML_SCHEMAS_UNKNOWN, value, val,
24718 len, fireErrors);
24719 if (ret != 0) {
24720 if (ret < 0) {
24721 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24722 "validating facets of list simple type");
24723 goto internal_error;
24724 }
24725 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24726 }
24727 }
24728 if (fireErrors && (ret > 0)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024729 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024730 * Report the normalized value.
24731 */
24732 normalize = 1;
24733 NORMALIZE(type);
24734 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24735 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024736 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024737 xmlSchemaTypeLinkPtr memberLink;
24738 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024739 * TODO: For all datatypes `derived` by `union` whiteSpace does
24740 * not apply directly; however, the normalization behavior of `union`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024741 * types is controlled by the value of whiteSpace on that one of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010024742 * `memberTypes` against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024743 *
24744 * This means that the value is normalized by the first validating
24745 * member type, then the facets of the union type are applied. This
24746 * needs changing of the value!
24747 */
24748
24749 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024750 * 1.2.3 if {variety} is `union` then the string must `match` a
24751 * literal in the `lexical space` of at least one member of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024752 * {member type definitions}
24753 */
24754 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24755 if (memberLink == NULL) {
24756 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24757 "union simple type has no member types");
24758 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000024759 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024760 /*
24761 * Always normalize union type values, since we currently
24762 * cannot store the whitespace information with the value
24763 * itself; otherwise a later value-comparison would be
24764 * not possible.
24765 */
24766 while (memberLink != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024767 if (valNeeded)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024768 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24769 memberLink->type, value, &val, 0, 1, 0);
24770 else
24771 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24772 memberLink->type, value, NULL, 0, 1, 0);
24773 if (ret <= 0)
24774 break;
24775 memberLink = memberLink->next;
24776 }
24777 if (ret != 0) {
24778 if (ret < 0) {
24779 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24780 "validating members of union simple type");
24781 goto internal_error;
24782 }
24783 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24784 }
24785 /*
24786 * Apply facets (pattern, enumeration).
24787 */
24788 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24789 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024790 * The normalization behavior of `union` types is controlled by
24791 * the value of whiteSpace on that one of the `memberTypes`
24792 * against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024793 */
24794 NORMALIZE(memberLink->type);
24795 ret = xmlSchemaValidateFacets(actxt, node, type,
24796 XML_SCHEMAS_UNKNOWN, value, val,
24797 0, fireErrors);
24798 if (ret != 0) {
24799 if (ret < 0) {
24800 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24801 "validating facets of union simple type");
24802 goto internal_error;
24803 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024804 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 }
24806 }
24807 if (fireErrors && (ret > 0))
24808 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24809 }
24810
24811 if (normValue != NULL)
24812 xmlFree(normValue);
24813 if (ret == 0) {
24814 if (retVal != NULL)
24815 *retVal = val;
24816 else if (val != NULL)
24817 xmlSchemaFreeValue(val);
24818 } else if (val != NULL)
24819 xmlSchemaFreeValue(val);
24820 return (ret);
24821internal_error:
24822 if (normValue != NULL)
24823 xmlFree(normValue);
24824 if (val != NULL)
24825 xmlSchemaFreeValue(val);
24826 return (-1);
24827}
24828
24829static int
24830xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24831 const xmlChar *value,
24832 const xmlChar **nsName,
24833 const xmlChar **localName)
24834{
24835 int ret = 0;
24836
24837 if ((nsName == NULL) || (localName == NULL))
24838 return (-1);
24839 *nsName = NULL;
24840 *localName = NULL;
24841
24842 ret = xmlValidateQName(value, 1);
24843 if (ret == -1)
24844 return (-1);
24845 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024846 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024847 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24848 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24849 return (1);
24850 }
24851 {
24852 xmlChar *local = NULL;
24853 xmlChar *prefix;
24854
24855 /*
24856 * NOTE: xmlSplitQName2 will return a duplicated
24857 * string.
24858 */
24859 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024860 if (local == NULL)
24861 *localName = xmlDictLookup(vctxt->dict, value, -1);
24862 else {
24863 *localName = xmlDictLookup(vctxt->dict, local, -1);
24864 xmlFree(local);
24865 }
24866
24867 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24868
24869 if (prefix != NULL) {
24870 xmlFree(prefix);
24871 /*
24872 * A namespace must be found if the prefix is NOT NULL.
24873 */
24874 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024875 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024876 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024877 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024878 "The QName value '%s' has no "
24879 "corresponding namespace declaration in scope",
24880 value, NULL);
24881 return (2);
24882 }
24883 }
24884 }
24885 return (0);
24886}
24887
24888static int
24889xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24890 xmlSchemaAttrInfoPtr iattr,
24891 xmlSchemaTypePtr *localType,
24892 xmlSchemaElementPtr elemDecl)
24893{
24894 int ret = 0;
24895 /*
24896 * cvc-elt (3.3.4) : (4)
24897 * AND
24898 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24899 * (1.2.1.2.1) - (1.2.1.2.4)
24900 * Handle 'xsi:type'.
24901 */
24902 if (localType == NULL)
24903 return (-1);
24904 *localType = NULL;
24905 if (iattr == NULL)
24906 return (0);
24907 else {
24908 const xmlChar *nsName = NULL, *local = NULL;
24909 /*
24910 * TODO: We should report a *warning* that the type was overriden
24911 * by the instance.
24912 */
24913 ACTIVATE_ATTRIBUTE(iattr);
24914 /*
24915 * (cvc-elt) (3.3.4) : (4.1)
24916 * (cvc-assess-elt) (1.2.1.2.2)
24917 */
24918 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24919 &nsName, &local);
24920 if (ret != 0) {
24921 if (ret < 0) {
24922 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24923 "calling xmlSchemaQNameExpand() to validate the "
24924 "attribute 'xsi:type'");
24925 goto internal_error;
24926 }
24927 goto exit;
24928 }
24929 /*
24930 * (cvc-elt) (3.3.4) : (4.2)
24931 * (cvc-assess-elt) (1.2.1.2.3)
24932 */
24933 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24934 if (*localType == NULL) {
24935 xmlChar *str = NULL;
24936
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024937 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024938 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024939 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024940 "The QName value '%s' of the xsi:type attribute does not "
24941 "resolve to a type definition",
24942 xmlSchemaFormatQName(&str, nsName, local), NULL);
24943 FREE_AND_NULL(str);
24944 ret = vctxt->err;
24945 goto exit;
24946 }
24947 if (elemDecl != NULL) {
24948 int set = 0;
24949
24950 /*
24951 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
Jan Pokorný761c9e92013-11-29 23:26:27 +010024952 * "The `local type definition` must be validly
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024953 * derived from the {type definition} given the union of
24954 * the {disallowed substitutions} and the {type definition}'s
24955 * {prohibited substitutions}, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010024956 * Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024957 * (if it is a complex type definition),
24958 * or given {disallowed substitutions} as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010024959 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024960 * definition)."
24961 *
24962 * {disallowed substitutions}: the "block" on the element decl.
24963 * {prohibited substitutions}: the "block" on the type def.
24964 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024965 /*
24966 * OPTIMIZE TODO: We could map types already evaluated
24967 * to be validly derived from other types to avoid checking
24968 * this over and over for the same types.
24969 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024970 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24971 (elemDecl->subtypes->flags &
24972 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24973 set |= SUBSET_EXTENSION;
24974
24975 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24976 (elemDecl->subtypes->flags &
24977 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24978 set |= SUBSET_RESTRICTION;
24979
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000024980 /*
24981 * REMOVED and CHANGED since this produced a parser context
24982 * which adds to the string dict of the schema. So this would
24983 * change the schema and we don't want this. We don't need
24984 * the parser context anymore.
24985 *
24986 * if ((vctxt->pctxt == NULL) &&
24987 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24988 * return (-1);
24989 */
24990
24991 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024992 elemDecl->subtypes, set) != 0) {
24993 xmlChar *str = NULL;
24994
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024995 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024996 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24997 "The type definition '%s', specified by xsi:type, is "
24998 "blocked or not validly derived from the type definition "
24999 "of the element declaration",
25000 xmlSchemaFormatQName(&str,
25001 (*localType)->targetNamespace,
25002 (*localType)->name),
25003 NULL);
25004 FREE_AND_NULL(str);
25005 ret = vctxt->err;
25006 *localType = NULL;
25007 }
25008 }
25009 }
25010exit:
25011 ACTIVATE_ELEM;
25012 return (ret);
25013internal_error:
25014 ACTIVATE_ELEM;
25015 return (-1);
25016}
25017
25018static int
25019xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25020{
25021 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Daniel Veillard14b56432006-03-09 18:41:40 +000025022 xmlSchemaTypePtr actualType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025023
25024 /*
25025 * cvc-elt (3.3.4) : 1
25026 */
25027 if (elemDecl == NULL) {
25028 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25029 "No matching declaration available");
25030 return (vctxt->err);
25031 }
Daniel Veillard14b56432006-03-09 18:41:40 +000025032 actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025033 /*
25034 * cvc-elt (3.3.4) : 2
25035 */
25036 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25037 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25038 "The element declaration is abstract");
25039 return (vctxt->err);
25040 }
25041 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025042 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25043 "The type definition is absent");
25044 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025045 }
25046 if (vctxt->nbAttrInfos != 0) {
25047 int ret;
25048 xmlSchemaAttrInfoPtr iattr;
25049 /*
25050 * cvc-elt (3.3.4) : 3
25051 * Handle 'xsi:nil'.
25052 */
25053 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25054 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25055 if (iattr) {
25056 ACTIVATE_ATTRIBUTE(iattr);
25057 /*
25058 * Validate the value.
25059 */
25060 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025061 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025062 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25063 iattr->value, &(iattr->val), 1, 0, 0);
25064 ACTIVATE_ELEM;
25065 if (ret < 0) {
25066 VERROR_INT("xmlSchemaValidateElemDecl",
25067 "calling xmlSchemaVCheckCVCSimpleType() to "
25068 "validate the attribute 'xsi:nil'");
25069 return (-1);
25070 }
25071 if (ret == 0) {
25072 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25073 /*
25074 * cvc-elt (3.3.4) : 3.1
25075 */
25076 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25077 "The element is not 'nillable'");
25078 /* Does not return an error on purpose. */
25079 } else {
25080 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25081 /*
25082 * cvc-elt (3.3.4) : 3.2.2
25083 */
25084 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25085 (elemDecl->value != NULL)) {
25086 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25087 "The element cannot be 'nilled' because "
25088 "there is a fixed value constraint defined "
25089 "for it");
25090 /* Does not return an error on purpose. */
25091 } else
25092 vctxt->inode->flags |=
25093 XML_SCHEMA_ELEM_INFO_NILLED;
25094 }
25095 }
25096 }
25097 }
25098 /*
25099 * cvc-elt (3.3.4) : 4
25100 * Handle 'xsi:type'.
25101 */
25102 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25103 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25104 if (iattr) {
25105 xmlSchemaTypePtr localType = NULL;
25106
25107 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25108 elemDecl);
25109 if (ret != 0) {
25110 if (ret == -1) {
25111 VERROR_INT("xmlSchemaValidateElemDecl",
25112 "calling xmlSchemaProcessXSIType() to "
25113 "process the attribute 'xsi:type'");
25114 return (-1);
25115 }
25116 /* Does not return an error on purpose. */
25117 }
25118 if (localType != NULL) {
25119 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25120 actualType = localType;
25121 }
25122 }
25123 }
25124 /*
25125 * IDC: Register identity-constraint XPath matchers.
25126 */
25127 if ((elemDecl->idcs != NULL) &&
25128 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25129 return (-1);
25130 /*
25131 * No actual type definition.
25132 */
25133 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025134 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25135 "The type definition is absent");
25136 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025137 }
25138 /*
25139 * Remember the actual type definition.
25140 */
25141 vctxt->inode->typeDef = actualType;
25142
25143 return (0);
25144}
25145
25146static int
25147xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25148{
25149 xmlSchemaAttrInfoPtr iattr;
25150 int ret = 0, i;
25151
25152 /*
25153 * SPEC cvc-type (3.1.1)
25154 * "The attributes of must be empty, excepting those whose namespace
25155 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25156 * whose local name is one of type, nil, schemaLocation or
25157 * noNamespaceSchemaLocation."
25158 */
25159 if (vctxt->nbAttrInfos == 0)
25160 return (0);
25161 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25162 iattr = vctxt->attrInfos[i];
25163 if (! iattr->metaType) {
25164 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025165 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025166 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25167 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25168 }
25169 }
25170 ACTIVATE_ELEM
25171 return (ret);
25172}
25173
25174/*
25175* Cleanup currently used attribute infos.
25176*/
25177static void
25178xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25179{
25180 int i;
25181 xmlSchemaAttrInfoPtr attr;
25182
25183 if (vctxt->nbAttrInfos == 0)
25184 return;
25185 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25186 attr = vctxt->attrInfos[i];
25187 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25188 if (attr->localName != NULL)
25189 xmlFree((xmlChar *) attr->localName);
25190 if (attr->nsName != NULL)
25191 xmlFree((xmlChar *) attr->nsName);
25192 }
25193 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25194 if (attr->value != NULL)
25195 xmlFree((xmlChar *) attr->value);
25196 }
25197 if (attr->val != NULL) {
25198 xmlSchemaFreeValue(attr->val);
25199 attr->val = NULL;
25200 }
25201 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25202 }
25203 vctxt->nbAttrInfos = 0;
25204}
25205
25206/*
25207* 3.4.4 Complex Type Definition Validation Rules
25208* Element Locally Valid (Complex Type) (cvc-complex-type)
25209* 3.2.4 Attribute Declaration Validation Rules
25210* Validation Rule: Attribute Locally Valid (cvc-attribute)
25211* Attribute Locally Valid (Use) (cvc-au)
25212*
25213* Only "assessed" attribute information items will be visible to
25214* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25215*/
25216static int
25217xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25218{
Daniel Veillarddee23482008-04-11 12:58:43 +000025219 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025220 xmlSchemaItemListPtr attrUseList;
25221 xmlSchemaAttributeUsePtr attrUse = NULL;
25222 xmlSchemaAttributePtr attrDecl = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000025223 xmlSchemaAttrInfoPtr iattr, tmpiattr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025224 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025225 int xpathRes = 0, res, wildIDs = 0, fixed;
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025226 xmlNodePtr defAttrOwnerElem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025227
25228 /*
25229 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025230 * (1) "The declaration must not be `absent` (see Missing
25231 * Sub-components ($5.3) for how this can fail to be
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025232 * the case)."
25233 * (2) "Its {type definition} must not be absent."
25234 *
25235 * NOTE (1) + (2): This is not handled here, since we currently do not
25236 * allow validation against schemas which have missing sub-components.
25237 *
25238 * SPEC (cvc-complex-type)
25239 * (3) "For each attribute information item in the element information
25240 * item's [attributes] excepting those whose [namespace name] is
25241 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25242 * [local name] is one of type, nil, schemaLocation or
25243 * noNamespaceSchemaLocation, the appropriate case among the following
25244 * must be true:
25245 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025246 */
25247 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25248 /*
25249 * @nbAttrs is the number of attributes present in the instance.
25250 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025251 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025252 if (attrUseList != NULL)
25253 nbUses = attrUseList->nbItems;
25254 else
25255 nbUses = 0;
25256 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025257 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025258 attrUse = attrUseList->items[i];
25259 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25260 for (j = 0; j < nbAttrs; j++) {
25261 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025262 /*
25263 * SPEC (cvc-complex-type) (3)
25264 * Skip meta attributes.
25265 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025266 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025267 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025268 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025269 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025270 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025271 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025272 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025273 continue;
25274 found = 1;
25275 /*
25276 * SPEC (cvc-complex-type)
25277 * (3.1) "If there is among the {attribute uses} an attribute
25278 * use with an {attribute declaration} whose {name} matches
25279 * the attribute information item's [local name] and whose
25280 * {target namespace} is identical to the attribute information
Jan Pokorný761c9e92013-11-29 23:26:27 +010025281 * item's [namespace name] (where an `absent` {target namespace}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025282 * is taken to be identical to a [namespace name] with no value),
Jan Pokorný761c9e92013-11-29 23:26:27 +010025283 * then the attribute information must be `valid` with respect
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025284 * to that attribute use as per Attribute Locally Valid (Use)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025285 * ($3.5.4). In this case the {attribute declaration} of that
25286 * attribute use is the `context-determined declaration` for the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025287 * attribute information item with respect to Schema-Validity
Jan Pokorný761c9e92013-11-29 23:26:27 +010025288 * Assessment (Attribute) ($3.2.4) and
25289 * Assessment Outcome (Attribute) ($3.2.5).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025290 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025291 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25292 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025293 /*
25294 * Context-determined declaration.
25295 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025296 iattr->decl = attrDecl;
25297 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025298 break;
25299 }
25300
25301 if (found)
25302 continue;
25303
25304 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25305 /*
25306 * Handle non-existent, required attributes.
25307 *
25308 * SPEC (cvc-complex-type)
25309 * (4) "The {attribute declaration} of each attribute use in
25310 * the {attribute uses} whose {required} is true matches one
25311 * of the attribute information items in the element information
25312 * item's [attributes] as per clause 3.1 above."
25313 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025314 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25315 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025316 VERROR_INT(
25317 "xmlSchemaVAttributesComplex",
25318 "calling xmlSchemaGetFreshAttrInfo()");
25319 return (-1);
25320 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025321 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25322 tmpiattr->use = attrUse;
Daniel Veillarddee23482008-04-11 12:58:43 +000025323 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025324 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25325 ((attrUse->defValue != NULL) ||
25326 (attrDecl->defValue != NULL))) {
25327 /*
25328 * Handle non-existent, optional, default/fixed attributes.
25329 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025330 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25331 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025332 VERROR_INT(
25333 "xmlSchemaVAttributesComplex",
25334 "calling xmlSchemaGetFreshAttrInfo()");
25335 return (-1);
25336 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025337 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25338 tmpiattr->use = attrUse;
25339 tmpiattr->decl = attrDecl;
25340 tmpiattr->typeDef = attrDecl->subtypes;
25341 tmpiattr->localName = attrDecl->name;
25342 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025343 }
25344 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025345
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025346 if (vctxt->nbAttrInfos == 0)
25347 return (0);
25348 /*
25349 * Validate against the wildcard.
25350 */
25351 if (type->attributeWildcard != NULL) {
25352 /*
25353 * SPEC (cvc-complex-type)
25354 * (3.2.1) "There must be an {attribute wildcard}."
25355 */
25356 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025357 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025358 /*
25359 * SPEC (cvc-complex-type) (3)
25360 * Skip meta attributes.
25361 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025362 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025363 continue;
25364 /*
25365 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025366 * (3.2.2) "The attribute information item must be `valid` with
25367 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025368 *
25369 * SPEC Item Valid (Wildcard) (cvc-wildcard)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025370 * "... its [namespace name] must be `valid` with respect to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025371 * the wildcard constraint, as defined in Wildcard allows
Jan Pokorný761c9e92013-11-29 23:26:27 +010025372 * Namespace Name ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025373 */
25374 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025375 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025376 /*
25377 * Handle processContents.
25378 *
25379 * SPEC (cvc-wildcard):
25380 * processContents | context-determined declaration:
25381 * "strict" "mustFind"
25382 * "lax" "none"
25383 * "skip" "skip"
25384 */
25385 if (type->attributeWildcard->processContents ==
25386 XML_SCHEMAS_ANY_SKIP) {
25387 /*
25388 * context-determined declaration = "skip"
25389 *
25390 * SPEC PSVI Assessment Outcome (Attribute)
25391 * [validity] = "notKnown"
25392 * [validation attempted] = "none"
25393 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025394 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025395 continue;
25396 }
25397 /*
25398 * Find an attribute declaration.
25399 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025400 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25401 iattr->localName, iattr->nsName);
25402 if (iattr->decl != NULL) {
25403 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025404 /*
25405 * SPEC (cvc-complex-type)
25406 * (5) "Let [Definition:] the wild IDs be the set of
25407 * all attribute information item to which clause 3.2
Jan Pokorný761c9e92013-11-29 23:26:27 +010025408 * applied and whose `validation` resulted in a
25409 * `context-determined declaration` of mustFind or no
25410 * `context-determined declaration` at all, and whose
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025411 * [local name] and [namespace name] resolve (as
Jan Pokorný761c9e92013-11-29 23:26:27 +010025412 * defined by QName resolution (Instance) ($3.15.4)) to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025413 * an attribute declaration whose {type definition} is
25414 * or is derived from ID. Then all of the following
25415 * must be true:"
25416 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025417 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025418 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025419 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025420 /*
25421 * SPEC (5.1) "There must be no more than one
Jan Pokorný761c9e92013-11-29 23:26:27 +010025422 * item in `wild IDs`."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025423 */
25424 if (wildIDs != 0) {
25425 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025426 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025427 TODO
25428 continue;
25429 }
25430 wildIDs++;
25431 /*
25432 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025433 * (5.2) "If `wild IDs` is non-empty, there must not
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025434 * be any attribute uses among the {attribute uses}
25435 * whose {attribute declaration}'s {type definition}
25436 * is or is derived from ID."
25437 */
Daniel Veillard2cdd17e2009-07-27 21:16:13 +020025438 if (attrUseList != NULL) {
25439 for (j = 0; j < attrUseList->nbItems; j++) {
25440 if (xmlSchemaIsDerivedFromBuiltInType(
25441 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25442 XML_SCHEMAS_ID)) {
25443 /* URGENT VAL TODO: implement */
25444 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25445 TODO
25446 break;
25447 }
25448 }
25449 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025450 }
25451 } else if (type->attributeWildcard->processContents ==
25452 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025453 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025454 /*
25455 * SPEC PSVI Assessment Outcome (Attribute)
25456 * [validity] = "notKnown"
25457 * [validation attempted] = "none"
25458 */
25459 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025460 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025461 }
25462 }
25463 }
25464 }
25465
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025466 if (vctxt->nbAttrInfos == 0)
25467 return (0);
25468
25469 /*
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025470 * Get the owner element; needed for creation of default attributes.
25471 * This fixes bug #341337, reported by David Grohmann.
25472 */
25473 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25474 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25475 if (ielem && ielem->node && ielem->node->doc)
25476 defAttrOwnerElem = ielem->node;
25477 }
25478 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025479 * Validate values, create default attributes, evaluate IDCs.
25480 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025481 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025482 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025483 /*
25484 * VAL TODO: Note that we won't try to resolve IDCs to
25485 * "lax" and "skip" validated attributes. Check what to
25486 * do in this case.
25487 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025488 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25489 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025490 continue;
25491 /*
25492 * VAL TODO: What to do if the type definition is missing?
25493 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025494 if (iattr->typeDef == NULL) {
25495 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025496 continue;
25497 }
25498
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025499 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025500 fixed = 0;
25501 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025502
25503 if (vctxt->xpathStates != NULL) {
25504 /*
25505 * Evaluate IDCs.
25506 */
25507 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25508 XML_ATTRIBUTE_NODE);
25509 if (xpathRes == -1) {
25510 VERROR_INT("xmlSchemaVAttributesComplex",
25511 "calling xmlSchemaXPathEvaluate()");
25512 goto internal_error;
25513 }
25514 }
25515
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025516 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025517 /*
25518 * Default/fixed attributes.
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025519 * We need the value only if we need to resolve IDCs or
25520 * will create default attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025521 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025522 if ((xpathRes) || (defAttrOwnerElem)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025523 if (iattr->use->defValue != NULL) {
25524 iattr->value = (xmlChar *) iattr->use->defValue;
25525 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025526 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025527 iattr->value = (xmlChar *) iattr->decl->defValue;
25528 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025529 }
25530 /*
25531 * IDCs will consume the precomputed default value,
25532 * so we need to clone it.
25533 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025534 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025535 VERROR_INT("xmlSchemaVAttributesComplex",
25536 "default/fixed value on an attribute use was "
25537 "not precomputed");
25538 goto internal_error;
25539 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025540 iattr->val = xmlSchemaCopyValue(iattr->val);
25541 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025542 VERROR_INT("xmlSchemaVAttributesComplex",
25543 "calling xmlSchemaCopyValue()");
25544 goto internal_error;
25545 }
25546 }
25547 /*
25548 * PSVI: Add the default attribute to the current element.
25549 * VAL TODO: Should we use the *normalized* value? This currently
25550 * uses the *initial* value.
25551 */
Daniel Veillarddee23482008-04-11 12:58:43 +000025552
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025553 if (defAttrOwnerElem) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025554 xmlChar *normValue;
25555 const xmlChar *value;
25556
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025557 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025558 /*
25559 * Normalize the value.
25560 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025561 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25562 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025563 if (normValue != NULL)
25564 value = BAD_CAST normValue;
25565
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025566 if (iattr->nsName == NULL) {
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025567 if (xmlNewProp(defAttrOwnerElem,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025568 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025569 VERROR_INT("xmlSchemaVAttributesComplex",
Alex Henrie73c50802015-10-26 18:33:14 +080025570 "calling xmlNewProp()");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025571 if (normValue != NULL)
25572 xmlFree(normValue);
25573 goto internal_error;
25574 }
25575 } else {
25576 xmlNsPtr ns;
25577
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025578 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25579 defAttrOwnerElem, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025580 if (ns == NULL) {
25581 xmlChar prefix[12];
25582 int counter = 0;
25583
25584 /*
25585 * Create a namespace declaration on the validation
25586 * root node if no namespace declaration is in scope.
25587 */
25588 do {
25589 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025590 ns = xmlSearchNs(defAttrOwnerElem->doc,
25591 defAttrOwnerElem, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025592 if (counter > 1000) {
25593 VERROR_INT(
25594 "xmlSchemaVAttributesComplex",
25595 "could not compute a ns prefix for a "
25596 "default/fixed attribute");
25597 if (normValue != NULL)
25598 xmlFree(normValue);
25599 goto internal_error;
25600 }
25601 } while (ns != NULL);
25602 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025603 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025604 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025605 /*
25606 * TODO:
25607 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25608 * If we have QNames: do we need to ensure there's a
25609 * prefix defined for the QName?
25610 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025611 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025612 }
25613 if (normValue != NULL)
25614 xmlFree(normValue);
25615 }
25616 /*
25617 * Go directly to IDC evaluation.
25618 */
25619 goto eval_idcs;
25620 }
25621 /*
25622 * Validate the value.
25623 */
25624 if (vctxt->value != NULL) {
25625 /*
25626 * Free last computed value; just for safety reasons.
25627 */
25628 xmlSchemaFreeValue(vctxt->value);
25629 vctxt->value = NULL;
25630 }
25631 /*
25632 * Note that the attribute *use* can be unavailable, if
25633 * the attribute was a wild attribute.
25634 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025635 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25636 ((iattr->use != NULL) &&
25637 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025638 fixed = 1;
25639 else
25640 fixed = 0;
25641 /*
25642 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025643 * (3) "The item's `normalized value` must be locally `valid`
Daniel Veillarddee23482008-04-11 12:58:43 +000025644 * with respect to that {type definition} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010025645 * String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025646 *
25647 * VAL TODO: Do we already have the
25648 * "normalized attribute value" here?
25649 */
25650 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025651 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025652 /*
25653 * Request a computed value.
25654 */
25655 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025656 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025657 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025658 1, 1, 0);
25659 } else {
25660 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025661 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025662 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025663 1, 0, 0);
25664 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025665
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025666 if (res != 0) {
25667 if (res == -1) {
25668 VERROR_INT("xmlSchemaVAttributesComplex",
25669 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25670 goto internal_error;
25671 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025672 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025673 /*
25674 * SPEC PSVI Assessment Outcome (Attribute)
25675 * [validity] = "invalid"
25676 */
25677 goto eval_idcs;
25678 }
25679
Daniel Veillarddee23482008-04-11 12:58:43 +000025680 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025681 /*
25682 * SPEC Attribute Locally Valid (Use) (cvc-au)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025683 * "For an attribute information item to be `valid`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025684 * with respect to an attribute use its *normalized*
Jan Pokorný761c9e92013-11-29 23:26:27 +010025685 * value must match the *canonical* lexical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025686 * representation of the attribute use's {value
25687 * constraint}value, if it is present and fixed."
25688 *
25689 * VAL TODO: The requirement for the *canonical* value
25690 * will be removed in XML Schema 1.1.
25691 */
25692 /*
25693 * SPEC Attribute Locally Valid (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025694 * (4) "The item's *actual* value must match the *value* of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025695 * the {value constraint}, if it is present and fixed."
25696 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025697 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025698 /* VAL TODO: A value was not precomputed. */
25699 TODO
25700 goto eval_idcs;
25701 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025702 if ((iattr->use != NULL) &&
25703 (iattr->use->defValue != NULL)) {
25704 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025705 /* VAL TODO: A default value was not precomputed. */
25706 TODO
25707 goto eval_idcs;
25708 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025709 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025710 /*
25711 if (xmlSchemaCompareValuesWhtsp(attr->val,
25712 (xmlSchemaWhitespaceValueType) ws,
25713 attr->use->defVal,
25714 (xmlSchemaWhitespaceValueType) ws) != 0) {
25715 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025716 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25717 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025718 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025719 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025720 /* VAL TODO: A default value was not precomputed. */
25721 TODO
25722 goto eval_idcs;
25723 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025724 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025725 /*
25726 if (xmlSchemaCompareValuesWhtsp(attr->val,
25727 (xmlSchemaWhitespaceValueType) ws,
25728 attrDecl->defVal,
25729 (xmlSchemaWhitespaceValueType) ws) != 0) {
25730 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025731 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25732 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025733 }
25734 /*
25735 * [validity] = "valid"
25736 */
25737 }
25738eval_idcs:
25739 /*
25740 * Evaluate IDCs.
25741 */
25742 if (xpathRes) {
25743 if (xmlSchemaXPathProcessHistory(vctxt,
25744 vctxt->depth +1) == -1) {
25745 VERROR_INT("xmlSchemaVAttributesComplex",
25746 "calling xmlSchemaXPathEvaluate()");
25747 goto internal_error;
25748 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025749 } else if (vctxt->xpathStates != NULL)
25750 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025751 }
25752
25753 /*
25754 * Report errors.
25755 */
25756 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025757 iattr = vctxt->attrInfos[i];
25758 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25759 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25760 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25761 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025762 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025763 ACTIVATE_ATTRIBUTE(iattr);
25764 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025765 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25766 xmlChar *str = NULL;
25767 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025768 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025769 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25770 "The attribute '%s' is required but missing",
25771 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025772 iattr->decl->targetNamespace,
25773 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025774 NULL);
25775 FREE_AND_NULL(str)
25776 break;
25777 }
25778 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25779 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25780 "The type definition is absent");
25781 break;
25782 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025783 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025784 XML_SCHEMAV_CVC_AU, NULL, NULL,
25785 "The value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000025786 "value constraint '%s'",
25787 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025788 break;
25789 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25790 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25791 "No matching global attribute declaration available, but "
25792 "demanded by the strict wildcard");
25793 break;
25794 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025795 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025796 break;
25797 /*
25798 * MAYBE VAL TODO: One might report different error messages
25799 * for the following errors.
25800 */
25801 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025802 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025803 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025804 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025805 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025806 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025807 }
25808 break;
25809 default:
25810 break;
25811 }
25812 }
25813
25814 ACTIVATE_ELEM;
25815 return (0);
25816internal_error:
25817 ACTIVATE_ELEM;
25818 return (-1);
25819}
25820
25821static int
25822xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25823 int *skip)
25824{
25825 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25826 /*
25827 * The namespace of the element was already identified to be
25828 * matching the wildcard.
25829 */
25830 if ((skip == NULL) || (wild == NULL) ||
25831 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25832 VERROR_INT("xmlSchemaValidateElemWildcard",
25833 "bad arguments");
25834 return (-1);
25835 }
25836 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025837 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25838 /*
25839 * URGENT VAL TODO: Either we need to position the stream to the
25840 * next sibling, or walk the whole subtree.
25841 */
25842 *skip = 1;
25843 return (0);
25844 }
25845 {
25846 xmlSchemaElementPtr decl = NULL;
25847
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025848 decl = xmlSchemaGetElem(vctxt->schema,
Daniel Veillarddee23482008-04-11 12:58:43 +000025849 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025850 if (decl != NULL) {
25851 vctxt->inode->decl = decl;
25852 return (0);
25853 }
25854 }
25855 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25856 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025857 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025858 "No matching global element declaration available, but "
25859 "demanded by the strict wildcard");
25860 return (vctxt->err);
25861 }
25862 if (vctxt->nbAttrInfos != 0) {
25863 xmlSchemaAttrInfoPtr iattr;
25864 /*
25865 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25866 * (1.2.1.2.1) - (1.2.1.2.3 )
25867 *
25868 * Use the xsi:type attribute for the type definition.
25869 */
25870 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25871 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25872 if (iattr != NULL) {
25873 if (xmlSchemaProcessXSIType(vctxt, iattr,
25874 &(vctxt->inode->typeDef), NULL) == -1) {
25875 VERROR_INT("xmlSchemaValidateElemWildcard",
25876 "calling xmlSchemaProcessXSIType() to "
25877 "process the attribute 'xsi:nil'");
25878 return (-1);
25879 }
25880 /*
25881 * Don't return an error on purpose.
25882 */
25883 return (0);
25884 }
25885 }
25886 /*
25887 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25888 *
25889 * Fallback to "anyType".
25890 */
25891 vctxt->inode->typeDef =
25892 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25893 return (0);
25894}
25895
25896/*
25897* xmlSchemaCheckCOSValidDefault:
25898*
25899* This will be called if: not nilled, no content and a default/fixed
25900* value is provided.
25901*/
25902
25903static int
25904xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25905 const xmlChar *value,
25906 xmlSchemaValPtr *val)
Daniel Veillarddee23482008-04-11 12:58:43 +000025907{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025908 int ret = 0;
25909 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25910
25911 /*
25912 * cos-valid-default:
25913 * Schema Component Constraint: Element Default Valid (Immediate)
Daniel Veillarddee23482008-04-11 12:58:43 +000025914 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025915 * definition the appropriate case among the following must be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000025916 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025917 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025918 /*
25919 * Complex type.
25920 *
25921 * SPEC (2.1) "its {content type} must be a simple type definition
25922 * or mixed."
25923 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010025924 * type}'s particle must be `emptiable` as defined by
25925 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025926 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025927 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25928 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25929 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025930 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25931 /* NOTE that this covers (2.2.2) as well. */
25932 VERROR(ret, NULL,
25933 "For a string to be a valid default, the type definition "
25934 "must be a simple type or a complex type with simple content "
25935 "or mixed content and a particle emptiable");
25936 return(ret);
25937 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025938 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025939 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000025940 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010025941 * must be `valid` with respect to that definition as defined by String
25942 * Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025943 *
25944 * AND
25945 *
Daniel Veillarddee23482008-04-11 12:58:43 +000025946 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010025947 * string must be `valid` with respect to that simple type definition
25948 * as defined by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000025949 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025950 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025951
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025952 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025953 NULL, inode->typeDef, value, val, 1, 1, 0);
25954
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025955 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025956
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025957 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025958 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25959 }
25960 if (ret < 0) {
25961 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25962 "calling xmlSchemaVCheckCVCSimpleType()");
Daniel Veillarddee23482008-04-11 12:58:43 +000025963 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025964 return (ret);
25965}
25966
25967static void
25968xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25969 const xmlChar * name ATTRIBUTE_UNUSED,
25970 xmlSchemaElementPtr item,
25971 xmlSchemaNodeInfoPtr inode)
25972{
25973 inode->decl = item;
25974#ifdef DEBUG_CONTENT
25975 {
25976 xmlChar *str = NULL;
25977
25978 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25979 xmlGenericError(xmlGenericErrorContext,
25980 "AUTOMATON callback for '%s' [declaration]\n",
25981 xmlSchemaFormatQName(&str,
25982 inode->localName, inode->nsName));
25983 } else {
25984 xmlGenericError(xmlGenericErrorContext,
25985 "AUTOMATON callback for '%s' [wildcard]\n",
25986 xmlSchemaFormatQName(&str,
25987 inode->localName, inode->nsName));
25988
25989 }
25990 FREE_AND_NULL(str)
25991 }
25992#endif
25993}
25994
25995static int
25996xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Daniel Veillarddee23482008-04-11 12:58:43 +000025997{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025998 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25999 if (vctxt->inode == NULL) {
26000 VERROR_INT("xmlSchemaValidatorPushElem",
26001 "calling xmlSchemaGetFreshElemInfo()");
26002 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000026003 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026004 vctxt->nbAttrInfos = 0;
26005 return (0);
26006}
26007
26008static int
26009xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26010 xmlSchemaNodeInfoPtr inode,
26011 xmlSchemaTypePtr type,
26012 const xmlChar *value)
26013{
26014 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26015 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026016 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026017 type, value, &(inode->val), 1, 1, 0));
26018 else
26019 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026020 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026021 type, value, NULL, 1, 0, 0));
26022}
26023
26024
26025
Daniel Veillarddee23482008-04-11 12:58:43 +000026026/*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026027* Process END of element.
26028*/
26029static int
26030xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26031{
26032 int ret = 0;
26033 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26034
26035 if (vctxt->nbAttrInfos != 0)
26036 xmlSchemaClearAttrInfos(vctxt);
26037 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26038 /*
26039 * This element was not expected;
26040 * we will not validate child elements of broken parents.
26041 * Skip validation of all content of the parent.
26042 */
26043 vctxt->skipDepth = vctxt->depth -1;
26044 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026045 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026046 if ((inode->typeDef == NULL) ||
26047 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26048 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026049 * 1. the type definition might be missing if the element was
26050 * error prone
26051 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026052 */
26053 goto end_elem;
26054 }
26055 /*
26056 * Check the content model.
26057 */
26058 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26059 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26060
26061 /*
26062 * Workaround for "anyType".
26063 */
26064 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
Daniel Veillarddee23482008-04-11 12:58:43 +000026065 goto character_content;
26066
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026067 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26068 xmlChar *values[10];
26069 int terminal, nbval = 10, nbneg;
26070
26071 if (inode->regexCtxt == NULL) {
26072 /*
26073 * Create the regex context.
26074 */
26075 inode->regexCtxt =
26076 xmlRegNewExecCtxt(inode->typeDef->contModel,
26077 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26078 vctxt);
26079 if (inode->regexCtxt == NULL) {
26080 VERROR_INT("xmlSchemaValidatorPopElem",
26081 "failed to create a regex context");
26082 goto internal_error;
26083 }
26084#ifdef DEBUG_AUTOMATA
26085 xmlGenericError(xmlGenericErrorContext,
26086 "AUTOMATON create on '%s'\n", inode->localName);
Daniel Veillarddee23482008-04-11 12:58:43 +000026087#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026088 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026089
26090 /*
26091 * Do not check further content if the node has been nilled
26092 */
26093 if (INODE_NILLED(inode)) {
26094 ret = 0;
26095#ifdef DEBUG_AUTOMATA
26096 xmlGenericError(xmlGenericErrorContext,
26097 "AUTOMATON succeeded on nilled '%s'\n",
26098 inode->localName);
26099#endif
26100 goto skip_nilled;
26101 }
26102
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026103 /*
26104 * Get hold of the still expected content, since a further
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020026105 * call to xmlRegExecPushString() will lose this information.
Daniel Veillarddee23482008-04-11 12:58:43 +000026106 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026107 xmlRegExecNextValues(inode->regexCtxt,
26108 &nbval, &nbneg, &values[0], &terminal);
26109 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
Daniel Veillard65fcf272007-07-11 17:55:30 +000026110 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026111 /*
26112 * Still missing something.
26113 */
26114 ret = 1;
26115 inode->flags |=
26116 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026117 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026118 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26119 "Missing child element(s)",
26120 nbval, nbneg, values);
26121#ifdef DEBUG_AUTOMATA
26122 xmlGenericError(xmlGenericErrorContext,
26123 "AUTOMATON missing ERROR on '%s'\n",
26124 inode->localName);
26125#endif
26126 } else {
26127 /*
26128 * Content model is satisfied.
26129 */
26130 ret = 0;
26131#ifdef DEBUG_AUTOMATA
26132 xmlGenericError(xmlGenericErrorContext,
26133 "AUTOMATON succeeded on '%s'\n",
26134 inode->localName);
26135#endif
26136 }
26137
26138 }
26139 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026140
26141skip_nilled:
26142
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026143 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26144 goto end_elem;
26145
26146character_content:
26147
26148 if (vctxt->value != NULL) {
26149 xmlSchemaFreeValue(vctxt->value);
26150 vctxt->value = NULL;
26151 }
26152 /*
26153 * Check character content.
26154 */
26155 if (inode->decl == NULL) {
26156 /*
26157 * Speedup if no declaration exists.
26158 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026159 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026160 ret = xmlSchemaVCheckINodeDataType(vctxt,
26161 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026162 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026163 ret = xmlSchemaVCheckINodeDataType(vctxt,
26164 inode, inode->typeDef->contentTypeDef,
26165 inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026166 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026167 if (ret < 0) {
26168 VERROR_INT("xmlSchemaValidatorPopElem",
26169 "calling xmlSchemaVCheckCVCSimpleType()");
26170 goto internal_error;
26171 }
26172 goto end_elem;
26173 }
26174 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026175 * cvc-elt (3.3.4) : 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026176 * The appropriate case among the following must be true:
26177 */
26178 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026179 * cvc-elt (3.3.4) : 5.1
26180 * If the declaration has a {value constraint},
26181 * the item has neither element nor character [children] and
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026182 * clause 3.2 has not applied, then all of the following must be true:
26183 */
26184 if ((inode->decl->value != NULL) &&
Daniel Veillarddee23482008-04-11 12:58:43 +000026185 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026186 (! INODE_NILLED(inode))) {
26187 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026188 * cvc-elt (3.3.4) : 5.1.1
Jan Pokorný761c9e92013-11-29 23:26:27 +010026189 * If the `actual type definition` is a `local type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026190 * then the canonical lexical representation of the {value constraint}
Jan Pokorný761c9e92013-11-29 23:26:27 +010026191 * value must be a valid default for the `actual type definition` as
26192 * defined in Element Default Valid (Immediate) ($3.3.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026193 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026194 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026195 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026196 * NOTE: Although the *canonical* value is stated, it is not
26197 * relevant if canonical or not. Additionally XML Schema 1.1
26198 * will removed this requirement as well.
26199 */
26200 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26201
26202 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26203 inode->decl->value, &(inode->val));
26204 if (ret != 0) {
26205 if (ret < 0) {
26206 VERROR_INT("xmlSchemaValidatorPopElem",
26207 "calling xmlSchemaCheckCOSValidDefault()");
26208 goto internal_error;
26209 }
26210 goto end_elem;
26211 }
26212 /*
26213 * Stop here, to avoid redundant validation of the value
26214 * (see following).
26215 */
26216 goto default_psvi;
Daniel Veillarddee23482008-04-11 12:58:43 +000026217 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026218 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026219 * cvc-elt (3.3.4) : 5.1.2
26220 * The element information item with the canonical lexical
26221 * representation of the {value constraint} value used as its
Jan Pokorný761c9e92013-11-29 23:26:27 +010026222 * `normalized value` must be `valid` with respect to the
26223 * `actual type definition` as defined by Element Locally Valid (Type)
26224 * ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026225 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026226 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026227 ret = xmlSchemaVCheckINodeDataType(vctxt,
26228 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026229 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026230 ret = xmlSchemaVCheckINodeDataType(vctxt,
26231 inode, inode->typeDef->contentTypeDef,
Daniel Veillarddee23482008-04-11 12:58:43 +000026232 inode->decl->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026233 }
26234 if (ret != 0) {
26235 if (ret < 0) {
26236 VERROR_INT("xmlSchemaValidatorPopElem",
26237 "calling xmlSchemaVCheckCVCSimpleType()");
26238 goto internal_error;
26239 }
26240 goto end_elem;
26241 }
26242
26243default_psvi:
26244 /*
26245 * PSVI: Create a text node on the instance element.
26246 */
26247 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26248 (inode->node != NULL)) {
26249 xmlNodePtr textChild;
26250 xmlChar *normValue;
26251 /*
26252 * VAL TODO: Normalize the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000026253 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026254 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26255 inode->decl->value);
26256 if (normValue != NULL) {
26257 textChild = xmlNewText(BAD_CAST normValue);
26258 xmlFree(normValue);
26259 } else
26260 textChild = xmlNewText(inode->decl->value);
26261 if (textChild == NULL) {
26262 VERROR_INT("xmlSchemaValidatorPopElem",
26263 "calling xmlNewText()");
26264 goto internal_error;
26265 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000026266 xmlAddChild(inode->node, textChild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026267 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026268
26269 } else if (! INODE_NILLED(inode)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026270 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026271 * 5.2.1 The element information item must be `valid` with respect
26272 * to the `actual type definition` as defined by Element Locally
26273 * Valid (Type) ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026274 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026275 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026276 /*
26277 * SPEC (cvc-type) (3.1)
26278 * "If the type definition is a simple type definition, ..."
26279 * (3.1.3) "If clause 3.2 of Element Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026280 * (Element) ($3.3.4) did not apply, then the `normalized value`
26281 * must be `valid` with respect to the type definition as defined
26282 * by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026283 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026284 ret = xmlSchemaVCheckINodeDataType(vctxt,
26285 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026286 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026287 /*
26288 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26289 * definition, then the element information item must be
Jan Pokorný761c9e92013-11-29 23:26:27 +010026290 * `valid` with respect to the type definition as per
26291 * Element Locally Valid (Complex Type) ($3.4.4);"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026292 *
26293 * SPEC (cvc-complex-type) (2.2)
Daniel Veillarddee23482008-04-11 12:58:43 +000026294 * "If the {content type} is a simple type definition, ...
Jan Pokorný761c9e92013-11-29 23:26:27 +010026295 * the `normalized value` of the element information item is
26296 * `valid` with respect to that simple type definition as
26297 * defined by String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026298 */
26299 ret = xmlSchemaVCheckINodeDataType(vctxt,
26300 inode, inode->typeDef->contentTypeDef, inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026301 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026302 if (ret != 0) {
26303 if (ret < 0) {
26304 VERROR_INT("xmlSchemaValidatorPopElem",
26305 "calling xmlSchemaVCheckCVCSimpleType()");
26306 goto internal_error;
26307 }
26308 goto end_elem;
26309 }
26310 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026311 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026312 * not applied, all of the following must be true:
26313 */
26314 if ((inode->decl->value != NULL) &&
26315 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26316
26317 /*
26318 * TODO: We will need a computed value, when comparison is
26319 * done on computed values.
26320 */
26321 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026322 * 5.2.2.1 The element information item must have no element
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026323 * information item [children].
26324 */
26325 if (inode->flags &
26326 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26327 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26328 VERROR(ret, NULL,
26329 "The content must not containt element nodes since "
26330 "there is a fixed value constraint");
26331 goto end_elem;
26332 } else {
26333 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026334 * 5.2.2.2 The appropriate case among the following must
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026335 * be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000026336 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026337 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026338 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026339 * 5.2.2.2.1 If the {content type} of the `actual type
26340 * definition` is mixed, then the *initial value* of the
Daniel Veillarddee23482008-04-11 12:58:43 +000026341 * item must match the canonical lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026342 * of the {value constraint} value.
26343 *
Daniel Veillarddee23482008-04-11 12:58:43 +000026344 * ... the *initial value* of an element information
26345 * item is the string composed of, in order, the
26346 * [character code] of each character information item in
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026347 * the [children] of that element information item.
Daniel Veillarddee23482008-04-11 12:58:43 +000026348 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026349 if (! xmlStrEqual(inode->value, inode->decl->value)){
Daniel Veillarddee23482008-04-11 12:58:43 +000026350 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026351 * VAL TODO: Report invalid & expected values as well.
26352 * VAL TODO: Implement the canonical stuff.
26353 */
26354 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000026355 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026356 ret, NULL, NULL,
26357 "The initial value '%s' does not match the fixed "
26358 "value constraint '%s'",
26359 inode->value, inode->decl->value);
26360 goto end_elem;
26361 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026362 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026363 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026364 * 5.2.2.2.2 If the {content type} of the `actual type
26365 * definition` is a simple type definition, then the
Daniel Veillarddee23482008-04-11 12:58:43 +000026366 * *actual value* of the item must match the canonical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026367 * lexical representation of the {value constraint} value.
26368 */
26369 /*
26370 * VAL TODO: *actual value* is the normalized value, impl.
26371 * this.
26372 * VAL TODO: Report invalid & expected values as well.
26373 * VAL TODO: Implement a comparison with the computed values.
26374 */
26375 if (! xmlStrEqual(inode->value,
26376 inode->decl->value)) {
26377 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026378 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026379 ret, NULL, NULL,
26380 "The actual value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000026381 "value constraint '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026382 inode->value,
26383 inode->decl->value);
26384 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026385 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026386 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026387 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026388 }
26389 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026390
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026391end_elem:
26392 if (vctxt->depth < 0) {
26393 /* TODO: raise error? */
26394 return (0);
26395 }
26396 if (vctxt->depth == vctxt->skipDepth)
26397 vctxt->skipDepth = -1;
26398 /*
26399 * Evaluate the history of XPath state objects.
Daniel Veillarddee23482008-04-11 12:58:43 +000026400 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026401 if (inode->appliedXPath &&
26402 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026403 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026404 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026405 * MAYBE TODO:
Jan Pokorný761c9e92013-11-29 23:26:27 +010026406 * SPEC (6) "The element information item must be `valid` with
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026407 * respect to each of the {identity-constraint definitions} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010026408 * Identity-constraint Satisfied ($3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026409 */
26410 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026411 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26412 * need to be built in any case.
26413 * We will currently build IDC node-tables and bubble them only if
26414 * keyrefs do exist.
26415 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026416
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026417 /*
26418 * Add the current IDC target-nodes to the IDC node-tables.
26419 */
26420 if ((inode->idcMatchers != NULL) &&
26421 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26422 {
26423 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26424 goto internal_error;
26425 }
26426 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026427 * Validate IDC keyrefs.
26428 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026429 if (vctxt->inode->hasKeyrefs)
26430 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26431 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026432 /*
26433 * Merge/free the IDC table.
26434 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026435 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026436#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026437 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026438 inode->nsName,
26439 inode->localName,
26440 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026441#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026442 if ((vctxt->depth > 0) &&
26443 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26444 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026445 /*
26446 * Merge the IDC node table with the table of the parent node.
26447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026448 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26449 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000026450 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026451 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026452 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026453 * Clear the current ielem.
26454 * VAL TODO: Don't free the PSVI IDC tables if they are
26455 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026456 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000026457 xmlSchemaClearElemInfo(vctxt, inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026458 /*
26459 * Skip further processing if we are on the validation root.
26460 */
26461 if (vctxt->depth == 0) {
26462 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026463 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026464 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026465 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026466 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026467 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026468 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026469 if (vctxt->aidcs != NULL) {
26470 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26471 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026472 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026473 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026474 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026475 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026476 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026477 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026478 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026479 }
26480 aidc = aidc->next;
26481 } while (aidc != NULL);
26482 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026483 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026484 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026485 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026486 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26487 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026488 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026489 return (ret);
26490
26491internal_error:
26492 vctxt->err = -1;
26493 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026494}
26495
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026496/*
26497* 3.4.4 Complex Type Definition Validation Rules
26498* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26499*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026500static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026501xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026502{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026503 xmlSchemaNodeInfoPtr pielem;
26504 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026505 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026506
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026507 if (vctxt->depth <= 0) {
26508 VERROR_INT("xmlSchemaValidateChildElem",
26509 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026510 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026511 }
26512 pielem = vctxt->elemInfos[vctxt->depth -1];
26513 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26514 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026515 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026516 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026518 if (INODE_NILLED(pielem)) {
26519 /*
26520 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26521 */
26522 ACTIVATE_PARENT_ELEM;
26523 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26524 VERROR(ret, NULL,
26525 "Neither character nor element content is allowed, "
26526 "because the element was 'nilled'");
26527 ACTIVATE_ELEM;
26528 goto unexpected_elem;
26529 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026530
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026531 ptype = pielem->typeDef;
26532
26533 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26534 /*
26535 * Workaround for "anyType": we have currently no content model
26536 * assigned for "anyType", so handle it explicitely.
26537 * "anyType" has an unbounded, lax "any" wildcard.
26538 */
26539 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26540 vctxt->inode->localName,
26541 vctxt->inode->nsName);
26542
26543 if (vctxt->inode->decl == NULL) {
26544 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026545 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026546 * Process "xsi:type".
26547 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026548 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026549 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26550 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26551 if (iattr != NULL) {
26552 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26553 &(vctxt->inode->typeDef), NULL);
26554 if (ret != 0) {
26555 if (ret == -1) {
26556 VERROR_INT("xmlSchemaValidateChildElem",
26557 "calling xmlSchemaProcessXSIType() to "
26558 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026559 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026560 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026561 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026562 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026563 } else {
26564 /*
26565 * Fallback to "anyType".
26566 *
26567 * SPEC (cvc-assess-elt)
Jan Pokorný761c9e92013-11-29 23:26:27 +010026568 * "If the item cannot be `strictly assessed`, [...]
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026569 * an element information item's schema validity may be laxly
Jan Pokorný761c9e92013-11-29 23:26:27 +010026570 * assessed if its `context-determined declaration` is not
26571 * skip by `validating` with respect to the `ur-type
26572 * definition` as per Element Locally Valid (Type) ($3.3.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026573 */
26574 vctxt->inode->typeDef =
26575 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026576 }
26577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026578 return (0);
26579 }
26580
26581 switch (ptype->contentType) {
26582 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026584 * SPEC (2.1) "If the {content type} is empty, then the
26585 * element information item has no character or element
26586 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026588 ACTIVATE_PARENT_ELEM
26589 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26590 VERROR(ret, NULL,
26591 "Element content is not allowed, "
26592 "because the content type is empty");
26593 ACTIVATE_ELEM
26594 goto unexpected_elem;
26595 break;
26596
26597 case XML_SCHEMA_CONTENT_MIXED:
26598 case XML_SCHEMA_CONTENT_ELEMENTS: {
26599 xmlRegExecCtxtPtr regexCtxt;
26600 xmlChar *values[10];
26601 int terminal, nbval = 10, nbneg;
26602
26603 /* VAL TODO: Optimized "anyType" validation.*/
26604
26605 if (ptype->contModel == NULL) {
26606 VERROR_INT("xmlSchemaValidateChildElem",
26607 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026608 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026610 /*
26611 * Safety belf for evaluation if the cont. model was already
26612 * examined to be invalid.
26613 */
26614 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26615 VERROR_INT("xmlSchemaValidateChildElem",
26616 "validating elem, but elem content is already invalid");
26617 return (-1);
26618 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026619
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026620 regexCtxt = pielem->regexCtxt;
26621 if (regexCtxt == NULL) {
26622 /*
26623 * Create the regex context.
26624 */
26625 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26626 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26627 vctxt);
26628 if (regexCtxt == NULL) {
26629 VERROR_INT("xmlSchemaValidateChildElem",
26630 "failed to create a regex context");
26631 return (-1);
26632 }
26633 pielem->regexCtxt = regexCtxt;
26634#ifdef DEBUG_AUTOMATA
26635 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26636 pielem->localName);
26637#endif
26638 }
26639
26640 /*
26641 * SPEC (2.4) "If the {content type} is element-only or mixed,
26642 * then the sequence of the element information item's
26643 * element information item [children], if any, taken in
Jan Pokorný761c9e92013-11-29 23:26:27 +010026644 * order, is `valid` with respect to the {content type}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026645 * particle, as defined in Element Sequence Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026646 * (Particle) ($3.9.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026647 */
26648 ret = xmlRegExecPushString2(regexCtxt,
26649 vctxt->inode->localName,
26650 vctxt->inode->nsName,
26651 vctxt->inode);
26652#ifdef DEBUG_AUTOMATA
26653 if (ret < 0)
26654 xmlGenericError(xmlGenericErrorContext,
26655 "AUTOMATON push ERROR for '%s' on '%s'\n",
26656 vctxt->inode->localName, pielem->localName);
26657 else
26658 xmlGenericError(xmlGenericErrorContext,
26659 "AUTOMATON push OK for '%s' on '%s'\n",
26660 vctxt->inode->localName, pielem->localName);
26661#endif
26662 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26663 VERROR_INT("xmlSchemaValidateChildElem",
26664 "calling xmlRegExecPushString2()");
26665 return (-1);
26666 }
26667 if (ret < 0) {
26668 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26669 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026670 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026671 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26672 "This element is not expected",
26673 nbval, nbneg, values);
26674 ret = vctxt->err;
26675 goto unexpected_elem;
26676 } else
26677 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026678 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026679 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026680 case XML_SCHEMA_CONTENT_SIMPLE:
26681 case XML_SCHEMA_CONTENT_BASIC:
26682 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026683 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026684 /*
26685 * SPEC (cvc-complex-type) (2.2)
26686 * "If the {content type} is a simple type definition, then
26687 * the element information item has no element information
26688 * item [children], ..."
26689 */
26690 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26691 VERROR(ret, NULL, "Element content is not allowed, "
26692 "because the content type is a simple type definition");
26693 } else {
26694 /*
26695 * SPEC (cvc-type) (3.1.2) "The element information item must
26696 * have no element information item [children]."
26697 */
26698 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26699 VERROR(ret, NULL, "Element content is not allowed, "
26700 "because the type definition is simple");
26701 }
26702 ACTIVATE_ELEM
26703 ret = vctxt->err;
26704 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026705 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026706
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026707 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026708 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026709 }
26710 return (ret);
26711unexpected_elem:
26712 /*
26713 * Pop this element and set the skipDepth to skip
26714 * all further content of the parent element.
26715 */
26716 vctxt->skipDepth = vctxt->depth;
26717 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26718 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26719 return (ret);
26720}
26721
26722#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26723#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26724#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26725
26726static int
26727xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26728 int nodeType, const xmlChar *value, int len,
26729 int mode, int *consumed)
26730{
26731 /*
26732 * Unfortunately we have to duplicate the text sometimes.
26733 * OPTIMIZE: Maybe we could skip it, if:
26734 * 1. content type is simple
26735 * 2. whitespace is "collapse"
26736 * 3. it consists of whitespace only
26737 *
26738 * Process character content.
26739 */
26740 if (consumed != NULL)
26741 *consumed = 0;
26742 if (INODE_NILLED(vctxt->inode)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026743 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026744 * SPEC cvc-elt (3.3.4 - 3.2.1)
26745 * "The element information item must have no character or
26746 * element information item [children]."
26747 */
26748 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26749 "Neither character nor element content is allowed "
26750 "because the element is 'nilled'");
26751 return (vctxt->err);
26752 }
26753 /*
26754 * SPEC (2.1) "If the {content type} is empty, then the
26755 * element information item has no character or element
26756 * information item [children]."
26757 */
26758 if (vctxt->inode->typeDef->contentType ==
Daniel Veillarddee23482008-04-11 12:58:43 +000026759 XML_SCHEMA_CONTENT_EMPTY) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026760 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26761 "Character content is not allowed, "
26762 "because the content type is empty");
26763 return (vctxt->err);
26764 }
26765
26766 if (vctxt->inode->typeDef->contentType ==
26767 XML_SCHEMA_CONTENT_ELEMENTS) {
26768 if ((nodeType != XML_TEXT_NODE) ||
26769 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026770 /*
26771 * SPEC cvc-complex-type (2.3)
26772 * "If the {content type} is element-only, then the
26773 * element information item has no character information
26774 * item [children] other than those whose [character
26775 * code] is defined as a white space in [XML 1.0 (Second
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026776 * Edition)]."
26777 */
26778 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26779 "Character content other than whitespace is not allowed "
26780 "because the content type is 'element-only'");
26781 return (vctxt->err);
26782 }
26783 return (0);
26784 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026785
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026786 if ((value == NULL) || (value[0] == 0))
26787 return (0);
26788 /*
26789 * Save the value.
26790 * NOTE that even if the content type is *mixed*, we need the
26791 * *initial value* for default/fixed value constraints.
26792 */
26793 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26794 ((vctxt->inode->decl == NULL) ||
26795 (vctxt->inode->decl->value == NULL)))
26796 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000026797
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026798 if (vctxt->inode->value == NULL) {
26799 /*
26800 * Set the value.
26801 */
26802 switch (mode) {
26803 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26804 /*
26805 * When working on a tree.
26806 */
26807 vctxt->inode->value = value;
26808 break;
26809 case XML_SCHEMA_PUSH_TEXT_CREATED:
26810 /*
26811 * When working with the reader.
26812 * The value will be freed by the element info.
26813 */
26814 vctxt->inode->value = value;
26815 if (consumed != NULL)
26816 *consumed = 1;
26817 vctxt->inode->flags |=
26818 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26819 break;
26820 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26821 /*
26822 * When working with SAX.
26823 * The value will be freed by the element info.
26824 */
26825 if (len != -1)
26826 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26827 else
26828 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26829 vctxt->inode->flags |=
26830 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26831 break;
26832 default:
26833 break;
26834 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000026835 } else {
26836 if (len < 0)
26837 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026838 /*
26839 * Concat the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000026840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026841 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000026842 vctxt->inode->value = BAD_CAST xmlStrncat(
26843 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026844 } else {
26845 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026846 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026847 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26848 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026850
26851 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000026852}
26853
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026854static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026855xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000026856{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026857 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000026858
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026859 if ((vctxt->skipDepth != -1) &&
26860 (vctxt->depth >= vctxt->skipDepth)) {
26861 VERROR_INT("xmlSchemaValidateElem",
26862 "in skip-state");
26863 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026865 if (vctxt->xsiAssemble) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026866 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026867 * We will stop validation if there was an error during
26868 * dynamic schema construction.
26869 * Note that we simply set @skipDepth to 0, this could
26870 * mean that a streaming document via SAX would be
26871 * still read to the end but it won't be validated any more.
26872 * TODO: If we are sure how to stop the validation at once
26873 * for all input scenarios, then this should be changed to
26874 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026875 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000026876 ret = xmlSchemaAssembleByXSI(vctxt);
26877 if (ret != 0) {
26878 if (ret == -1)
26879 goto internal_error;
26880 vctxt->skipDepth = 0;
26881 return(ret);
26882 }
Jim Panettac84e8632010-11-03 21:05:18 +010026883 /*
26884 * Augment the IDC definitions for the main schema and all imported ones
26885 * NOTE: main schema is the first in the imported list
26886 */
26887 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026888 }
26889 if (vctxt->depth > 0) {
26890 /*
26891 * Validate this element against the content model
26892 * of the parent.
26893 */
26894 ret = xmlSchemaValidateChildElem(vctxt);
26895 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026896 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026897 VERROR_INT("xmlSchemaValidateElem",
26898 "calling xmlSchemaStreamValidateChildElement()");
26899 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026900 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026901 goto exit;
26902 }
26903 if (vctxt->depth == vctxt->skipDepth)
26904 goto exit;
26905 if ((vctxt->inode->decl == NULL) &&
26906 (vctxt->inode->typeDef == NULL)) {
26907 VERROR_INT("xmlSchemaValidateElem",
26908 "the child element was valid but neither the "
26909 "declaration nor the type was set");
26910 goto internal_error;
26911 }
26912 } else {
26913 /*
26914 * Get the declaration of the validation root.
26915 */
26916 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26917 vctxt->inode->localName,
26918 vctxt->inode->nsName);
26919 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026920 ret = XML_SCHEMAV_CVC_ELT_1;
26921 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026922 "No matching global declaration available "
26923 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026924 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026925 }
26926 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000026927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026928 if (vctxt->inode->decl == NULL)
26929 goto type_validation;
26930
26931 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26932 int skip;
26933 /*
26934 * Wildcards.
26935 */
26936 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26937 if (ret != 0) {
26938 if (ret < 0) {
26939 VERROR_INT("xmlSchemaValidateElem",
26940 "calling xmlSchemaValidateElemWildcard()");
26941 goto internal_error;
26942 }
26943 goto exit;
26944 }
26945 if (skip) {
26946 vctxt->skipDepth = vctxt->depth;
26947 goto exit;
26948 }
26949 /*
26950 * The declaration might be set by the wildcard validation,
26951 * when the processContents is "lax" or "strict".
26952 */
26953 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26954 /*
26955 * Clear the "decl" field to not confuse further processing.
26956 */
26957 vctxt->inode->decl = NULL;
26958 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026959 }
Daniel Veillard4255d502002-04-16 15:50:10 +000026960 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026961 /*
26962 * Validate against the declaration.
26963 */
26964 ret = xmlSchemaValidateElemDecl(vctxt);
26965 if (ret != 0) {
26966 if (ret < 0) {
26967 VERROR_INT("xmlSchemaValidateElem",
26968 "calling xmlSchemaValidateElemDecl()");
26969 goto internal_error;
26970 }
26971 goto exit;
26972 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026973 /*
26974 * Validate against the type definition.
26975 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026976type_validation:
26977
26978 if (vctxt->inode->typeDef == NULL) {
26979 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26980 ret = XML_SCHEMAV_CVC_TYPE_1;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080026981 VERROR(ret, NULL,
26982 "The type definition is absent");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026983 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000026984 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026985 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26986 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26987 ret = XML_SCHEMAV_CVC_TYPE_2;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080026988 VERROR(ret, NULL,
26989 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026990 goto exit;
26991 }
26992 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000026993 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026994 * during validation against the declaration. This must be done
26995 * _before_ attribute validation.
26996 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026997 if (vctxt->xpathStates != NULL) {
26998 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026999 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027000 if (ret == -1) {
27001 VERROR_INT("xmlSchemaValidateElem",
27002 "calling xmlSchemaXPathEvaluate()");
27003 goto internal_error;
27004 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027005 }
27006 /*
27007 * Validate attributes.
27008 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027009 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027010 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027011 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027012
27013 ret = xmlSchemaVAttributesComplex(vctxt);
27014 }
27015 } else if (vctxt->nbAttrInfos != 0) {
27016
27017 ret = xmlSchemaVAttributesSimple(vctxt);
27018 }
27019 /*
27020 * Clear registered attributes.
27021 */
27022 if (vctxt->nbAttrInfos != 0)
27023 xmlSchemaClearAttrInfos(vctxt);
27024 if (ret == -1) {
27025 VERROR_INT("xmlSchemaValidateElem",
27026 "calling attributes validation");
27027 goto internal_error;
27028 }
27029 /*
27030 * Don't return an error if attributes are invalid on purpose.
27031 */
27032 ret = 0;
27033
27034exit:
27035 if (ret != 0)
27036 vctxt->skipDepth = vctxt->depth;
27037 return (ret);
27038internal_error:
27039 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027040}
27041
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027042#ifdef XML_SCHEMA_READER_ENABLED
27043static int
27044xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027045{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027046 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27047 int depth, nodeType, ret = 0, consumed;
27048 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027049
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027050 vctxt->depth = -1;
27051 ret = xmlTextReaderRead(vctxt->reader);
27052 /*
27053 * Move to the document element.
27054 */
27055 while (ret == 1) {
27056 nodeType = xmlTextReaderNodeType(vctxt->reader);
27057 if (nodeType == XML_ELEMENT_NODE)
27058 goto root_found;
27059 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027061 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027062
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027063root_found:
27064
27065 do {
27066 depth = xmlTextReaderDepth(vctxt->reader);
27067 nodeType = xmlTextReaderNodeType(vctxt->reader);
27068
27069 if (nodeType == XML_ELEMENT_NODE) {
Daniel Veillarddee23482008-04-11 12:58:43 +000027070
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027071 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027072 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27073 VERROR_INT("xmlSchemaVReaderWalk",
27074 "calling xmlSchemaValidatorPushElem()");
27075 goto internal_error;
27076 }
27077 ielem = vctxt->inode;
27078 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27079 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27080 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27081 /*
27082 * Is the element empty?
27083 */
27084 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27085 if (ret == -1) {
27086 VERROR_INT("xmlSchemaVReaderWalk",
27087 "calling xmlTextReaderIsEmptyElement()");
27088 goto internal_error;
27089 }
27090 if (ret) {
27091 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27092 }
27093 /*
27094 * Register attributes.
27095 */
27096 vctxt->nbAttrInfos = 0;
27097 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27098 if (ret == -1) {
27099 VERROR_INT("xmlSchemaVReaderWalk",
27100 "calling xmlTextReaderMoveToFirstAttribute()");
27101 goto internal_error;
27102 }
27103 if (ret == 1) {
27104 do {
27105 /*
27106 * VAL TODO: How do we know that the reader works on a
27107 * node tree, to be able to pass a node here?
27108 */
27109 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27110 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27111 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27112 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27113
27114 VERROR_INT("xmlSchemaVReaderWalk",
27115 "calling xmlSchemaValidatorPushAttribute()");
27116 goto internal_error;
27117 }
27118 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27119 if (ret == -1) {
27120 VERROR_INT("xmlSchemaVReaderWalk",
27121 "calling xmlTextReaderMoveToFirstAttribute()");
27122 goto internal_error;
27123 }
27124 } while (ret == 1);
27125 /*
27126 * Back to element position.
27127 */
27128 ret = xmlTextReaderMoveToElement(vctxt->reader);
27129 if (ret == -1) {
27130 VERROR_INT("xmlSchemaVReaderWalk",
27131 "calling xmlTextReaderMoveToElement()");
27132 goto internal_error;
27133 }
27134 }
27135 /*
27136 * Validate the element.
27137 */
27138 ret= xmlSchemaValidateElem(vctxt);
27139 if (ret != 0) {
27140 if (ret == -1) {
27141 VERROR_INT("xmlSchemaVReaderWalk",
27142 "calling xmlSchemaValidateElem()");
27143 goto internal_error;
27144 }
27145 goto exit;
27146 }
27147 if (vctxt->depth == vctxt->skipDepth) {
27148 int curDepth;
27149 /*
27150 * Skip all content.
27151 */
27152 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27153 ret = xmlTextReaderRead(vctxt->reader);
27154 curDepth = xmlTextReaderDepth(vctxt->reader);
27155 while ((ret == 1) && (curDepth != depth)) {
27156 ret = xmlTextReaderRead(vctxt->reader);
27157 curDepth = xmlTextReaderDepth(vctxt->reader);
27158 }
27159 if (ret < 0) {
27160 /*
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020027161 * VAL TODO: A reader error occurred; what to do here?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027162 */
27163 ret = 1;
27164 goto exit;
27165 }
27166 }
27167 goto leave_elem;
27168 }
27169 /*
27170 * READER VAL TODO: Is an END_ELEM really never called
27171 * if the elem is empty?
27172 */
27173 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27174 goto leave_elem;
27175 } else if (nodeType == END_ELEM) {
27176 /*
27177 * Process END of element.
27178 */
27179leave_elem:
27180 ret = xmlSchemaValidatorPopElem(vctxt);
27181 if (ret != 0) {
27182 if (ret < 0) {
27183 VERROR_INT("xmlSchemaVReaderWalk",
27184 "calling xmlSchemaValidatorPopElem()");
27185 goto internal_error;
27186 }
27187 goto exit;
27188 }
27189 if (vctxt->depth >= 0)
27190 ielem = vctxt->inode;
27191 else
27192 ielem = NULL;
27193 } else if ((nodeType == XML_TEXT_NODE) ||
27194 (nodeType == XML_CDATA_SECTION_NODE) ||
27195 (nodeType == WHTSP) ||
27196 (nodeType == SIGN_WHTSP)) {
27197 /*
27198 * Process character content.
27199 */
27200 xmlChar *value;
27201
27202 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27203 nodeType = XML_TEXT_NODE;
27204
27205 value = xmlTextReaderValue(vctxt->reader);
27206 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27207 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27208 if (! consumed)
27209 xmlFree(value);
27210 if (ret == -1) {
27211 VERROR_INT("xmlSchemaVReaderWalk",
27212 "calling xmlSchemaVPushText()");
27213 goto internal_error;
27214 }
27215 } else if ((nodeType == XML_ENTITY_NODE) ||
27216 (nodeType == XML_ENTITY_REF_NODE)) {
27217 /*
27218 * VAL TODO: What to do with entities?
27219 */
27220 TODO
27221 }
27222 /*
27223 * Read next node.
27224 */
27225 ret = xmlTextReaderRead(vctxt->reader);
27226 } while (ret == 1);
27227
27228exit:
27229 return (ret);
27230internal_error:
27231 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027232}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027233#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000027234
27235/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027236 * *
27237 * SAX validation handlers *
27238 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027239 ************************************************************************/
27240
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027241/*
27242* Process text content.
27243*/
27244static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027245xmlSchemaSAXHandleText(void *ctx,
27246 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027247 int len)
27248{
27249 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27250
27251 if (vctxt->depth < 0)
27252 return;
27253 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27254 return;
27255 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27256 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27257 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27258 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27259 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27260 "calling xmlSchemaVPushText()");
27261 vctxt->err = -1;
27262 xmlStopParser(vctxt->parserCtxt);
27263 }
27264}
27265
27266/*
27267* Process CDATA content.
27268*/
27269static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027270xmlSchemaSAXHandleCDataSection(void *ctx,
27271 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027272 int len)
Daniel Veillarddee23482008-04-11 12:58:43 +000027273{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027274 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27275
27276 if (vctxt->depth < 0)
27277 return;
27278 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27279 return;
27280 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27281 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27282 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27283 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27284 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27285 "calling xmlSchemaVPushText()");
27286 vctxt->err = -1;
27287 xmlStopParser(vctxt->parserCtxt);
27288 }
27289}
27290
27291static void
27292xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27293 const xmlChar * name ATTRIBUTE_UNUSED)
27294{
27295 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27296
27297 if (vctxt->depth < 0)
27298 return;
27299 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27300 return;
27301 /* SAX VAL TODO: What to do here? */
27302 TODO
27303}
27304
27305static void
27306xmlSchemaSAXHandleStartElementNs(void *ctx,
Daniel Veillarddee23482008-04-11 12:58:43 +000027307 const xmlChar * localname,
27308 const xmlChar * prefix ATTRIBUTE_UNUSED,
27309 const xmlChar * URI,
27310 int nb_namespaces,
27311 const xmlChar ** namespaces,
27312 int nb_attributes,
27313 int nb_defaulted ATTRIBUTE_UNUSED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027314 const xmlChar ** attributes)
Daniel Veillarddee23482008-04-11 12:58:43 +000027315{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027316 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27317 int ret;
27318 xmlSchemaNodeInfoPtr ielem;
27319 int i, j;
Daniel Veillarddee23482008-04-11 12:58:43 +000027320
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027321 /*
27322 * SAX VAL TODO: What to do with nb_defaulted?
27323 */
27324 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027325 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027326 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027327 vctxt->depth++;
27328 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027329 return;
27330 /*
27331 * Push the element.
27332 */
27333 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27334 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27335 "calling xmlSchemaValidatorPushElem()");
27336 goto internal_error;
27337 }
27338 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027339 /*
27340 * TODO: Is this OK?
27341 */
27342 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027343 ielem->localName = localname;
27344 ielem->nsName = URI;
27345 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27346 /*
27347 * Register namespaces on the elem info.
Daniel Veillarddee23482008-04-11 12:58:43 +000027348 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027349 if (nb_namespaces != 0) {
27350 /*
27351 * Although the parser builds its own namespace list,
27352 * we have no access to it, so we'll use an own one.
27353 */
Daniel Veillarddee23482008-04-11 12:58:43 +000027354 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027355 /*
27356 * Store prefix and namespace name.
Daniel Veillarddee23482008-04-11 12:58:43 +000027357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027358 if (ielem->nsBindings == NULL) {
27359 ielem->nsBindings =
27360 (const xmlChar **) xmlMalloc(10 *
27361 sizeof(const xmlChar *));
27362 if (ielem->nsBindings == NULL) {
27363 xmlSchemaVErrMemory(vctxt,
27364 "allocating namespace bindings for SAX validation",
27365 NULL);
27366 goto internal_error;
27367 }
27368 ielem->nbNsBindings = 0;
27369 ielem->sizeNsBindings = 5;
27370 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27371 ielem->sizeNsBindings *= 2;
27372 ielem->nsBindings =
27373 (const xmlChar **) xmlRealloc(
27374 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027375 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027376 if (ielem->nsBindings == NULL) {
27377 xmlSchemaVErrMemory(vctxt,
27378 "re-allocating namespace bindings for SAX validation",
27379 NULL);
27380 goto internal_error;
27381 }
27382 }
27383
27384 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27385 if (namespaces[j+1][0] == 0) {
27386 /*
27387 * Handle xmlns="".
27388 */
27389 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27390 } else
27391 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27392 namespaces[j+1];
Daniel Veillarddee23482008-04-11 12:58:43 +000027393 ielem->nbNsBindings++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027394 }
27395 }
27396 /*
27397 * Register attributes.
27398 * SAX VAL TODO: We are not adding namespace declaration
27399 * attributes yet.
27400 */
27401 if (nb_attributes != 0) {
Alex Henrie31696022016-05-26 17:38:35 -060027402 int valueLen, k, l;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027403 xmlChar *value;
27404
27405 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27406 /*
Alex Henrief6599c52016-05-02 22:29:59 -060027407 * Duplicate the value, changing any &#38; to a literal ampersand.
27408 *
27409 * libxml2 differs from normal SAX here in that it escapes all ampersands
27410 * as &#38; instead of delivering the raw converted string. Changing the
27411 * behavior at this point would break applications that use this API, so
Alex Henrie31696022016-05-26 17:38:35 -060027412 * we are forced to work around it.
Daniel Veillarddee23482008-04-11 12:58:43 +000027413 */
Alex Henrie31696022016-05-26 17:38:35 -060027414 valueLen = attributes[j+4] - attributes[j+3];
27415 value = xmlMallocAtomic(valueLen + 1);
27416 if (value == NULL) {
27417 xmlSchemaVErrMemory(vctxt,
27418 "allocating string for decoded attribute",
27419 NULL);
27420 goto internal_error;
27421 }
27422 for (k = 0, l = 0; k < valueLen; l++) {
27423 if (k < valueLen - 4 &&
27424 attributes[j+3][k+0] == '&' &&
27425 attributes[j+3][k+1] == '#' &&
27426 attributes[j+3][k+2] == '3' &&
27427 attributes[j+3][k+3] == '8' &&
27428 attributes[j+3][k+4] == ';') {
27429 value[l] = '&';
27430 k += 5;
27431 } else {
27432 value[l] = attributes[j+3][k];
27433 k++;
27434 }
27435 }
27436 value[l] = '\0';
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027437 /*
27438 * TODO: Set the node line.
27439 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027440 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027441 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027442 value, 1);
27443 if (ret == -1) {
27444 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27445 "calling xmlSchemaValidatorPushAttribute()");
27446 goto internal_error;
27447 }
27448 }
27449 }
27450 /*
27451 * Validate the element.
27452 */
27453 ret = xmlSchemaValidateElem(vctxt);
27454 if (ret != 0) {
27455 if (ret == -1) {
27456 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27457 "calling xmlSchemaValidateElem()");
27458 goto internal_error;
27459 }
27460 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000027461 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027462
27463exit:
27464 return;
27465internal_error:
27466 vctxt->err = -1;
27467 xmlStopParser(vctxt->parserCtxt);
27468 return;
27469}
27470
27471static void
27472xmlSchemaSAXHandleEndElementNs(void *ctx,
27473 const xmlChar * localname ATTRIBUTE_UNUSED,
27474 const xmlChar * prefix ATTRIBUTE_UNUSED,
27475 const xmlChar * URI ATTRIBUTE_UNUSED)
27476{
27477 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27478 int res;
27479
27480 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027481 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027482 */
27483 if (vctxt->skipDepth != -1) {
27484 if (vctxt->depth > vctxt->skipDepth) {
27485 vctxt->depth--;
27486 return;
27487 } else
27488 vctxt->skipDepth = -1;
27489 }
27490 /*
27491 * SAX VAL TODO: Just a temporary check.
27492 */
27493 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27494 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27495 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27496 "elem pop mismatch");
27497 }
27498 res = xmlSchemaValidatorPopElem(vctxt);
27499 if (res != 0) {
27500 if (res < 0) {
27501 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27502 "calling xmlSchemaValidatorPopElem()");
27503 goto internal_error;
27504 }
27505 goto exit;
27506 }
27507exit:
27508 return;
27509internal_error:
27510 vctxt->err = -1;
27511 xmlStopParser(vctxt->parserCtxt);
27512 return;
27513}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027514
Daniel Veillard4255d502002-04-16 15:50:10 +000027515/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027516 * *
27517 * Validation interfaces *
27518 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027519 ************************************************************************/
27520
27521/**
27522 * xmlSchemaNewValidCtxt:
27523 * @schema: a precompiled XML Schemas
27524 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027525 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027526 *
27527 * Returns the validation context or NULL in case of error
27528 */
27529xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027530xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27531{
Daniel Veillard4255d502002-04-16 15:50:10 +000027532 xmlSchemaValidCtxtPtr ret;
27533
27534 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27535 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027536 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027537 return (NULL);
27538 }
27539 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027540 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027541 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027542 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027543 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027544 return (ret);
27545}
27546
27547/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027548 * xmlSchemaValidateSetFilename:
Daniel Veillardef4526a2012-08-15 09:14:31 +080027549 * @vctxt: the schema validation context
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027550 * @filename: the file name
27551 *
27552 * Workaround to provide file error reporting information when this is
27553 * not provided by current APIs
27554 */
27555void
27556xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27557 if (vctxt == NULL)
27558 return;
27559 if (vctxt->filename != NULL)
27560 xmlFree(vctxt->filename);
27561 if (filename != NULL)
27562 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27563 else
27564 vctxt->filename = NULL;
27565}
27566
27567/**
27568 * xmlSchemaClearValidCtxt:
27569 * @vctxt: the schema validation context
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027570 *
27571 * Free the resources associated to the schema validation context;
27572 * leaves some fields alive intended for reuse of the context.
27573 */
27574static void
27575xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27576{
27577 if (vctxt == NULL)
27578 return;
27579
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027580 /*
27581 * TODO: Should we clear the flags?
27582 * Might be problematic if one reuses the context
27583 * and assumes that the options remain the same.
27584 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027585 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027586 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027587 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027588#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027589 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027590#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000027591 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027592
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027593 if (vctxt->value != NULL) {
27594 xmlSchemaFreeValue(vctxt->value);
27595 vctxt->value = NULL;
27596 }
27597 /*
27598 * Augmented IDC information.
27599 */
27600 if (vctxt->aidcs != NULL) {
27601 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27602 do {
27603 next = cur->next;
27604 xmlFree(cur);
27605 cur = next;
27606 } while (cur != NULL);
27607 vctxt->aidcs = NULL;
27608 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027609 if (vctxt->idcMatcherCache != NULL) {
27610 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27611
27612 while (matcher) {
27613 tmp = matcher;
27614 matcher = matcher->nextCached;
27615 xmlSchemaIDCFreeMatcherList(tmp);
27616 }
27617 vctxt->idcMatcherCache = NULL;
27618 }
27619
27620
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027621 if (vctxt->idcNodes != NULL) {
27622 int i;
27623 xmlSchemaPSVIIDCNodePtr item;
27624
27625 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027626 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027627 xmlFree(item->keys);
27628 xmlFree(item);
27629 }
27630 xmlFree(vctxt->idcNodes);
27631 vctxt->idcNodes = NULL;
Daniel Veillard1131e112006-08-07 11:02:54 +000027632 vctxt->nbIdcNodes = 0;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027633 vctxt->sizeIdcNodes = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027634 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027635 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027636 * Note that we won't delete the XPath state pool here.
27637 */
27638 if (vctxt->xpathStates != NULL) {
27639 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27640 vctxt->xpathStates = NULL;
27641 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027642 /*
27643 * Attribute info.
27644 */
27645 if (vctxt->nbAttrInfos != 0) {
27646 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027648 /*
27649 * Element info.
27650 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027651 if (vctxt->elemInfos != NULL) {
27652 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027653 xmlSchemaNodeInfoPtr ei;
27654
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027655 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027656 ei = vctxt->elemInfos[i];
27657 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027658 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027659 xmlSchemaClearElemInfo(vctxt, ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027660 }
Daniel Veillarddee23482008-04-11 12:58:43 +000027661 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027662 xmlSchemaItemListClear(vctxt->nodeQNames);
27663 /* Recreate the dict. */
27664 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027665 /*
27666 * TODO: Is is save to recreate it? Do we have a scenario
27667 * where the user provides the dict?
27668 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027669 vctxt->dict = xmlDictCreate();
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027670
27671 if (vctxt->filename != NULL) {
27672 xmlFree(vctxt->filename);
27673 vctxt->filename = NULL;
27674 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027675}
27676
27677/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027678 * xmlSchemaFreeValidCtxt:
27679 * @ctxt: the schema validation context
27680 *
27681 * Free the resources associated to the schema validation context
27682 */
27683void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027684xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27685{
Daniel Veillard4255d502002-04-16 15:50:10 +000027686 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027687 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027688 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027689 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027690 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027691 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027692 if (ctxt->idcNodes != NULL) {
27693 int i;
27694 xmlSchemaPSVIIDCNodePtr item;
27695
27696 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027697 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027698 xmlFree(item->keys);
27699 xmlFree(item);
27700 }
27701 xmlFree(ctxt->idcNodes);
27702 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027703 if (ctxt->idcKeys != NULL) {
27704 int i;
27705 for (i = 0; i < ctxt->nbIdcKeys; i++)
27706 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27707 xmlFree(ctxt->idcKeys);
27708 }
27709
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027710 if (ctxt->xpathStates != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027711 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027712 ctxt->xpathStates = NULL;
27713 }
27714 if (ctxt->xpathStatePool != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027715 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027716 ctxt->xpathStatePool = NULL;
27717 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027718
27719 /*
27720 * Augmented IDC information.
27721 */
27722 if (ctxt->aidcs != NULL) {
27723 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27724 do {
27725 next = cur->next;
27726 xmlFree(cur);
27727 cur = next;
27728 } while (cur != NULL);
27729 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027730 if (ctxt->attrInfos != NULL) {
27731 int i;
27732 xmlSchemaAttrInfoPtr attr;
27733
27734 /* Just a paranoid call to the cleanup. */
27735 if (ctxt->nbAttrInfos != 0)
27736 xmlSchemaClearAttrInfos(ctxt);
27737 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27738 attr = ctxt->attrInfos[i];
27739 xmlFree(attr);
27740 }
27741 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027742 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027743 if (ctxt->elemInfos != NULL) {
27744 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027745 xmlSchemaNodeInfoPtr ei;
27746
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027747 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027748 ei = ctxt->elemInfos[i];
27749 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027750 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027751 xmlSchemaClearElemInfo(ctxt, ei);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027752 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027753 }
27754 xmlFree(ctxt->elemInfos);
27755 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027756 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027757 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027758 if (ctxt->dict != NULL)
27759 xmlDictFree(ctxt->dict);
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027760 if (ctxt->filename != NULL)
27761 xmlFree(ctxt->filename);
Daniel Veillard4255d502002-04-16 15:50:10 +000027762 xmlFree(ctxt);
27763}
27764
27765/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027766 * xmlSchemaIsValid:
27767 * @ctxt: the schema validation context
27768 *
27769 * Check if any error was detected during validation.
Daniel Veillarddee23482008-04-11 12:58:43 +000027770 *
Daniel Veillardf10ae122005-07-10 19:03:16 +000027771 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27772 * of internal error.
27773 */
27774int
27775xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27776{
27777 if (ctxt == NULL)
27778 return(-1);
27779 return(ctxt->err == 0);
27780}
27781
27782/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027783 * xmlSchemaSetValidErrors:
27784 * @ctxt: a schema validation context
27785 * @err: the error function
27786 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000027787 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000027788 *
William M. Brack2f2a6632004-08-20 23:09:47 +000027789 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000027790 */
27791void
27792xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027793 xmlSchemaValidityErrorFunc err,
27794 xmlSchemaValidityWarningFunc warn, void *ctx)
27795{
Daniel Veillard4255d502002-04-16 15:50:10 +000027796 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027797 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000027798 ctxt->error = err;
27799 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027800 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027801 if (ctxt->pctxt != NULL)
27802 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000027803}
27804
27805/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027806 * xmlSchemaSetValidStructuredErrors:
27807 * @ctxt: a schema validation context
27808 * @serror: the structured error function
27809 * @ctx: the functions context
27810 *
27811 * Set the structured error callback
27812 */
27813void
27814xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027815 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027816{
27817 if (ctxt == NULL)
27818 return;
27819 ctxt->serror = serror;
27820 ctxt->error = NULL;
27821 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027822 ctxt->errCtxt = ctx;
27823 if (ctxt->pctxt != NULL)
27824 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000027825}
27826
27827/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000027828 * xmlSchemaGetValidErrors:
Daniel Veillarddee23482008-04-11 12:58:43 +000027829 * @ctxt: a XML-Schema validation context
Daniel Veillard259f0df2004-08-18 09:13:18 +000027830 * @err: the error function result
27831 * @warn: the warning function result
27832 * @ctx: the functions context result
27833 *
27834 * Get the error and warning callback informations
27835 *
27836 * Returns -1 in case of error and 0 otherwise
27837 */
27838int
27839xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027840 xmlSchemaValidityErrorFunc * err,
27841 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000027842{
27843 if (ctxt == NULL)
27844 return (-1);
27845 if (err != NULL)
27846 *err = ctxt->error;
27847 if (warn != NULL)
27848 *warn = ctxt->warning;
27849 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000027850 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000027851 return (0);
27852}
27853
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027854
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027855/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027856 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027857 * @ctxt: a schema validation context
27858 * @options: a combination of xmlSchemaValidOption
27859 *
27860 * Sets the options to be used during the validation.
27861 *
27862 * Returns 0 in case of success, -1 in case of an
27863 * API error.
27864 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027865int
27866xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27867 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027868
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027869{
27870 int i;
27871
27872 if (ctxt == NULL)
27873 return (-1);
27874 /*
27875 * WARNING: Change the start value if adding to the
27876 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027877 * TODO: Is there an other, more easy to maintain,
27878 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027879 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027880 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027881 if (options & 1<<i)
27882 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027883 }
27884 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027885 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027886}
27887
27888/**
Daniel Veillard6927b102004-10-27 17:29:04 +000027889 * xmlSchemaValidCtxtGetOptions:
Daniel Veillarddee23482008-04-11 12:58:43 +000027890 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027891 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027892 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027893 *
William M. Brack21e4ef22005-01-02 09:53:13 +000027894 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027895 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027896int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027897xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027898
27899{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027900 if (ctxt == NULL)
27901 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027902 else
27903 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027904}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027905
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027906static int
27907xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27908{
27909 xmlAttrPtr attr;
27910 int ret = 0;
27911 xmlSchemaNodeInfoPtr ielem = NULL;
27912 xmlNodePtr node, valRoot;
27913 const xmlChar *nsName;
27914
27915 /* DOC VAL TODO: Move this to the start function. */
Csaba László1f6c42c2013-03-18 15:30:00 +080027916 if (vctxt->validationRoot != NULL)
27917 valRoot = vctxt->validationRoot;
27918 else
27919 valRoot = xmlDocGetRootElement(vctxt->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027920 if (valRoot == NULL) {
27921 /* VAL TODO: Error code? */
27922 VERROR(1, NULL, "The document has no document element");
27923 return (1);
27924 }
27925 vctxt->depth = -1;
27926 vctxt->validationRoot = valRoot;
27927 node = valRoot;
27928 while (node != NULL) {
27929 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27930 goto next_sibling;
27931 if (node->type == XML_ELEMENT_NODE) {
27932
27933 /*
27934 * Init the node-info.
27935 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027936 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027937 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27938 goto internal_error;
27939 ielem = vctxt->inode;
27940 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027941 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027942 ielem->localName = node->name;
27943 if (node->ns != NULL)
27944 ielem->nsName = node->ns->href;
27945 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27946 /*
27947 * Register attributes.
27948 * DOC VAL TODO: We do not register namespace declaration
27949 * attributes yet.
27950 */
27951 vctxt->nbAttrInfos = 0;
27952 if (node->properties != NULL) {
27953 attr = node->properties;
27954 do {
27955 if (attr->ns != NULL)
27956 nsName = attr->ns->href;
27957 else
27958 nsName = NULL;
27959 ret = xmlSchemaValidatorPushAttribute(vctxt,
27960 (xmlNodePtr) attr,
Daniel Veillarddee23482008-04-11 12:58:43 +000027961 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027962 * Note that we give it the line number of the
27963 * parent element.
27964 */
27965 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027966 attr->name, nsName, 0,
27967 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27968 if (ret == -1) {
27969 VERROR_INT("xmlSchemaDocWalk",
27970 "calling xmlSchemaValidatorPushAttribute()");
27971 goto internal_error;
27972 }
27973 attr = attr->next;
27974 } while (attr);
27975 }
27976 /*
27977 * Validate the element.
27978 */
27979 ret = xmlSchemaValidateElem(vctxt);
27980 if (ret != 0) {
27981 if (ret == -1) {
27982 VERROR_INT("xmlSchemaDocWalk",
27983 "calling xmlSchemaValidateElem()");
27984 goto internal_error;
27985 }
27986 /*
27987 * Don't stop validation; just skip the content
27988 * of this element.
27989 */
27990 goto leave_node;
27991 }
27992 if ((vctxt->skipDepth != -1) &&
27993 (vctxt->depth >= vctxt->skipDepth))
27994 goto leave_node;
27995 } else if ((node->type == XML_TEXT_NODE) ||
27996 (node->type == XML_CDATA_SECTION_NODE)) {
27997 /*
27998 * Process character content.
27999 */
Daniel Veillard14b56432006-03-09 18:41:40 +000028000 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028001 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28002 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28003 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28004 if (ret < 0) {
28005 VERROR_INT("xmlSchemaVDocWalk",
28006 "calling xmlSchemaVPushText()");
28007 goto internal_error;
28008 }
28009 /*
28010 * DOC VAL TODO: Should we skip further validation of the
28011 * element content here?
28012 */
28013 } else if ((node->type == XML_ENTITY_NODE) ||
28014 (node->type == XML_ENTITY_REF_NODE)) {
28015 /*
28016 * DOC VAL TODO: What to do with entities?
Daniel Veillarddee23482008-04-11 12:58:43 +000028017 */
Kasimier T. Buchcik146a9822006-05-04 17:19:07 +000028018 VERROR_INT("xmlSchemaVDocWalk",
28019 "there is at least one entity reference in the node-tree "
28020 "currently being validated. Processing of entities with "
28021 "this XML Schema processor is not supported (yet). Please "
28022 "substitute entities before validation.");
28023 goto internal_error;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028024 } else {
28025 goto leave_node;
28026 /*
28027 * DOC VAL TODO: XInclude nodes, etc.
28028 */
28029 }
28030 /*
28031 * Walk the doc.
28032 */
28033 if (node->children != NULL) {
28034 node = node->children;
28035 continue;
28036 }
28037leave_node:
28038 if (node->type == XML_ELEMENT_NODE) {
28039 /*
28040 * Leaving the scope of an element.
28041 */
28042 if (node != vctxt->inode->node) {
28043 VERROR_INT("xmlSchemaVDocWalk",
28044 "element position mismatch");
28045 goto internal_error;
28046 }
28047 ret = xmlSchemaValidatorPopElem(vctxt);
28048 if (ret != 0) {
28049 if (ret < 0) {
28050 VERROR_INT("xmlSchemaVDocWalk",
28051 "calling xmlSchemaValidatorPopElem()");
28052 goto internal_error;
28053 }
28054 }
28055 if (node == valRoot)
28056 goto exit;
28057 }
28058next_sibling:
28059 if (node->next != NULL)
28060 node = node->next;
28061 else {
28062 node = node->parent;
28063 goto leave_node;
28064 }
28065 }
28066
28067exit:
28068 return (ret);
28069internal_error:
28070 return (-1);
28071}
28072
28073static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000028074xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028075 /*
28076 * Some initialization.
Daniel Veillarddee23482008-04-11 12:58:43 +000028077 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028078 vctxt->err = 0;
28079 vctxt->nberrors = 0;
28080 vctxt->depth = -1;
28081 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028082 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028083 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000028084#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028085 vctxt->createIDCNodeTables = 1;
28086#else
28087 vctxt->createIDCNodeTables = 0;
28088#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028089 /*
28090 * Create a schema + parser if necessary.
28091 */
28092 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028093 xmlSchemaParserCtxtPtr pctxt;
Daniel Veillarddee23482008-04-11 12:58:43 +000028094
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028095 vctxt->xsiAssemble = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028096 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028097 * If not schema was given then we will create a schema
28098 * dynamically using XSI schema locations.
28099 *
28100 * Create the schema parser context.
28101 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028102 if ((vctxt->pctxt == NULL) &&
28103 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28104 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028105 pctxt = vctxt->pctxt;
28106 pctxt->xsiAssemble = 1;
28107 /*
28108 * Create the schema.
28109 */
28110 vctxt->schema = xmlSchemaNewSchema(pctxt);
28111 if (vctxt->schema == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000028112 return (-1);
28113 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028114 * Create the schema construction context.
28115 */
28116 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28117 if (pctxt->constructor == NULL)
28118 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028119 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028120 /*
28121 * Take ownership of the constructor to be able to free it.
28122 */
28123 pctxt->ownsConstructor = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028124 }
28125 /*
28126 * Augment the IDC definitions for the main schema and all imported ones
Daniel Veillard3888f472007-08-23 09:29:03 +000028127 * NOTE: main schema if the first in the imported list
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028128 */
Daniel Veillard3888f472007-08-23 09:29:03 +000028129 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000028130
Daniel Veillardf10ae122005-07-10 19:03:16 +000028131 return(0);
28132}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028133
Daniel Veillardf10ae122005-07-10 19:03:16 +000028134static void
28135xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028136 if (vctxt->xsiAssemble) {
28137 if (vctxt->schema != NULL) {
28138 xmlSchemaFree(vctxt->schema);
28139 vctxt->schema = NULL;
28140 }
28141 }
28142 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028143}
28144
28145static int
28146xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28147{
28148 int ret = 0;
28149
28150 if (xmlSchemaPreRun(vctxt) < 0)
28151 return(-1);
28152
28153 if (vctxt->doc != NULL) {
28154 /*
28155 * Tree validation.
28156 */
28157 ret = xmlSchemaVDocWalk(vctxt);
28158#ifdef LIBXML_READER_ENABLED
28159 } else if (vctxt->reader != NULL) {
28160 /*
28161 * XML Reader validation.
28162 */
28163#ifdef XML_SCHEMA_READER_ENABLED
28164 ret = xmlSchemaVReaderWalk(vctxt);
28165#endif
28166#endif
28167 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28168 /*
28169 * SAX validation.
28170 */
28171 ret = xmlParseDocument(vctxt->parserCtxt);
28172 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028173 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000028174 "no instance to validate");
28175 ret = -1;
28176 }
28177
28178 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028179 if (ret == 0)
28180 ret = vctxt->err;
28181 return (ret);
28182}
28183
28184/**
28185 * xmlSchemaValidateOneElement:
28186 * @ctxt: a schema validation context
28187 * @elem: an element node
28188 *
28189 * Validate a branch of a tree, starting with the given @elem.
28190 *
28191 * Returns 0 if the element and its subtree is valid, a positive error
28192 * code number otherwise and -1 in case of an internal or API error.
28193 */
28194int
28195xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28196{
28197 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28198 return (-1);
28199
28200 if (ctxt->schema == NULL)
28201 return (-1);
28202
28203 ctxt->doc = elem->doc;
28204 ctxt->node = elem;
28205 ctxt->validationRoot = elem;
28206 return(xmlSchemaVStart(ctxt));
28207}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028208
Daniel Veillard259f0df2004-08-18 09:13:18 +000028209/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028210 * xmlSchemaValidateDoc:
28211 * @ctxt: a schema validation context
28212 * @doc: a parsed document tree
28213 *
28214 * Validate a document tree in memory.
28215 *
28216 * Returns 0 if the document is schemas valid, a positive error code
28217 * number otherwise and -1 in case of internal or API error.
28218 */
28219int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028220xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28221{
Daniel Veillard4255d502002-04-16 15:50:10 +000028222 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028223 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000028224
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028225 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028226 ctxt->node = xmlDocGetRootElement(doc);
28227 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028228 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028229 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28230 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028231 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028232 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028233 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028234 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028235 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000028236}
28237
Daniel Veillardcdc82732005-07-08 15:04:06 +000028238
28239/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080028240 * *
28241 * Function and data for SAX streaming API *
28242 * *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028243 ************************************************************************/
28244typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28245typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28246
28247struct _xmlSchemaSplitSAXData {
28248 xmlSAXHandlerPtr user_sax;
28249 void *user_data;
28250 xmlSchemaValidCtxtPtr ctxt;
28251 xmlSAXHandlerPtr schemas_sax;
28252};
28253
Daniel Veillard971771e2005-07-09 17:32:57 +000028254#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28255
28256struct _xmlSchemaSAXPlug {
28257 unsigned int magic;
28258
28259 /* the original callbacks informations */
28260 xmlSAXHandlerPtr *user_sax_ptr;
28261 xmlSAXHandlerPtr user_sax;
28262 void **user_data_ptr;
28263 void *user_data;
28264
28265 /* the block plugged back and validation informations */
28266 xmlSAXHandler schemas_sax;
28267 xmlSchemaValidCtxtPtr ctxt;
28268};
28269
Daniel Veillardcdc82732005-07-08 15:04:06 +000028270/* All those functions just bounces to the user provided SAX handlers */
28271static void
28272internalSubsetSplit(void *ctx, const xmlChar *name,
28273 const xmlChar *ExternalID, const xmlChar *SystemID)
28274{
Daniel Veillard971771e2005-07-09 17:32:57 +000028275 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028276 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28277 (ctxt->user_sax->internalSubset != NULL))
28278 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28279 SystemID);
28280}
28281
28282static int
28283isStandaloneSplit(void *ctx)
28284{
Daniel Veillard971771e2005-07-09 17:32:57 +000028285 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028286 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28287 (ctxt->user_sax->isStandalone != NULL))
28288 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28289 return(0);
28290}
28291
28292static int
28293hasInternalSubsetSplit(void *ctx)
28294{
Daniel Veillard971771e2005-07-09 17:32:57 +000028295 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028296 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28297 (ctxt->user_sax->hasInternalSubset != NULL))
28298 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28299 return(0);
28300}
28301
28302static int
28303hasExternalSubsetSplit(void *ctx)
28304{
Daniel Veillard971771e2005-07-09 17:32:57 +000028305 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028306 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28307 (ctxt->user_sax->hasExternalSubset != NULL))
28308 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28309 return(0);
28310}
28311
28312static void
28313externalSubsetSplit(void *ctx, const xmlChar *name,
28314 const xmlChar *ExternalID, const xmlChar *SystemID)
28315{
Daniel Veillard971771e2005-07-09 17:32:57 +000028316 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028317 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
Daniel Veillardb3e45362008-03-26 13:39:31 +000028318 (ctxt->user_sax->externalSubset != NULL))
28319 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028320 SystemID);
28321}
28322
28323static xmlParserInputPtr
28324resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28325{
Daniel Veillard971771e2005-07-09 17:32:57 +000028326 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028327 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28328 (ctxt->user_sax->resolveEntity != NULL))
28329 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28330 systemId));
28331 return(NULL);
28332}
28333
28334static xmlEntityPtr
28335getEntitySplit(void *ctx, const xmlChar *name)
28336{
Daniel Veillard971771e2005-07-09 17:32:57 +000028337 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028338 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28339 (ctxt->user_sax->getEntity != NULL))
28340 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28341 return(NULL);
28342}
28343
28344static xmlEntityPtr
28345getParameterEntitySplit(void *ctx, const xmlChar *name)
28346{
Daniel Veillard971771e2005-07-09 17:32:57 +000028347 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028348 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349 (ctxt->user_sax->getParameterEntity != NULL))
28350 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28351 return(NULL);
28352}
28353
28354
28355static void
28356entityDeclSplit(void *ctx, const xmlChar *name, int type,
28357 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28358{
Daniel Veillard971771e2005-07-09 17:32:57 +000028359 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028360 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361 (ctxt->user_sax->entityDecl != NULL))
28362 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28363 systemId, content);
28364}
28365
28366static void
28367attributeDeclSplit(void *ctx, const xmlChar * elem,
28368 const xmlChar * name, int type, int def,
28369 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28370{
Daniel Veillard971771e2005-07-09 17:32:57 +000028371 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028372 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28373 (ctxt->user_sax->attributeDecl != NULL)) {
28374 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28375 def, defaultValue, tree);
28376 } else {
28377 xmlFreeEnumeration(tree);
28378 }
28379}
28380
28381static void
28382elementDeclSplit(void *ctx, const xmlChar *name, int type,
28383 xmlElementContentPtr content)
28384{
Daniel Veillard971771e2005-07-09 17:32:57 +000028385 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028386 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28387 (ctxt->user_sax->elementDecl != NULL))
28388 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28389}
28390
28391static void
28392notationDeclSplit(void *ctx, const xmlChar *name,
28393 const xmlChar *publicId, const xmlChar *systemId)
28394{
Daniel Veillard971771e2005-07-09 17:32:57 +000028395 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028396 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28397 (ctxt->user_sax->notationDecl != NULL))
28398 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28399 systemId);
28400}
28401
28402static void
28403unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28404 const xmlChar *publicId, const xmlChar *systemId,
28405 const xmlChar *notationName)
28406{
Daniel Veillard971771e2005-07-09 17:32:57 +000028407 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028408 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28409 (ctxt->user_sax->unparsedEntityDecl != NULL))
28410 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28411 systemId, notationName);
28412}
28413
28414static void
28415setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28416{
Daniel Veillard971771e2005-07-09 17:32:57 +000028417 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028418 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28419 (ctxt->user_sax->setDocumentLocator != NULL))
28420 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28421}
28422
28423static void
28424startDocumentSplit(void *ctx)
28425{
Daniel Veillard971771e2005-07-09 17:32:57 +000028426 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028427 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28428 (ctxt->user_sax->startDocument != NULL))
28429 ctxt->user_sax->startDocument(ctxt->user_data);
28430}
28431
28432static void
28433endDocumentSplit(void *ctx)
28434{
Daniel Veillard971771e2005-07-09 17:32:57 +000028435 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028436 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28437 (ctxt->user_sax->endDocument != NULL))
28438 ctxt->user_sax->endDocument(ctxt->user_data);
28439}
28440
28441static void
28442processingInstructionSplit(void *ctx, const xmlChar *target,
28443 const xmlChar *data)
28444{
Daniel Veillard971771e2005-07-09 17:32:57 +000028445 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028446 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28447 (ctxt->user_sax->processingInstruction != NULL))
28448 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28449}
28450
28451static void
28452commentSplit(void *ctx, const xmlChar *value)
28453{
Daniel Veillard971771e2005-07-09 17:32:57 +000028454 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028455 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28456 (ctxt->user_sax->comment != NULL))
28457 ctxt->user_sax->comment(ctxt->user_data, value);
28458}
28459
28460/*
28461 * Varargs error callbacks to the user application, harder ...
28462 */
28463
Daniel Veillardffa3c742005-07-21 13:24:09 +000028464static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028465warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028466 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028467 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28468 (ctxt->user_sax->warning != NULL)) {
28469 TODO
28470 }
28471}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028472static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028473errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028474 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028475 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28476 (ctxt->user_sax->error != NULL)) {
28477 TODO
28478 }
28479}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028480static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028481fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028482 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028483 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28484 (ctxt->user_sax->fatalError != NULL)) {
28485 TODO
28486 }
28487}
28488
28489/*
28490 * Those are function where both the user handler and the schemas handler
28491 * need to be called.
28492 */
28493static void
28494charactersSplit(void *ctx, const xmlChar *ch, int len)
28495{
Daniel Veillard971771e2005-07-09 17:32:57 +000028496 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028497 if (ctxt == NULL)
28498 return;
28499 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28500 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28501 if (ctxt->ctxt != NULL)
28502 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28503}
28504
28505static void
28506ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28507{
Daniel Veillard971771e2005-07-09 17:32:57 +000028508 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028509 if (ctxt == NULL)
28510 return;
28511 if ((ctxt->user_sax != NULL) &&
28512 (ctxt->user_sax->ignorableWhitespace != NULL))
28513 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28514 if (ctxt->ctxt != NULL)
28515 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28516}
28517
28518static void
28519cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28520{
Daniel Veillard971771e2005-07-09 17:32:57 +000028521 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028522 if (ctxt == NULL)
28523 return;
28524 if ((ctxt->user_sax != NULL) &&
Daniel Veillard7d0ca5e2008-02-05 08:43:52 +000028525 (ctxt->user_sax->cdataBlock != NULL))
28526 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028527 if (ctxt->ctxt != NULL)
28528 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28529}
28530
28531static void
28532referenceSplit(void *ctx, const xmlChar *name)
28533{
Daniel Veillard971771e2005-07-09 17:32:57 +000028534 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillard14b56432006-03-09 18:41:40 +000028535 if (ctxt == NULL)
28536 return;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028537 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28538 (ctxt->user_sax->reference != NULL))
28539 ctxt->user_sax->reference(ctxt->user_data, name);
28540 if (ctxt->ctxt != NULL)
28541 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28542}
28543
28544static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028545startElementNsSplit(void *ctx, const xmlChar * localname,
28546 const xmlChar * prefix, const xmlChar * URI,
28547 int nb_namespaces, const xmlChar ** namespaces,
28548 int nb_attributes, int nb_defaulted,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028549 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028550 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028551 if (ctxt == NULL)
28552 return;
28553 if ((ctxt->user_sax != NULL) &&
28554 (ctxt->user_sax->startElementNs != NULL))
28555 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28556 URI, nb_namespaces, namespaces,
28557 nb_attributes, nb_defaulted,
28558 attributes);
28559 if (ctxt->ctxt != NULL)
28560 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28561 URI, nb_namespaces, namespaces,
28562 nb_attributes, nb_defaulted,
28563 attributes);
28564}
28565
28566static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028567endElementNsSplit(void *ctx, const xmlChar * localname,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028568 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028569 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028570 if (ctxt == NULL)
28571 return;
28572 if ((ctxt->user_sax != NULL) &&
28573 (ctxt->user_sax->endElementNs != NULL))
28574 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28575 if (ctxt->ctxt != NULL)
28576 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28577}
28578
Daniel Veillard4255d502002-04-16 15:50:10 +000028579/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028580 * xmlSchemaSAXPlug:
28581 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028582 * @sax: a pointer to the original xmlSAXHandlerPtr
28583 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028584 *
28585 * Plug a SAX based validation layer in a SAX parsing event flow.
28586 * The original @saxptr and @dataptr data are replaced by new pointers
28587 * but the calls to the original will be maintained.
28588 *
28589 * Returns a pointer to a data structure needed to unplug the validation layer
28590 * or NULL in case of errors.
28591 */
28592xmlSchemaSAXPlugPtr
28593xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28594 xmlSAXHandlerPtr *sax, void **user_data)
28595{
28596 xmlSchemaSAXPlugPtr ret;
28597 xmlSAXHandlerPtr old_sax;
28598
28599 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28600 return(NULL);
28601
28602 /*
28603 * We only allow to plug into SAX2 event streams
28604 */
28605 old_sax = *sax;
28606 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28607 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000028608 if ((old_sax != NULL) &&
Daniel Veillard971771e2005-07-09 17:32:57 +000028609 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28610 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28611 return(NULL);
28612
28613 /*
28614 * everything seems right allocate the local data needed for that layer
28615 */
28616 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28617 if (ret == NULL) {
28618 return(NULL);
28619 }
28620 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28621 ret->magic = XML_SAX_PLUG_MAGIC;
28622 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28623 ret->ctxt = ctxt;
28624 ret->user_sax_ptr = sax;
28625 ret->user_sax = old_sax;
Daniel Veillarddee23482008-04-11 12:58:43 +000028626 if (old_sax == NULL) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028627 /*
28628 * go direct, no need for the split block and functions.
28629 */
28630 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28631 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28632 /*
28633 * Note that we use the same text-function for both, to prevent
28634 * the parser from testing for ignorable whitespace.
28635 */
28636 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28637 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28638
28639 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28640 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28641
28642 ret->user_data = ctxt;
28643 *user_data = ctxt;
28644 } else {
28645 /*
28646 * for each callback unused by Schemas initialize it to the Split
Daniel Veillarddee23482008-04-11 12:58:43 +000028647 * routine only if non NULL in the user block, this can speed up
Daniel Veillard971771e2005-07-09 17:32:57 +000028648 * things at the SAX level.
28649 */
28650 if (old_sax->internalSubset != NULL)
28651 ret->schemas_sax.internalSubset = internalSubsetSplit;
28652 if (old_sax->isStandalone != NULL)
28653 ret->schemas_sax.isStandalone = isStandaloneSplit;
28654 if (old_sax->hasInternalSubset != NULL)
28655 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28656 if (old_sax->hasExternalSubset != NULL)
28657 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28658 if (old_sax->resolveEntity != NULL)
28659 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28660 if (old_sax->getEntity != NULL)
28661 ret->schemas_sax.getEntity = getEntitySplit;
28662 if (old_sax->entityDecl != NULL)
28663 ret->schemas_sax.entityDecl = entityDeclSplit;
28664 if (old_sax->notationDecl != NULL)
28665 ret->schemas_sax.notationDecl = notationDeclSplit;
28666 if (old_sax->attributeDecl != NULL)
28667 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28668 if (old_sax->elementDecl != NULL)
28669 ret->schemas_sax.elementDecl = elementDeclSplit;
28670 if (old_sax->unparsedEntityDecl != NULL)
28671 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28672 if (old_sax->setDocumentLocator != NULL)
28673 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28674 if (old_sax->startDocument != NULL)
28675 ret->schemas_sax.startDocument = startDocumentSplit;
28676 if (old_sax->endDocument != NULL)
28677 ret->schemas_sax.endDocument = endDocumentSplit;
28678 if (old_sax->processingInstruction != NULL)
28679 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28680 if (old_sax->comment != NULL)
28681 ret->schemas_sax.comment = commentSplit;
28682 if (old_sax->warning != NULL)
28683 ret->schemas_sax.warning = warningSplit;
28684 if (old_sax->error != NULL)
28685 ret->schemas_sax.error = errorSplit;
28686 if (old_sax->fatalError != NULL)
28687 ret->schemas_sax.fatalError = fatalErrorSplit;
28688 if (old_sax->getParameterEntity != NULL)
28689 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28690 if (old_sax->externalSubset != NULL)
28691 ret->schemas_sax.externalSubset = externalSubsetSplit;
28692
28693 /*
28694 * the 6 schemas callback have to go to the splitter functions
28695 * Note that we use the same text-function for ignorableWhitespace
28696 * if possible, to prevent the parser from testing for ignorable
28697 * whitespace.
28698 */
28699 ret->schemas_sax.characters = charactersSplit;
28700 if ((old_sax->ignorableWhitespace != NULL) &&
28701 (old_sax->ignorableWhitespace != old_sax->characters))
28702 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28703 else
28704 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28705 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28706 ret->schemas_sax.reference = referenceSplit;
28707 ret->schemas_sax.startElementNs = startElementNsSplit;
28708 ret->schemas_sax.endElementNs = endElementNsSplit;
28709
28710 ret->user_data_ptr = user_data;
28711 ret->user_data = *user_data;
28712 *user_data = ret;
28713 }
28714
28715 /*
28716 * plug the pointers back.
28717 */
28718 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028719 ctxt->sax = *sax;
28720 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28721 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028722 return(ret);
28723}
28724
28725/**
28726 * xmlSchemaSAXUnplug:
28727 * @plug: a data structure returned by xmlSchemaSAXPlug
28728 *
28729 * Unplug a SAX based validation layer in a SAX parsing event flow.
28730 * The original pointers used in the call are restored.
28731 *
28732 * Returns 0 in case of success and -1 in case of failure.
28733 */
28734int
28735xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28736{
28737 xmlSAXHandlerPtr *sax;
28738 void **user_data;
28739
28740 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28741 return(-1);
28742 plug->magic = 0;
28743
Daniel Veillardf10ae122005-07-10 19:03:16 +000028744 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028745 /* restore the data */
28746 sax = plug->user_sax_ptr;
28747 *sax = plug->user_sax;
28748 if (plug->user_sax != NULL) {
28749 user_data = plug->user_data_ptr;
28750 *user_data = plug->user_data;
28751 }
28752
28753 /* free and return */
28754 xmlFree(plug);
28755 return(0);
28756}
28757
28758/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080028759 * xmlSchemaValidateSetLocator:
28760 * @vctxt: a schema validation context
28761 * @f: the locator function pointer
28762 * @ctxt: the locator context
28763 *
28764 * Allows to set a locator function to the validation context,
28765 * which will be used to provide file and line information since
28766 * those are not provided as part of the SAX validation flow
28767 * Setting @f to NULL disable the locator.
28768 */
28769
28770void
28771xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28772 xmlSchemaValidityLocatorFunc f,
28773 void *ctxt)
28774{
28775 if (vctxt == NULL) return;
28776 vctxt->locFunc = f;
28777 vctxt->locCtxt = ctxt;
28778}
28779
28780/**
28781 * xmlSchemaValidateStreamLocator:
28782 * @ctx: the xmlTextReaderPtr used
28783 * @file: returned file information
28784 * @line: returned line information
28785 *
28786 * Internal locator function for the readers
28787 *
28788 * Returns 0 in case the Schema validation could be (des)activated and
28789 * -1 in case of error.
28790 */
28791static int
28792xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28793 unsigned long *line) {
28794 xmlParserCtxtPtr ctxt;
28795
28796 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28797 return(-1);
28798
28799 if (file != NULL)
28800 *file = NULL;
28801 if (line != NULL)
28802 *line = 0;
28803
28804 ctxt = (xmlParserCtxtPtr) ctx;
28805 if (ctxt->input != NULL) {
28806 if (file != NULL)
28807 *file = ctxt->input->filename;
28808 if (line != NULL)
28809 *line = ctxt->input->line;
28810 return(0);
28811 }
28812 return(-1);
28813}
28814
28815/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028816 * xmlSchemaValidateStream:
28817 * @ctxt: a schema validation context
28818 * @input: the input to use for reading the data
28819 * @enc: an optional encoding information
28820 * @sax: a SAX handler for the resulting events
28821 * @user_data: the context to provide to the SAX handler.
28822 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028823 * Validate an input based on a flow of SAX event from the parser
28824 * and forward the events to the @sax handler with the provided @user_data
28825 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000028826 *
28827 * Returns 0 if the document is schemas valid, a positive error code
28828 * number otherwise and -1 in case of internal or API error.
28829 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028830int
Daniel Veillard4255d502002-04-16 15:50:10 +000028831xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028832 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28833 xmlSAXHandlerPtr sax, void *user_data)
28834{
Daniel Veillard971771e2005-07-09 17:32:57 +000028835 xmlSchemaSAXPlugPtr plug = NULL;
28836 xmlSAXHandlerPtr old_sax = NULL;
28837 xmlParserCtxtPtr pctxt = NULL;
28838 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028839 int ret;
28840
Daniel Veillard4255d502002-04-16 15:50:10 +000028841 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028842 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028843
Daniel Veillardcdc82732005-07-08 15:04:06 +000028844 /*
28845 * prepare the parser
28846 */
28847 pctxt = xmlNewParserCtxt();
28848 if (pctxt == NULL)
28849 return (-1);
28850 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000028851 pctxt->sax = sax;
28852 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028853#if 0
28854 if (options)
28855 xmlCtxtUseOptions(pctxt, options);
28856#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000028857 pctxt->linenumbers = 1;
Daniel Veillard97fa5b32012-08-14 11:01:07 +080028858 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028859
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000028860 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028861 if (inputStream == NULL) {
28862 ret = -1;
28863 goto done;
28864 }
28865 inputPush(pctxt, inputStream);
28866 ctxt->parserCtxt = pctxt;
28867 ctxt->input = input;
28868
28869 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000028870 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000028871 */
Daniel Veillard971771e2005-07-09 17:32:57 +000028872 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28873 if (plug == NULL) {
28874 ret = -1;
28875 goto done;
28876 }
28877 ctxt->input = input;
28878 ctxt->enc = enc;
28879 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028880 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28881 ret = xmlSchemaVStart(ctxt);
28882
28883 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28884 ret = ctxt->parserCtxt->errNo;
28885 if (ret == 0)
28886 ret = 1;
Daniel Veillard33fe2882008-04-10 08:09:25 +000028887 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028888
28889done:
Daniel Veillard971771e2005-07-09 17:32:57 +000028890 ctxt->parserCtxt = NULL;
28891 ctxt->sax = NULL;
28892 ctxt->input = NULL;
28893 if (plug != NULL) {
28894 xmlSchemaSAXUnplug(plug);
28895 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028896 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000028897 if (pctxt != NULL) {
28898 pctxt->sax = old_sax;
28899 xmlFreeParserCtxt(pctxt);
28900 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000028901 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000028902}
28903
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028904/**
28905 * xmlSchemaValidateFile:
28906 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000028907 * @filename: the URI of the instance
28908 * @options: a future set of options, currently unused
28909 *
28910 * Do a schemas validation of the given resource, it will use the
28911 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028912 *
28913 * Returns 0 if the document is valid, a positive error code
28914 * number otherwise and -1 in case of an internal or API error.
28915 */
28916int
28917xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000028918 const char * filename,
28919 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028920{
28921 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028922 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028923
28924 if ((ctxt == NULL) || (filename == NULL))
28925 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000028926
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028927 input = xmlParserInputBufferCreateFilename(filename,
28928 XML_CHAR_ENCODING_NONE);
28929 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028930 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000028931 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
Daniel Veillarddee23482008-04-11 12:58:43 +000028932 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028933 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000028934}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028935
Daniel Veillarddee23482008-04-11 12:58:43 +000028936/**
28937 * xmlSchemaValidCtxtGetParserCtxt:
28938 * @ctxt: a schema validation context
28939 *
28940 * allow access to the parser context of the schema validation context
28941 *
28942 * Returns the parser context of the schema validation context or NULL
28943 * in case of error.
28944 */
28945xmlParserCtxtPtr
28946xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28947{
28948 if (ctxt == NULL)
28949 return(NULL);
28950 return (ctxt->parserCtxt);
28951}
28952
Daniel Veillard5d4644e2005-04-01 13:11:58 +000028953#define bottom_xmlschemas
28954#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000028955#endif /* LIBXML_SCHEMAS_ENABLED */