blob: 1efd09624965cef42ddefd1663867dd2c2bdc360 [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:
Haibo Huangcfd91dc2020-07-30 23:01:33 -070025 * - Eliminated 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 */
Haibo Huang3496e1e2020-11-30 18:17:15 -0800863 xmlHashTablePtr htab;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000864};
865
866/*
867* Element info flags.
868*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000869#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
870#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
871#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
872#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
873
874#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
875#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
876#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
877
878#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
879#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
880#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
881#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000882
883/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000884 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000885 *
886 * Holds information of an element node.
887 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000888struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000889 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000890 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000891 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000892 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000893 const xmlChar *nsName;
894 const xmlChar *value;
895 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000896 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000897
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000898 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000899
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000900 int valNeeded;
901 int normVal;
902
903 xmlSchemaElementPtr decl; /* the element/attribute declaration */
904 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000905 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
906 for the scope element*/
907 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
908 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000909 xmlRegExecCtxtPtr regexCtxt;
910
911 const xmlChar **nsBindings; /* Namespace bindings on this element */
912 int nbNsBindings;
Daniel Veillarddee23482008-04-11 12:58:43 +0000913 int sizeNsBindings;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000914
915 int hasKeyrefs;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +0000916 int appliedXPath; /* Indicates that an XPath has been applied. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000917};
918
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000919#define XML_SCHEMAS_ATTR_UNKNOWN 1
920#define XML_SCHEMAS_ATTR_ASSESSED 2
921#define XML_SCHEMAS_ATTR_PROHIBITED 3
922#define XML_SCHEMAS_ATTR_ERR_MISSING 4
923#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
924#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
925#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
926#define XML_SCHEMAS_ATTR_DEFAULT 8
927#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
928#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
929#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
930#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
931#define XML_SCHEMAS_ATTR_WILD_SKIP 13
932#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
933#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
934#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
935#define XML_SCHEMAS_ATTR_META 17
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000936/*
937* @metaType values of xmlSchemaAttrInfo.
938*/
939#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
940#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
941#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
942#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
943#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000944
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000945typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
946typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
947struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000948 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000949 xmlNodePtr node;
Daniel Veillarddee23482008-04-11 12:58:43 +0000950 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000951 const xmlChar *localName;
952 const xmlChar *nsName;
953 const xmlChar *value;
954 xmlSchemaValPtr val; /* the pre-computed value if any */
955 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
956 int flags; /* combination of node info flags */
957
958 xmlSchemaAttributePtr decl; /* the attribute declaration */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +0000959 xmlSchemaAttributeUsePtr use; /* the attribute use */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000960 int state;
961 int metaType;
962 const xmlChar *vcValue; /* the value constraint value */
963 xmlSchemaNodeInfoPtr parent;
964};
965
966
967#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000968/**
969 * xmlSchemaValidCtxt:
970 *
971 * A Schemas validation context
972 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000973struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000974 int type;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +0000975 void *errCtxt; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000976 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000977 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000978 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000979
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000980 xmlSchemaPtr schema; /* The schema in use */
981 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000982 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000983 xmlCharEncoding enc;
984 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000985 xmlParserCtxtPtr parserCtxt;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +0000986 void *user_data; /* TODO: What is this for? */
Daniel Veillard97fa5b32012-08-14 11:01:07 +0800987 char *filename;
Daniel Veillard4255d502002-04-16 15:50:10 +0000988
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000989 int err;
990 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000991
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000992 xmlNodePtr node;
993 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000994 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000995
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000996 xmlRegExecCtxtPtr regexp;
997 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000998
Daniel Veillardc0826a72004-08-10 14:17:33 +0000999 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001000 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001001 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001002 xmlSchemaParserCtxtPtr pctxt;
1003 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001004
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001005 int depth;
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001006 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001007 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001008 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001009
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001010 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001011
1012 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1013 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +00001014 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001015
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001016 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1017 int nbIdcNodes;
1018 int sizeIdcNodes;
1019
1020 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1021 int nbIdcKeys;
1022 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001023
1024 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001025
1026 xmlDictPtr dict;
1027
Daniel Veillard39e5c892005-07-03 22:48:50 +00001028#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001029 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +00001030#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001031
1032 xmlSchemaAttrInfoPtr *attrInfos;
1033 int nbAttrInfos;
1034 int sizeAttrInfos;
1035
1036 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001037 xmlSchemaItemListPtr nodeQNames;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00001038 int hasKeyrefs;
1039 int createIDCNodeTables;
1040 int psviExposeIDCNodeTables;
Daniel Veillard97fa5b32012-08-14 11:01:07 +08001041
1042 /* Locator for error reporting in streaming mode */
1043 xmlSchemaValidityLocatorFunc locFunc;
1044 void *locCtxt;
Daniel Veillard4255d502002-04-16 15:50:10 +00001045};
1046
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00001047/**
1048 * xmlSchemaSubstGroup:
1049 *
1050 *
1051 */
1052typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1053typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1054struct _xmlSchemaSubstGroup {
1055 xmlSchemaElementPtr head;
1056 xmlSchemaItemListPtr members;
1057};
1058
Haibo Huang3496e1e2020-11-30 18:17:15 -08001059/**
1060 * xmlIDCHashEntry:
1061 *
1062 * an entry in hash tables to quickly look up keys/uniques
1063 */
1064typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1065typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1066struct _xmlIDCHashEntry {
1067 xmlIDCHashEntryPtr next; /* next item with same hash */
1068 int index; /* index into associated item list */
1069};
1070
Daniel Veillard4255d502002-04-16 15:50:10 +00001071/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001072 * *
1073 * Some predeclarations *
1074 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00001075 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001076
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001077static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1078 xmlSchemaPtr schema,
1079 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001080static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1081 xmlSchemaPtr schema,
1082 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001083static int
1084xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001085 xmlSchemaAbstractCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001086static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001087xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1088static int
William M. Brack2f2a6632004-08-20 23:09:47 +00001089xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1090 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001091static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001092xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1093 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +00001094static void
1095xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001096static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001097xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001098static xmlSchemaTreeItemPtr
1099xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1100 xmlNodePtr node, xmlSchemaTypeType type,
1101 int withParticle);
1102static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001103xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001104static xmlSchemaTypeLinkPtr
1105xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001106static void
1107xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1108 const char *funcName,
David Kilzer4472c3a2016-05-13 15:13:17 +08001109 const char *message) LIBXML_ATTR_FORMAT(3,0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001110static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +00001111xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001112 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001113 xmlSchemaTypePtr baseType,
1114 int subset);
1115static void
1116xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001117 xmlSchemaParserCtxtPtr ctxt);
1118static void
1119xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001120static xmlSchemaQNameRefPtr
1121xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1122 xmlSchemaPtr schema,
1123 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +00001124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001125/************************************************************************
1126 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001127 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001128 * *
1129 ************************************************************************/
1130
1131/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001132 * xmlSchemaItemTypeToStr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001133 * @type: the type of the schema item
1134 *
1135 * Returns the component name of a schema item.
1136 */
1137static const xmlChar *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001138xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001139{
1140 switch (type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001141 case XML_SCHEMA_TYPE_BASIC:
1142 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001143 case XML_SCHEMA_TYPE_SIMPLE:
1144 return(BAD_CAST "simple type definition");
1145 case XML_SCHEMA_TYPE_COMPLEX:
1146 return(BAD_CAST "complex type definition");
1147 case XML_SCHEMA_TYPE_ELEMENT:
1148 return(BAD_CAST "element declaration");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001149 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1150 return(BAD_CAST "attribute use");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001151 case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 return(BAD_CAST "attribute declaration");
1153 case XML_SCHEMA_TYPE_GROUP:
1154 return(BAD_CAST "model group definition");
1155 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1156 return(BAD_CAST "attribute group definition");
1157 case XML_SCHEMA_TYPE_NOTATION:
1158 return(BAD_CAST "notation declaration");
1159 case XML_SCHEMA_TYPE_SEQUENCE:
1160 return(BAD_CAST "model group (sequence)");
1161 case XML_SCHEMA_TYPE_CHOICE:
1162 return(BAD_CAST "model group (choice)");
1163 case XML_SCHEMA_TYPE_ALL:
1164 return(BAD_CAST "model group (all)");
1165 case XML_SCHEMA_TYPE_PARTICLE:
1166 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001167 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001168 return(BAD_CAST "unique identity-constraint");
1169 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001170 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001171 return(BAD_CAST "key identity-constraint");
1172 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001173 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001174 return(BAD_CAST "keyref identity-constraint");
1175 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00001176 case XML_SCHEMA_TYPE_ANY:
1177 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001178 case XML_SCHEMA_EXTRA_QNAMEREF:
1179 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001180 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1181 return(BAD_CAST "[helper component] attribute use prohibition");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001182 default:
1183 return(BAD_CAST "Not a schema component");
1184 }
1185}
1186
1187/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001188 * xmlSchemaGetComponentTypeStr:
1189 * @type: the type of the schema item
1190 *
1191 * Returns the component name of a schema item.
1192 */
1193static const xmlChar *
1194xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1195{
1196 switch (item->type) {
1197 case XML_SCHEMA_TYPE_BASIC:
1198 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1199 return(BAD_CAST "complex type definition");
1200 else
Daniel Veillarddee23482008-04-11 12:58:43 +00001201 return(BAD_CAST "simple type definition");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001202 default:
1203 return(xmlSchemaItemTypeToStr(item->type));
1204 }
1205}
1206
1207/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001208 * xmlSchemaGetComponentNode:
1209 * @item: a schema component
1210 *
1211 * Returns node associated with the schema component.
1212 * NOTE that such a node need not be available; plus, a component's
1213 * node need not to reflect the component directly, since there is no
1214 * one-to-one relationship between the XML Schema representation and
1215 * the component representation.
1216 */
1217static xmlNodePtr
1218xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1219{
1220 switch (item->type) {
1221 case XML_SCHEMA_TYPE_ELEMENT:
1222 return (((xmlSchemaElementPtr) item)->node);
1223 case XML_SCHEMA_TYPE_ATTRIBUTE:
1224 return (((xmlSchemaAttributePtr) item)->node);
1225 case XML_SCHEMA_TYPE_COMPLEX:
1226 case XML_SCHEMA_TYPE_SIMPLE:
1227 return (((xmlSchemaTypePtr) item)->node);
1228 case XML_SCHEMA_TYPE_ANY:
1229 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1230 return (((xmlSchemaWildcardPtr) item)->node);
1231 case XML_SCHEMA_TYPE_PARTICLE:
1232 return (((xmlSchemaParticlePtr) item)->node);
1233 case XML_SCHEMA_TYPE_SEQUENCE:
1234 case XML_SCHEMA_TYPE_CHOICE:
1235 case XML_SCHEMA_TYPE_ALL:
1236 return (((xmlSchemaModelGroupPtr) item)->node);
1237 case XML_SCHEMA_TYPE_GROUP:
1238 return (((xmlSchemaModelGroupDefPtr) item)->node);
1239 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1240 return (((xmlSchemaAttributeGroupPtr) item)->node);
1241 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1242 case XML_SCHEMA_TYPE_IDC_KEY:
1243 case XML_SCHEMA_TYPE_IDC_KEYREF:
1244 return (((xmlSchemaIDCPtr) item)->node);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001245 case XML_SCHEMA_EXTRA_QNAMEREF:
1246 return(((xmlSchemaQNameRefPtr) item)->node);
1247 /* TODO: What to do with NOTATIONs?
1248 case XML_SCHEMA_TYPE_NOTATION:
1249 return (((xmlSchemaNotationPtr) item)->node);
1250 */
1251 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1252 return (((xmlSchemaAttributeUsePtr) item)->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001253 default:
1254 return (NULL);
1255 }
1256}
1257
1258#if 0
1259/**
1260 * xmlSchemaGetNextComponent:
1261 * @item: a schema component
1262 *
1263 * Returns the next sibling of the schema component.
1264 */
1265static xmlSchemaBasicItemPtr
1266xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1267{
1268 switch (item->type) {
1269 case XML_SCHEMA_TYPE_ELEMENT:
1270 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1271 case XML_SCHEMA_TYPE_ATTRIBUTE:
1272 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1273 case XML_SCHEMA_TYPE_COMPLEX:
1274 case XML_SCHEMA_TYPE_SIMPLE:
1275 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1276 case XML_SCHEMA_TYPE_ANY:
1277 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1278 return (NULL);
1279 case XML_SCHEMA_TYPE_PARTICLE:
1280 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1281 case XML_SCHEMA_TYPE_SEQUENCE:
1282 case XML_SCHEMA_TYPE_CHOICE:
1283 case XML_SCHEMA_TYPE_ALL:
1284 return (NULL);
1285 case XML_SCHEMA_TYPE_GROUP:
1286 return (NULL);
1287 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1288 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1289 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1290 case XML_SCHEMA_TYPE_IDC_KEY:
1291 case XML_SCHEMA_TYPE_IDC_KEYREF:
1292 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1293 default:
1294 return (NULL);
1295 }
1296}
1297#endif
1298
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001299
1300/**
1301 * xmlSchemaFormatQName:
1302 * @buf: the string buffer
1303 * @namespaceName: the namespace name
1304 * @localName: the local name
1305 *
1306 * Returns the given QName in the format "{namespaceName}localName" or
1307 * just "localName" if @namespaceName is NULL.
1308 *
1309 * Returns the localName if @namespaceName is NULL, a formatted
1310 * string otherwise.
1311 */
1312static const xmlChar*
1313xmlSchemaFormatQName(xmlChar **buf,
1314 const xmlChar *namespaceName,
1315 const xmlChar *localName)
1316{
1317 FREE_AND_NULL(*buf)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001318 if (namespaceName != NULL) {
1319 *buf = xmlStrdup(BAD_CAST "{");
1320 *buf = xmlStrcat(*buf, namespaceName);
1321 *buf = xmlStrcat(*buf, BAD_CAST "}");
1322 }
1323 if (localName != NULL) {
1324 if (namespaceName == NULL)
1325 return(localName);
1326 *buf = xmlStrcat(*buf, localName);
1327 } else {
1328 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
Daniel Veillarddee23482008-04-11 12:58:43 +00001329 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001330 return ((const xmlChar *) *buf);
1331}
1332
Daniel Veillarddee23482008-04-11 12:58:43 +00001333static const xmlChar*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001334xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1335{
1336 if (ns != NULL)
1337 return (xmlSchemaFormatQName(buf, ns->href, localName));
1338 else
1339 return (xmlSchemaFormatQName(buf, NULL, localName));
1340}
1341
1342static const xmlChar *
1343xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1344{
1345 switch (item->type) {
1346 case XML_SCHEMA_TYPE_ELEMENT:
1347 return (((xmlSchemaElementPtr) item)->name);
1348 case XML_SCHEMA_TYPE_ATTRIBUTE:
1349 return (((xmlSchemaAttributePtr) item)->name);
1350 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1351 return (((xmlSchemaAttributeGroupPtr) item)->name);
1352 case XML_SCHEMA_TYPE_BASIC:
1353 case XML_SCHEMA_TYPE_SIMPLE:
1354 case XML_SCHEMA_TYPE_COMPLEX:
1355 return (((xmlSchemaTypePtr) item)->name);
1356 case XML_SCHEMA_TYPE_GROUP:
1357 return (((xmlSchemaModelGroupDefPtr) item)->name);
1358 case XML_SCHEMA_TYPE_IDC_KEY:
1359 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1360 case XML_SCHEMA_TYPE_IDC_KEYREF:
1361 return (((xmlSchemaIDCPtr) item)->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001362 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1363 if (WXS_ATTRUSE_DECL(item) != NULL) {
1364 return(xmlSchemaGetComponentName(
1365 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1366 } else
1367 return(NULL);
1368 case XML_SCHEMA_EXTRA_QNAMEREF:
1369 return (((xmlSchemaQNameRefPtr) item)->name);
1370 case XML_SCHEMA_TYPE_NOTATION:
1371 return (((xmlSchemaNotationPtr) item)->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001372 default:
1373 /*
1374 * Other components cannot have names.
1375 */
1376 break;
1377 }
1378 return (NULL);
1379}
1380
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001381#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1382#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1383/*
1384static const xmlChar *
1385xmlSchemaGetQNameRefName(void *ref)
1386{
1387 return(((xmlSchemaQNameRefPtr) ref)->name);
1388}
1389
1390static const xmlChar *
1391xmlSchemaGetQNameRefTargetNs(void *ref)
1392{
1393 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1394}
1395*/
1396
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001397static const xmlChar *
1398xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1399{
1400 switch (item->type) {
1401 case XML_SCHEMA_TYPE_ELEMENT:
1402 return (((xmlSchemaElementPtr) item)->targetNamespace);
1403 case XML_SCHEMA_TYPE_ATTRIBUTE:
1404 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1405 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1406 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1407 case XML_SCHEMA_TYPE_BASIC:
1408 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1409 case XML_SCHEMA_TYPE_SIMPLE:
1410 case XML_SCHEMA_TYPE_COMPLEX:
1411 return (((xmlSchemaTypePtr) item)->targetNamespace);
1412 case XML_SCHEMA_TYPE_GROUP:
1413 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1414 case XML_SCHEMA_TYPE_IDC_KEY:
1415 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1416 case XML_SCHEMA_TYPE_IDC_KEYREF:
1417 return (((xmlSchemaIDCPtr) item)->targetNamespace);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001418 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1419 if (WXS_ATTRUSE_DECL(item) != NULL) {
1420 return(xmlSchemaGetComponentTargetNs(
1421 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1422 }
1423 /* TODO: Will returning NULL break something? */
1424 break;
1425 case XML_SCHEMA_EXTRA_QNAMEREF:
1426 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1427 case XML_SCHEMA_TYPE_NOTATION:
1428 return (((xmlSchemaNotationPtr) item)->targetNamespace);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001429 default:
1430 /*
1431 * Other components cannot have names.
1432 */
1433 break;
1434 }
1435 return (NULL);
1436}
1437
1438static const xmlChar*
1439xmlSchemaGetComponentQName(xmlChar **buf,
1440 void *item)
1441{
1442 return (xmlSchemaFormatQName(buf,
1443 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1444 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1445}
1446
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001447static const xmlChar*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001448xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001449{
1450 xmlChar *str = NULL;
1451
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001452 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001453 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001454 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1455 (xmlSchemaBasicItemPtr) item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001456 *buf = xmlStrcat(*buf, BAD_CAST "'");
1457 FREE_AND_NULL(str);
1458 return(*buf);
1459}
1460
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001461static const xmlChar*
1462xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1463{
1464 return(xmlSchemaGetComponentDesignation(buf, idc));
1465}
1466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001467/**
1468 * xmlSchemaWildcardPCToString:
1469 * @pc: the type of processContents
1470 *
1471 * Returns a string representation of the type of
1472 * processContents.
1473 */
1474static const xmlChar *
1475xmlSchemaWildcardPCToString(int pc)
1476{
1477 switch (pc) {
1478 case XML_SCHEMAS_ANY_SKIP:
1479 return (BAD_CAST "skip");
1480 case XML_SCHEMAS_ANY_LAX:
1481 return (BAD_CAST "lax");
1482 case XML_SCHEMAS_ANY_STRICT:
1483 return (BAD_CAST "strict");
1484 default:
1485 return (BAD_CAST "invalid process contents");
1486 }
1487}
1488
1489/**
1490 * xmlSchemaGetCanonValueWhtspExt:
1491 * @val: the precomputed value
1492 * @retValue: the returned value
1493 * @ws: the whitespace type of the value
Haibo Huang3496e1e2020-11-30 18:17:15 -08001494 * @for_hash: non-zero if this is supposed to generate a string for hashing
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001495 *
Jan Pokorný7a7cad62013-11-29 23:26:26 +01001496 * Get a the canonical representation of the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001497 * The caller has to free the returned retValue.
1498 *
1499 * Returns 0 if the value could be built and -1 in case of
1500 * API errors or if the value type is not supported yet.
1501 */
1502static int
Haibo Huang3496e1e2020-11-30 18:17:15 -08001503xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1504 xmlSchemaWhitespaceValueType ws,
1505 xmlChar **retValue,
1506 int for_hash)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001507{
1508 int list;
1509 xmlSchemaValType valType;
1510 const xmlChar *value, *value2 = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00001511
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001512
1513 if ((retValue == NULL) || (val == NULL))
1514 return (-1);
1515 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1516 *retValue = NULL;
1517 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00001518 value = NULL;
1519 valType = xmlSchemaGetValType(val);
1520 switch (valType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001521 case XML_SCHEMAS_STRING:
1522 case XML_SCHEMAS_NORMSTRING:
1523 case XML_SCHEMAS_ANYSIMPLETYPE:
1524 value = xmlSchemaValueGetAsString(val);
1525 if (value != NULL) {
1526 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1527 value2 = xmlSchemaCollapseString(value);
1528 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1529 value2 = xmlSchemaWhiteSpaceReplace(value);
1530 if (value2 != NULL)
1531 value = value2;
1532 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001533 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001534 default:
1535 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1536 if (value2 != NULL)
1537 xmlFree((xmlChar *) value2);
1538 goto internal_error;
1539 }
Haibo Huang3496e1e2020-11-30 18:17:15 -08001540 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1541 /* We can mostly use the canonical value for hashing,
1542 except in the case of decimal. There the canonical
1543 representation requires a trailing '.0' even for
1544 non-fractional numbers, but for the derived integer
1545 types it forbids any decimal point. Nevertheless they
1546 compare equal if the value is equal. We need to generate
1547 the same hash value for this to work, and it's easiest
1548 to just cut off the useless '.0' suffix for the
1549 decimal type. */
1550 int len = xmlStrlen(value2);
1551 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1552 ((xmlChar*)value2)[len-2] = 0;
1553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001554 value = value2;
1555 }
1556 if (*retValue == NULL)
1557 if (value == NULL) {
1558 if (! list)
1559 *retValue = xmlStrdup(BAD_CAST "");
1560 } else
1561 *retValue = xmlStrdup(value);
1562 else if (value != NULL) {
1563 /* List. */
1564 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1565 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1566 }
1567 FREE_AND_NULL(value2)
1568 val = xmlSchemaValueGetNext(val);
1569 } while (val != NULL);
1570
1571 return (0);
1572internal_error:
1573 if (*retValue != NULL)
1574 xmlFree((xmlChar *) (*retValue));
1575 if (value2 != NULL)
1576 xmlFree((xmlChar *) value2);
1577 return (-1);
1578}
1579
Haibo Huang3496e1e2020-11-30 18:17:15 -08001580static int
1581xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1582 xmlSchemaWhitespaceValueType ws,
1583 xmlChar **retValue)
1584{
1585 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1586}
1587
1588static int
1589xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1590 xmlChar **retValue)
1591{
1592 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1593 retValue, 1);
1594}
1595
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001596/**
1597 * xmlSchemaFormatItemForReport:
1598 * @buf: the string buffer
1599 * @itemDes: the designation of the item
1600 * @itemName: the name of the item
Daniel Veillarddee23482008-04-11 12:58:43 +00001601 * @item: the item as an object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001602 * @itemNode: the node of the item
1603 * @local: the local name
1604 * @parsing: if the function is used during the parse
1605 *
1606 * Returns a representation of the given item used
Daniel Veillarddee23482008-04-11 12:58:43 +00001607 * for error reports.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001608 *
Daniel Veillarddee23482008-04-11 12:58:43 +00001609 * The following order is used to build the resulting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001610 * designation if the arguments are not NULL:
1611 * 1a. If itemDes not NULL -> itemDes
1612 * 1b. If (itemDes not NULL) and (itemName not NULL)
1613 * -> itemDes + itemName
1614 * 2. If the preceding was NULL and (item not NULL) -> item
1615 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
Daniel Veillarddee23482008-04-11 12:58:43 +00001616 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001617 * If the itemNode is an attribute node, the name of the attribute
1618 * will be appended to the result.
1619 *
1620 * Returns the formatted string and sets @buf to the resulting value.
Daniel Veillarddee23482008-04-11 12:58:43 +00001621 */
1622static xmlChar*
1623xmlSchemaFormatItemForReport(xmlChar **buf,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624 const xmlChar *itemDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001625 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001626 xmlNodePtr itemNode)
1627{
1628 xmlChar *str = NULL;
1629 int named = 1;
1630
1631 if (*buf != NULL) {
1632 xmlFree(*buf);
1633 *buf = NULL;
1634 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001635
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001636 if (itemDes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00001637 *buf = xmlStrdup(itemDes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 } else if (item != NULL) {
1639 switch (item->type) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001640 case XML_SCHEMA_TYPE_BASIC: {
1641 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1642
1643 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001644 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001645 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001646 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001647 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001648 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1649 else
1650 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001651 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001652 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001654 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001655 case XML_SCHEMA_TYPE_SIMPLE: {
1656 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1657
1658 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001659 *buf = xmlStrdup(BAD_CAST"");
1660 } else {
1661 *buf = xmlStrdup(BAD_CAST "local ");
1662 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001663 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001664 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001665 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001666 *buf = xmlStrcat(*buf, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001667 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001668 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1669 else
1670 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001671 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001672 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001673 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001674 *buf = xmlStrcat(*buf, BAD_CAST "'");
1675 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001677 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001678 case XML_SCHEMA_TYPE_COMPLEX: {
1679 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1680
1681 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001682 *buf = xmlStrdup(BAD_CAST "");
1683 else
1684 *buf = xmlStrdup(BAD_CAST "local ");
1685 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001686 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001687 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001688 *buf = xmlStrcat(*buf, type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001689 *buf = xmlStrcat(*buf, BAD_CAST "'");
1690 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001691 }
1692 break;
1693 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1694 xmlSchemaAttributeUsePtr ause;
Daniel Veillarddee23482008-04-11 12:58:43 +00001695
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001696 ause = WXS_ATTR_USE_CAST item;
1697 *buf = xmlStrdup(BAD_CAST "attribute use ");
1698 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1699 *buf = xmlStrcat(*buf, BAD_CAST "'");
1700 *buf = xmlStrcat(*buf,
1701 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1702 FREE_AND_NULL(str)
1703 *buf = xmlStrcat(*buf, BAD_CAST "'");
1704 } else {
1705 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1706 }
1707 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001708 break;
1709 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1710 xmlSchemaAttributePtr attr;
Daniel Veillarddee23482008-04-11 12:58:43 +00001711
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001712 attr = (xmlSchemaAttributePtr) item;
1713 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1714 *buf = xmlStrcat(*buf, BAD_CAST " '");
1715 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1716 attr->targetNamespace, attr->name));
1717 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001718 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001719 }
1720 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001721 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1722 xmlSchemaGetComponentDesignation(buf, item);
1723 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001724 case XML_SCHEMA_TYPE_ELEMENT: {
1725 xmlSchemaElementPtr elem;
1726
Daniel Veillarddee23482008-04-11 12:58:43 +00001727 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001728 *buf = xmlStrdup(BAD_CAST "element decl.");
1729 *buf = xmlStrcat(*buf, BAD_CAST " '");
1730 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1731 elem->targetNamespace, elem->name));
1732 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001733 }
1734 break;
1735 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1736 case XML_SCHEMA_TYPE_IDC_KEY:
Daniel Veillarddee23482008-04-11 12:58:43 +00001737 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001738 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1739 *buf = xmlStrdup(BAD_CAST "unique '");
1740 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1741 *buf = xmlStrdup(BAD_CAST "key '");
1742 else
1743 *buf = xmlStrdup(BAD_CAST "keyRef '");
1744 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1745 *buf = xmlStrcat(*buf, BAD_CAST "'");
1746 break;
1747 case XML_SCHEMA_TYPE_ANY:
1748 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1749 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1750 ((xmlSchemaWildcardPtr) item)->processContents));
1751 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1752 break;
1753 case XML_SCHEMA_FACET_MININCLUSIVE:
1754 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1755 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1756 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1757 case XML_SCHEMA_FACET_TOTALDIGITS:
1758 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1759 case XML_SCHEMA_FACET_PATTERN:
1760 case XML_SCHEMA_FACET_ENUMERATION:
1761 case XML_SCHEMA_FACET_WHITESPACE:
1762 case XML_SCHEMA_FACET_LENGTH:
1763 case XML_SCHEMA_FACET_MAXLENGTH:
1764 case XML_SCHEMA_FACET_MINLENGTH:
1765 *buf = xmlStrdup(BAD_CAST "facet '");
1766 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1767 *buf = xmlStrcat(*buf, BAD_CAST "'");
1768 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001769 case XML_SCHEMA_TYPE_GROUP: {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001770 *buf = xmlStrdup(BAD_CAST "model group def.");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001771 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001772 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001773 *buf = xmlStrcat(*buf, BAD_CAST "'");
1774 FREE_AND_NULL(str)
1775 }
1776 break;
1777 case XML_SCHEMA_TYPE_SEQUENCE:
1778 case XML_SCHEMA_TYPE_CHOICE:
1779 case XML_SCHEMA_TYPE_ALL:
1780 case XML_SCHEMA_TYPE_PARTICLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001781 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1782 break;
1783 case XML_SCHEMA_TYPE_NOTATION: {
1784 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1785 *buf = xmlStrcat(*buf, BAD_CAST " '");
1786 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1787 *buf = xmlStrcat(*buf, BAD_CAST "'");
1788 FREE_AND_NULL(str);
1789 }
J. Peter Mugaasd2c329a2017-10-21 13:49:31 +02001790 /* Falls through. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001791 default:
1792 named = 0;
1793 }
Daniel Veillarddee23482008-04-11 12:58:43 +00001794 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001795 named = 0;
1796
1797 if ((named == 0) && (itemNode != NULL)) {
1798 xmlNodePtr elem;
1799
1800 if (itemNode->type == XML_ATTRIBUTE_NODE)
1801 elem = itemNode->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00001802 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001803 elem = itemNode;
1804 *buf = xmlStrdup(BAD_CAST "Element '");
1805 if (elem->ns != NULL) {
1806 *buf = xmlStrcat(*buf,
1807 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1808 FREE_AND_NULL(str)
1809 } else
1810 *buf = xmlStrcat(*buf, elem->name);
1811 *buf = xmlStrcat(*buf, BAD_CAST "'");
Daniel Veillarddee23482008-04-11 12:58:43 +00001812
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001813 }
1814 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1815 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1816 if (itemNode->ns != NULL) {
1817 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1818 itemNode->ns->href, itemNode->name));
1819 FREE_AND_NULL(str)
1820 } else
1821 *buf = xmlStrcat(*buf, itemNode->name);
1822 *buf = xmlStrcat(*buf, BAD_CAST "'");
1823 }
1824 FREE_AND_NULL(str)
Daniel Veillarddee23482008-04-11 12:58:43 +00001825
David Kilzer502f6a62016-05-23 14:58:41 +08001826 return (xmlEscapeFormatString(buf));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001827}
1828
1829/**
1830 * xmlSchemaFormatFacetEnumSet:
1831 * @buf: the string buffer
1832 * @type: the type holding the enumeration facets
1833 *
1834 * Builds a string consisting of all enumeration elements.
1835 *
1836 * Returns a string of all enumeration elements.
1837 */
1838static const xmlChar *
1839xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1840 xmlChar **buf, xmlSchemaTypePtr type)
1841{
1842 xmlSchemaFacetPtr facet;
1843 xmlSchemaWhitespaceValueType ws;
1844 xmlChar *value = NULL;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001845 int res, found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001846
1847 if (*buf != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00001848 xmlFree(*buf);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001849 *buf = NULL;
1850
1851 do {
1852 /*
1853 * Use the whitespace type of the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +00001854 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001855 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1856 for (facet = type->facets; facet != NULL; facet = facet->next) {
1857 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1858 continue;
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001859 found = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001860 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1861 ws, &value);
1862 if (res == -1) {
1863 xmlSchemaInternalErr(actxt,
1864 "xmlSchemaFormatFacetEnumSet",
1865 "compute the canonical lexical representation");
1866 if (*buf != NULL)
1867 xmlFree(*buf);
1868 *buf = NULL;
1869 return (NULL);
1870 }
1871 if (*buf == NULL)
1872 *buf = xmlStrdup(BAD_CAST "'");
1873 else
1874 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1875 *buf = xmlStrcat(*buf, BAD_CAST value);
1876 *buf = xmlStrcat(*buf, BAD_CAST "'");
1877 if (value != NULL) {
1878 xmlFree((xmlChar *)value);
1879 value = NULL;
1880 }
1881 }
Kasimier T. Buchcikb63d2fa2006-04-19 11:20:49 +00001882 /*
1883 * The enumeration facet of a type restricts the enumeration
1884 * facet of the ancestor type; i.e., such restricted enumerations
1885 * do not belong to the set of the given type. Thus we break
1886 * on the first found enumeration.
1887 */
1888 if (found)
1889 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001890 type = type->baseType;
1891 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1892
1893 return ((const xmlChar *) *buf);
1894}
1895
1896/************************************************************************
1897 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001898 * Error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001899 * *
1900 ************************************************************************/
1901
1902#if 0
1903static void
1904xmlSchemaErrMemory(const char *msg)
1905{
1906 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1907 msg);
1908}
1909#endif
1910
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00001911static void
1912xmlSchemaPSimpleErr(const char *msg)
1913{
1914 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1915 msg);
1916}
1917
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001918/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001919 * xmlSchemaPErrMemory:
1920 * @node: a context node
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001921 * @extra: extra information
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001922 *
1923 * Handle an out of memory condition
1924 */
1925static void
1926xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1927 const char *extra, xmlNodePtr node)
1928{
1929 if (ctxt != NULL)
1930 ctxt->nberrors++;
1931 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1932 extra);
1933}
1934
1935/**
1936 * xmlSchemaPErr:
1937 * @ctxt: the parsing context
1938 * @node: the context node
1939 * @error: the error code
1940 * @msg: the error message
1941 * @str1: extra data
1942 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001943 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001944 * Handle a parser error
1945 */
David Kilzer4472c3a2016-05-13 15:13:17 +08001946static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1948 const char *msg, const xmlChar * str1, const xmlChar * str2)
1949{
1950 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001951 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 void *data = NULL;
1953
1954 if (ctxt != NULL) {
1955 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00001956 ctxt->err = error;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001957 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00001958 data = ctxt->errCtxt;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001959 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001960 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001961 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001962 error, XML_ERR_ERROR, NULL, 0,
1963 (const char *) str1, (const char *) str2, NULL, 0, 0,
1964 msg, str1, str2);
1965}
1966
1967/**
1968 * xmlSchemaPErr2:
1969 * @ctxt: the parsing context
1970 * @node: the context node
1971 * @node: the current child
1972 * @error: the error code
1973 * @msg: the error message
1974 * @str1: extra data
1975 * @str2: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00001976 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001977 * Handle a parser error
1978 */
David Kilzer4472c3a2016-05-13 15:13:17 +08001979static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001980xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1981 xmlNodePtr child, int error,
1982 const char *msg, const xmlChar * str1, const xmlChar * str2)
1983{
1984 if (child != NULL)
1985 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1986 else
1987 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1988}
1989
Daniel Veillard01fa6152004-06-29 17:04:39 +00001990
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001991/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001992 * xmlSchemaPErrExt:
1993 * @ctxt: the parsing context
1994 * @node: the context node
Daniel Veillarddee23482008-04-11 12:58:43 +00001995 * @error: the error code
Daniel Veillard3646d642004-06-02 19:19:14 +00001996 * @strData1: extra data
1997 * @strData2: extra data
1998 * @strData3: extra data
1999 * @msg: the message
2000 * @str1: extra parameter for the message display
2001 * @str2: extra parameter for the message display
2002 * @str3: extra parameter for the message display
2003 * @str4: extra parameter for the message display
2004 * @str5: extra parameter for the message display
Daniel Veillarddee23482008-04-11 12:58:43 +00002005 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002006 * Handle a parser error
2007 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002008static void LIBXML_ATTR_FORMAT(7,0)
Daniel Veillard3646d642004-06-02 19:19:14 +00002009xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
Daniel Veillarddee23482008-04-11 12:58:43 +00002010 const xmlChar * strData1, const xmlChar * strData2,
2011 const xmlChar * strData3, const char *msg, const xmlChar * str1,
Daniel Veillard3646d642004-06-02 19:19:14 +00002012 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2013 const xmlChar * str5)
2014{
2015
2016 xmlGenericErrorFunc channel = NULL;
2017 xmlStructuredErrorFunc schannel = NULL;
2018 void *data = NULL;
2019
2020 if (ctxt != NULL) {
2021 ctxt->nberrors++;
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00002022 ctxt->err = error;
Daniel Veillard3646d642004-06-02 19:19:14 +00002023 channel = ctxt->error;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002024 data = ctxt->errCtxt;
Daniel Veillard3646d642004-06-02 19:19:14 +00002025 schannel = ctxt->serror;
2026 }
2027 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2028 error, XML_ERR_ERROR, NULL, 0,
Daniel Veillarddee23482008-04-11 12:58:43 +00002029 (const char *) strData1, (const char *) strData2,
2030 (const char *) strData3, 0, 0, msg, str1, str2,
William M. Brack803812b2004-06-03 02:11:24 +00002031 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00002032}
Daniel Veillard01fa6152004-06-29 17:04:39 +00002033
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002034/************************************************************************
2035 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002036 * Allround error functions *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002037 * *
2038 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00002039
2040/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002041 * xmlSchemaVTypeErrMemory:
2042 * @node: a context node
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002043 * @extra: extra information
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002044 *
2045 * Handle an out of memory condition
2046 */
2047static void
2048xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2049 const char *extra, xmlNodePtr node)
2050{
2051 if (ctxt != NULL) {
2052 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002053 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002054 }
2055 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2056 extra);
2057}
2058
David Kilzer4472c3a2016-05-13 15:13:17 +08002059static void LIBXML_ATTR_FORMAT(2,0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002060xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2061 const char *msg, const xmlChar *str)
2062{
2063 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2064 msg, (const char *) str);
2065}
2066
2067#define WXS_ERROR_TYPE_ERROR 1
2068#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002069/**
David Kilzer4472c3a2016-05-13 15:13:17 +08002070 * xmlSchemaErr4Line:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002071 * @ctxt: the validation context
David Kilzer4472c3a2016-05-13 15:13:17 +08002072 * @errorLevel: the error level
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002073 * @error: the error code
David Kilzer4472c3a2016-05-13 15:13:17 +08002074 * @node: the context node
2075 * @line: the line number
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002076 * @msg: the error message
2077 * @str1: extra data
2078 * @str2: extra data
2079 * @str3: extra data
David Kilzer4472c3a2016-05-13 15:13:17 +08002080 * @str4: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002081 *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082 * Handle a validation error
2083 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002084static void LIBXML_ATTR_FORMAT(6,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002085xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002086 xmlErrorLevel errorLevel,
2087 int error, xmlNodePtr node, int line, const char *msg,
2088 const xmlChar *str1, const xmlChar *str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002089 const xmlChar *str3, const xmlChar *str4)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090{
Daniel Veillard659e71e2003-10-10 14:10:40 +00002091 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002092 xmlGenericErrorFunc channel = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002093 void *data = NULL;
2094
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002095 if (ctxt != NULL) {
2096 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2097 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00002098 const char *file = NULL;
Juergen Keild201e712014-08-07 11:42:07 +08002099 int col = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002100 if (errorLevel != XML_ERR_WARNING) {
2101 vctxt->nberrors++;
2102 vctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002103 channel = vctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002104 } else {
2105 channel = vctxt->warning;
2106 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002107 schannel = vctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002108 data = vctxt->errCtxt;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002109
2110 /*
2111 * Error node. If we specify a line number, then
2112 * do not channel any node to the error function.
2113 */
2114 if (line == 0) {
2115 if ((node == NULL) &&
2116 (vctxt->depth >= 0) &&
2117 (vctxt->inode != NULL)) {
2118 node = vctxt->inode->node;
2119 }
2120 /*
2121 * Get filename and line if no node-tree.
2122 */
2123 if ((node == NULL) &&
2124 (vctxt->parserCtxt != NULL) &&
2125 (vctxt->parserCtxt->input != NULL)) {
2126 file = vctxt->parserCtxt->input->filename;
2127 line = vctxt->parserCtxt->input->line;
Juergen Keild201e712014-08-07 11:42:07 +08002128 col = vctxt->parserCtxt->input->col;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002129 }
2130 } else {
2131 /*
2132 * Override the given node's (if any) position
2133 * and channel only the given line number.
2134 */
2135 node = NULL;
2136 /*
2137 * Get filename.
2138 */
2139 if (vctxt->doc != NULL)
2140 file = (const char *) vctxt->doc->URL;
2141 else if ((vctxt->parserCtxt != NULL) &&
2142 (vctxt->parserCtxt->input != NULL))
2143 file = vctxt->parserCtxt->input->filename;
Daniel Veillarddee23482008-04-11 12:58:43 +00002144 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08002145 if (vctxt->locFunc != NULL) {
2146 if ((file == NULL) || (line == 0)) {
2147 unsigned long l;
2148 const char *f;
2149 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2150 if (file == NULL)
2151 file = f;
2152 if (line == 0)
2153 line = (int) l;
2154 }
2155 }
2156 if ((file == NULL) && (vctxt->filename != NULL))
2157 file = vctxt->filename;
2158
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 __xmlRaiseError(schannel, channel, data, ctxt,
2160 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002161 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 (const char *) str1, (const char *) str2,
Juergen Keild201e712014-08-07 11:42:07 +08002163 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002164
2165 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2166 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002167 if (errorLevel != XML_ERR_WARNING) {
2168 pctxt->nberrors++;
2169 pctxt->err = error;
Daniel Veillarddee23482008-04-11 12:58:43 +00002170 channel = pctxt->error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002171 } else {
2172 channel = pctxt->warning;
2173 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 schannel = pctxt->serror;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +00002175 data = pctxt->errCtxt;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002177 node, XML_FROM_SCHEMASP, error,
2178 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002179 (const char *) str1, (const char *) str2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002180 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002181 } else {
2182 TODO
2183 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002184 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002185}
2186
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002187/**
2188 * xmlSchemaErr3:
2189 * @ctxt: the validation context
2190 * @node: the context node
2191 * @error: the error code
2192 * @msg: the error message
2193 * @str1: extra data
2194 * @str2: extra data
2195 * @str3: extra data
Daniel Veillarddee23482008-04-11 12:58:43 +00002196 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002197 * Handle a validation error
2198 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002199static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00002200xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002201 int error, xmlNodePtr node, const char *msg,
2202 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2203{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002204 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2205 msg, str1, str2, str3, NULL);
2206}
2207
David Kilzer4472c3a2016-05-13 15:13:17 +08002208static void LIBXML_ATTR_FORMAT(4,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00002209xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002210 int error, xmlNodePtr node, const char *msg,
2211 const xmlChar *str1, const xmlChar *str2,
2212 const xmlChar *str3, const xmlChar *str4)
2213{
2214 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2215 msg, str1, str2, str3, str4);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002216}
2217
David Kilzer4472c3a2016-05-13 15:13:17 +08002218static void LIBXML_ATTR_FORMAT(4,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002219xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2220 int error, xmlNodePtr node, const char *msg,
2221 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002222{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002223 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002224}
2225
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226static xmlChar *
2227xmlSchemaFormatNodeForError(xmlChar ** msg,
2228 xmlSchemaAbstractCtxtPtr actxt,
2229 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002230{
2231 xmlChar *str = NULL;
2232
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002233 *msg = NULL;
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002234 if ((node != NULL) &&
2235 (node->type != XML_ELEMENT_NODE) &&
2236 (node->type != XML_ATTRIBUTE_NODE))
2237 {
Daniel Veillarddee23482008-04-11 12:58:43 +00002238 /*
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002239 * Don't try to format other nodes than element and
2240 * attribute nodes.
David Kilzer4472c3a2016-05-13 15:13:17 +08002241 * Play safe and return an empty string.
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00002242 */
2243 *msg = xmlStrdup(BAD_CAST "");
2244 return(*msg);
2245 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 if (node != NULL) {
2247 /*
2248 * Work on tree nodes.
2249 */
2250 if (node->type == XML_ATTRIBUTE_NODE) {
2251 xmlNodePtr elem = node->parent;
Daniel Veillarddee23482008-04-11 12:58:43 +00002252
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002253 *msg = xmlStrdup(BAD_CAST "Element '");
2254 if (elem->ns != NULL)
2255 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2256 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002257 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002258 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2259 NULL, elem->name));
2260 FREE_AND_NULL(str);
2261 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002262 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002263 } else {
2264 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002265 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002266 if (node->ns != NULL)
2267 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2268 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002269 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002270 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2271 NULL, node->name));
2272 FREE_AND_NULL(str);
2273 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2274 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2275 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2276 /*
2277 * Work on node infos.
Daniel Veillarddee23482008-04-11 12:58:43 +00002278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002279 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2280 xmlSchemaNodeInfoPtr ielem =
2281 vctxt->elemInfos[vctxt->depth];
2282
2283 *msg = xmlStrdup(BAD_CAST "Element '");
2284 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2285 ielem->nsName, ielem->localName));
2286 FREE_AND_NULL(str);
2287 *msg = xmlStrcat(*msg, BAD_CAST "', ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002288 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289 } else {
2290 *msg = xmlStrdup(BAD_CAST "Element '");
2291 }
2292 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2293 vctxt->inode->nsName, vctxt->inode->localName));
2294 FREE_AND_NULL(str);
2295 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002296 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
Daniel Veillarddee23482008-04-11 12:58:43 +00002297 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002298 * Hmm, no node while parsing?
2299 * Return an empty string, in case NULL will break something.
2300 */
2301 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002302 } else {
2303 TODO
2304 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305 }
David Kilzer502f6a62016-05-23 14:58:41 +08002306
2307 /*
2308 * xmlSchemaFormatItemForReport() also returns an escaped format
2309 * string, so do this before calling it below (in the future).
2310 */
2311 xmlEscapeFormatString(msg);
2312
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002313 /*
2314 * VAL TODO: The output of the given schema component is currently
2315 * disabled.
2316 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002317#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002318 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2319 *msg = xmlStrcat(*msg, BAD_CAST " [");
2320 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2321 NULL, type, NULL, 0));
2322 FREE_AND_NULL(str)
2323 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002324 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002325#endif
2326 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002327}
2328
David Kilzer4472c3a2016-05-13 15:13:17 +08002329static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002330xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002331 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002332 const char *message,
2333 const xmlChar *str1,
2334 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002336 xmlChar *msg = NULL;
2337
Daniel Veillard14b56432006-03-09 18:41:40 +00002338 if (actxt == NULL)
2339 return;
David Kilzer4472c3a2016-05-13 15:13:17 +08002340 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002341 msg = xmlStrcat(msg, BAD_CAST message);
2342 msg = xmlStrcat(msg, BAD_CAST ".\n");
2343
2344 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
David Kilzer4472c3a2016-05-13 15:13:17 +08002345 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2346 (const char *) msg, (const xmlChar *) funcName, str1, str2);
Daniel Veillarddee23482008-04-11 12:58:43 +00002347 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
David Kilzer4472c3a2016-05-13 15:13:17 +08002348 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2349 (const char *) msg, (const xmlChar *) funcName, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350
2351 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002352}
2353
David Kilzer4472c3a2016-05-13 15:13:17 +08002354static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002355xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2356 const char *funcName,
2357 const char *message)
2358{
2359 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2360}
2361
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002362#if 0
David Kilzer4472c3a2016-05-13 15:13:17 +08002363static void LIBXML_ATTR_FORMAT(3,0)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002364xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2365 const char *funcName,
2366 const char *message,
2367 const xmlChar *str1,
2368 const xmlChar *str2)
2369{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002370 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002371 str1, str2);
2372}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002373#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00002374
David Kilzer4472c3a2016-05-13 15:13:17 +08002375static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002376xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2377 xmlParserErrors error,
2378 xmlNodePtr node,
2379 xmlSchemaBasicItemPtr item,
2380 const char *message,
2381 const xmlChar *str1, const xmlChar *str2,
2382 const xmlChar *str3, const xmlChar *str4)
2383{
2384 xmlChar *msg = NULL;
2385
2386 if ((node == NULL) && (item != NULL) &&
2387 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2388 node = WXS_ITEM_NODE(item);
2389 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2390 msg = xmlStrcat(msg, BAD_CAST ": ");
2391 } else
2392 xmlSchemaFormatNodeForError(&msg, actxt, node);
2393 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002394 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002395 xmlSchemaErr4(actxt, error, node,
2396 (const char *) msg, str1, str2, str3, str4);
2397 FREE_AND_NULL(msg)
2398}
2399
David Kilzer4472c3a2016-05-13 15:13:17 +08002400static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002401xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2402 xmlParserErrors error,
2403 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002404 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002405 const char *message,
2406 const xmlChar *str1,
2407 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002408{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002409 xmlSchemaCustomErr4(actxt, error, node, item,
Daniel Veillarddee23482008-04-11 12:58:43 +00002410 message, str1, str2, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002411}
2412
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002413
2414
David Kilzer4472c3a2016-05-13 15:13:17 +08002415static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002416xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2417 xmlParserErrors error,
2418 xmlNodePtr node,
2419 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2420 const char *message,
2421 const xmlChar *str1,
2422 const xmlChar *str2,
2423 const xmlChar *str3)
2424{
2425 xmlChar *msg = NULL;
2426
2427 xmlSchemaFormatNodeForError(&msg, actxt, node);
2428 msg = xmlStrcat(msg, (const xmlChar *) message);
Daniel Veillarddee23482008-04-11 12:58:43 +00002429 msg = xmlStrcat(msg, BAD_CAST ".\n");
2430
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002431 /* URGENT TODO: Set the error code to something sane. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002432 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2433 (const char *) msg, str1, str2, str3, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002434
2435 FREE_AND_NULL(msg)
2436}
2437
2438
2439
David Kilzer4472c3a2016-05-13 15:13:17 +08002440static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002441xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2442 xmlParserErrors error,
2443 xmlSchemaPSVIIDCNodePtr idcNode,
2444 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2445 const char *message,
2446 const xmlChar *str1,
2447 const xmlChar *str2)
2448{
2449 xmlChar *msg = NULL, *qname = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002450
2451 msg = xmlStrdup(BAD_CAST "Element '%s': ");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002452 msg = xmlStrcat(msg, (const xmlChar *) message);
2453 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002454 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002455 error, NULL, idcNode->nodeLine, (const char *) msg,
2456 xmlSchemaFormatQName(&qname,
2457 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
Daniel Veillarddee23482008-04-11 12:58:43 +00002458 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002459 str1, str2, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002460 FREE_AND_NULL(qname);
2461 FREE_AND_NULL(msg);
2462}
2463
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002464static int
2465xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2466 xmlNodePtr node)
2467{
2468 if (node != NULL)
2469 return (node->type);
2470 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2471 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2472 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2473 return (-1);
2474}
2475
2476static int
2477xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2478{
2479 switch (item->type) {
2480 case XML_SCHEMA_TYPE_COMPLEX:
2481 case XML_SCHEMA_TYPE_SIMPLE:
2482 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2483 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002484 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 case XML_SCHEMA_TYPE_GROUP:
2486 return (1);
2487 case XML_SCHEMA_TYPE_ELEMENT:
2488 if ( ((xmlSchemaElementPtr) item)->flags &
2489 XML_SCHEMAS_ELEM_GLOBAL)
2490 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002491 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002492 case XML_SCHEMA_TYPE_ATTRIBUTE:
2493 if ( ((xmlSchemaAttributePtr) item)->flags &
2494 XML_SCHEMAS_ATTR_GLOBAL)
2495 return(1);
2496 break;
2497 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002498 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002499 return(1);
2500 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002501 return (0);
2502}
2503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002504static void
2505xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2506 xmlParserErrors error,
2507 xmlNodePtr node,
2508 const xmlChar *value,
2509 xmlSchemaTypePtr type,
2510 int displayValue)
2511{
2512 xmlChar *msg = NULL;
2513
2514 xmlSchemaFormatNodeForError(&msg, actxt, node);
2515
2516 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2517 XML_ATTRIBUTE_NODE))
2518 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2519 else
2520 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2521 "value of ");
2522
2523 if (! xmlSchemaIsGlobalItem(type))
2524 msg = xmlStrcat(msg, BAD_CAST "the local ");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "the ");
2527
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002528 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002529 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002530 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002531 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002532 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002533 msg = xmlStrcat(msg, BAD_CAST "union type");
2534
2535 if (xmlSchemaIsGlobalItem(type)) {
2536 xmlChar *str = NULL;
2537 msg = xmlStrcat(msg, BAD_CAST " '");
2538 if (type->builtInType != 0) {
2539 msg = xmlStrcat(msg, BAD_CAST "xs:");
David Kilzer502f6a62016-05-23 14:58:41 +08002540 str = xmlStrdup(type->name);
2541 } else {
2542 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2543 if (!str)
2544 str = xmlStrdup(qName);
2545 }
2546 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002547 msg = xmlStrcat(msg, BAD_CAST "'");
2548 FREE_AND_NULL(str);
2549 }
2550 msg = xmlStrcat(msg, BAD_CAST ".\n");
2551 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2552 XML_ATTRIBUTE_NODE))
2553 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2554 else
2555 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2556 FREE_AND_NULL(msg)
2557}
2558
Daniel Veillardc0826a72004-08-10 14:17:33 +00002559static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002560xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2561 xmlSchemaNodeInfoPtr ni,
2562 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002563{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002564 if (node != NULL) {
2565 if (node->ns != NULL)
2566 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2567 else
2568 return (xmlSchemaFormatQName(str, NULL, node->name));
2569 } else if (ni != NULL)
2570 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2571 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572}
2573
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2576 xmlParserErrors error,
2577 xmlSchemaAttrInfoPtr ni,
2578 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlChar *msg = NULL, *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002581
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002582 xmlSchemaFormatNodeForError(&msg, actxt, node);
2583 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2584 xmlSchemaErr(actxt, error, node, (const char *) msg,
2585 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
Daniel Veillarddee23482008-04-11 12:58:43 +00002586 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002588 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002589}
2590
David Kilzer4472c3a2016-05-13 15:13:17 +08002591static void LIBXML_ATTR_FORMAT(5,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002592xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2593 xmlParserErrors error,
2594 xmlNodePtr node,
2595 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002596 const char *message,
2597 int nbval,
2598 int nbneg,
2599 xmlChar **values)
2600{
2601 xmlChar *str = NULL, *msg = NULL;
2602 xmlChar *localName, *nsName;
2603 const xmlChar *cur, *end;
Daniel Veillard6a0baa02005-12-10 11:11:12 +00002604 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00002605
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002606 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002607 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002608 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002609 /*
2610 * Note that is does not make sense to report that we have a
2611 * wildcard here, since the wildcard might be unfolded into
2612 * multiple transitions.
2613 */
2614 if (nbval + nbneg > 0) {
2615 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002616 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002617 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002618 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002619 nsName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002620
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002621 for (i = 0; i < nbval + nbneg; i++) {
2622 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002623 if (cur == NULL)
2624 continue;
2625 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2626 (cur[3] == ' ')) {
Daniel Veillard77005e62005-07-19 16:26:18 +00002627 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002628 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002629 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002630 /*
2631 * Get the local name.
2632 */
2633 localName = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00002634
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002635 end = cur;
2636 if (*end == '*') {
2637 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002638 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002639 } else {
2640 while ((*end != 0) && (*end != '|'))
2641 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002642 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Daniel Veillarddee23482008-04-11 12:58:43 +00002643 }
2644 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002645 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002646 /*
2647 * Skip "*|*" if they come with negated expressions, since
2648 * they represent the same negated wildcard.
2649 */
2650 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2651 /*
2652 * Get the namespace name.
2653 */
2654 cur = end;
2655 if (*end == '*') {
2656 nsName = xmlStrdup(BAD_CAST "{*}");
2657 } else {
2658 while (*end != 0)
2659 end++;
Daniel Veillarddee23482008-04-11 12:58:43 +00002660
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002661 if (i >= nbval)
2662 nsName = xmlStrdup(BAD_CAST "{##other:");
2663 else
2664 nsName = xmlStrdup(BAD_CAST "{");
Daniel Veillarddee23482008-04-11 12:58:43 +00002665
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002666 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2667 nsName = xmlStrcat(nsName, BAD_CAST "}");
2668 }
2669 str = xmlStrcat(str, BAD_CAST nsName);
2670 FREE_AND_NULL(nsName)
2671 } else {
2672 FREE_AND_NULL(localName);
2673 continue;
2674 }
Daniel Veillarddee23482008-04-11 12:58:43 +00002675 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002676 str = xmlStrcat(str, BAD_CAST localName);
2677 FREE_AND_NULL(localName);
Daniel Veillarddee23482008-04-11 12:58:43 +00002678
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002679 if (i < nbval + nbneg -1)
2680 str = xmlStrcat(str, BAD_CAST ", ");
Daniel Veillarddee23482008-04-11 12:58:43 +00002681 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002682 str = xmlStrcat(str, BAD_CAST " ).\n");
David Kilzer502f6a62016-05-23 14:58:41 +08002683 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002684 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002685 } else
2686 msg = xmlStrcat(msg, BAD_CAST "\n");
2687 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002688 xmlFree(msg);
2689}
2690
David Kilzer4472c3a2016-05-13 15:13:17 +08002691static void LIBXML_ATTR_FORMAT(8,0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002692xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2693 xmlParserErrors error,
2694 xmlNodePtr node,
2695 const xmlChar *value,
2696 unsigned long length,
2697 xmlSchemaTypePtr type,
2698 xmlSchemaFacetPtr facet,
2699 const char *message,
2700 const xmlChar *str1,
2701 const xmlChar *str2)
2702{
2703 xmlChar *str = NULL, *msg = NULL;
2704 xmlSchemaTypeType facetType;
2705 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2706
2707 xmlSchemaFormatNodeForError(&msg, actxt, node);
2708 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2709 facetType = XML_SCHEMA_FACET_ENUMERATION;
2710 /*
2711 * If enumerations are validated, one must not expect the
2712 * facet to be given.
Daniel Veillarddee23482008-04-11 12:58:43 +00002713 */
2714 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002715 facetType = facet->type;
2716 msg = xmlStrcat(msg, BAD_CAST "[");
2717 msg = xmlStrcat(msg, BAD_CAST "facet '");
2718 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2719 msg = xmlStrcat(msg, BAD_CAST "'] ");
2720 if (message == NULL) {
2721 /*
2722 * Use a default message.
2723 */
2724 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2725 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2726 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2727
2728 char len[25], actLen[25];
2729
2730 /* FIXME, TODO: What is the max expected string length of the
2731 * this value?
2732 */
2733 if (nodeType == XML_ATTRIBUTE_NODE)
2734 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2735 else
2736 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2737
2738 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2739 snprintf(actLen, 24, "%lu", length);
2740
2741 if (facetType == XML_SCHEMA_FACET_LENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002742 msg = xmlStrcat(msg,
2743 BAD_CAST "this differs from the allowed length of '%s'.\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002744 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002745 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002746 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2747 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
Daniel Veillarddee23482008-04-11 12:58:43 +00002748 msg = xmlStrcat(msg,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002749 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002750
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751 if (nodeType == XML_ATTRIBUTE_NODE)
2752 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2753 value, (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002754 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002755 xmlSchemaErr(actxt, error, node, (const char *) msg,
2756 (const xmlChar *) actLen, (const xmlChar *) len);
Daniel Veillarddee23482008-04-11 12:58:43 +00002757
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002758 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2759 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2760 "of the set {%s}.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002761 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002762 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2763 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2764 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2765 "by the pattern '%s'.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002766 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002767 facet->value);
2768 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2769 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2770 "minimum value allowed ('%s').\n");
2771 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2772 facet->value);
2773 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2774 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2775 "maximum value allowed ('%s').\n");
2776 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2777 facet->value);
2778 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002779 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002780 "'%s'.\n");
2781 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2782 facet->value);
2783 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00002784 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 "'%s'.\n");
2786 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2787 facet->value);
2788 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2789 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2790 "digits than are allowed ('%s').\n");
2791 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2792 facet->value);
2793 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2794 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2795 "digits than are allowed ('%s').\n");
2796 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2797 facet->value);
Daniel Veillarddee23482008-04-11 12:58:43 +00002798 } else if (nodeType == XML_ATTRIBUTE_NODE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00002800 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2801 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002802 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2803 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2804 }
2805 } else {
2806 msg = xmlStrcat(msg, (const xmlChar *) message);
2807 msg = xmlStrcat(msg, BAD_CAST ".\n");
2808 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
Daniel Veillarddee23482008-04-11 12:58:43 +00002809 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002810 FREE_AND_NULL(str)
2811 xmlFree(msg);
2812}
2813
2814#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002815 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002816
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002817#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002818
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002819#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2820#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002821
2822#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2823
2824
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002825/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002826 * xmlSchemaPMissingAttrErr:
2827 * @ctxt: the schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002828 * @ownerItem: the owner as a schema object
2829 * @ownerElem: the owner as an element node
2830 * @node: the parent element node of the missing attribute node
2831 * @type: the corresponding type of the attribute node
2832 *
2833 * Reports an illegal attribute.
2834 */
2835static void
2836xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002837 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002838 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839 xmlNodePtr ownerElem,
2840 const char *name,
2841 const char *message)
2842{
2843 xmlChar *des = NULL;
2844
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002845 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2846
Daniel Veillardc0826a72004-08-10 14:17:33 +00002847 if (message != NULL)
2848 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002849 else
2850 xmlSchemaPErr(ctxt, ownerElem, error,
2851 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002852 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002853 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002854}
2855
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002856
Daniel Veillardc0826a72004-08-10 14:17:33 +00002857/**
2858 * xmlSchemaPResCompAttrErr:
2859 * @ctxt: the schema validation context
2860 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002861 * @ownerItem: the owner as a schema object
2862 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002863 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002864 * @refName: the referenced local name
2865 * @refURI: the referenced namespace URI
2866 * @message: optional message
2867 *
2868 * Used to report QName attribute values that failed to resolve
2869 * to schema components.
2870 */
2871static void
2872xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002873 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002874 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002875 xmlNodePtr ownerElem,
2876 const char *name,
2877 const xmlChar *refName,
2878 const xmlChar *refURI,
2879 xmlSchemaTypeType refType,
2880 const char *refTypeStr)
2881{
2882 xmlChar *des = NULL, *strA = NULL;
2883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002884 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002885 if (refTypeStr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002886 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
Nick Wellnhofer359e7502017-11-13 21:13:46 +01002887 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002888 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002889 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2890 "%s.\n", BAD_CAST des, BAD_CAST name,
2891 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002892 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002893 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002894 FREE_AND_NULL(strA)
2895}
2896
William M. Brack2f2a6632004-08-20 23:09:47 +00002897/**
2898 * xmlSchemaPCustomAttrErr:
2899 * @ctxt: the schema parser context
2900 * @error: the error code
2901 * @ownerDes: the designation of the owner
2902 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002903 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002904 *
2905 * Reports an illegal attribute during the parse.
2906 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002907static void
2908xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002909 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002910 xmlChar **ownerDes,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002911 xmlSchemaBasicItemPtr ownerItem,
William M. Brack2f2a6632004-08-20 23:09:47 +00002912 xmlAttrPtr attr,
2913 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002914{
2915 xmlChar *des = NULL;
2916
2917 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002918 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002919 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002920 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002921 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002922 } else
2923 des = *ownerDes;
Daniel Veillard14b56432006-03-09 18:41:40 +00002924 if (attr == NULL) {
2925 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2926 "%s, attribute '%s': %s.\n",
Daniel Veillardaac7c682006-03-10 13:40:16 +00002927 BAD_CAST des, (const xmlChar *) "Unknown",
2928 (const xmlChar *) msg, NULL, NULL);
Daniel Veillard14b56432006-03-09 18:41:40 +00002929 } else {
2930 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2931 "%s, attribute '%s': %s.\n",
2932 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2933 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002934 if (ownerDes == NULL)
2935 FREE_AND_NULL(des);
2936}
2937
2938/**
2939 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002940 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002941 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002942 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002944 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002945 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002946 */
2947static void
2948xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002949 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002950 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002951 xmlAttrPtr attr)
2952{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002953 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002954
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002955 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2956 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2957 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2958 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2959 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002960 FREE_AND_NULL(strA);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002961 FREE_AND_NULL(strB);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002962}
2963
William M. Brack2f2a6632004-08-20 23:09:47 +00002964/**
2965 * xmlSchemaPCustomErr:
2966 * @ctxt: the schema parser context
2967 * @error: the error code
2968 * @itemDes: the designation of the schema item
2969 * @item: the schema item
2970 * @itemElem: the node of the schema item
2971 * @message: the error message
2972 * @str1: an optional param for the error message
2973 * @str2: an optional param for the error message
2974 * @str3: an optional param for the error message
2975 *
2976 * Reports an error during parsing.
2977 */
David Kilzer4472c3a2016-05-13 15:13:17 +08002978static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002979xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002980 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002981 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002982 xmlNodePtr itemElem,
2983 const char *message,
2984 const xmlChar *str1,
2985 const xmlChar *str2,
2986 const xmlChar *str3)
2987{
2988 xmlChar *des = NULL, *msg = NULL;
2989
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002990 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002991 msg = xmlStrdup(BAD_CAST "%s: ");
2992 msg = xmlStrcat(msg, (const xmlChar *) message);
2993 msg = xmlStrcat(msg, BAD_CAST ".\n");
2994 if ((itemElem == NULL) && (item != NULL))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002995 itemElem = WXS_ITEM_NODE(item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002996 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002997 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00002998 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002999 FREE_AND_NULL(msg);
3000}
3001
William M. Brack2f2a6632004-08-20 23:09:47 +00003002/**
3003 * xmlSchemaPCustomErr:
3004 * @ctxt: the schema parser context
3005 * @error: the error code
3006 * @itemDes: the designation of the schema item
3007 * @item: the schema item
3008 * @itemElem: the node of the schema item
3009 * @message: the error message
3010 * @str1: the optional param for the error message
3011 *
3012 * Reports an error during parsing.
3013 */
David Kilzer4472c3a2016-05-13 15:13:17 +08003014static void LIBXML_ATTR_FORMAT(5,0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003015xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003016 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003017 xmlSchemaBasicItemPtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003018 xmlNodePtr itemElem,
3019 const char *message,
3020 const xmlChar *str1)
3021{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003022 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003023 str1, NULL, NULL);
3024}
3025
William M. Brack2f2a6632004-08-20 23:09:47 +00003026/**
3027 * xmlSchemaPAttrUseErr:
3028 * @ctxt: the schema parser context
3029 * @error: the error code
3030 * @itemDes: the designation of the schema type
3031 * @item: the schema type
3032 * @itemElem: the node of the schema type
3033 * @attr: the invalid schema attribute
3034 * @message: the error message
3035 * @str1: the optional param for the error message
3036 *
3037 * Reports an attribute use error during parsing.
3038 */
David Kilzer4472c3a2016-05-13 15:13:17 +08003039static void LIBXML_ATTR_FORMAT(6,0)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003040xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003041 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003042 xmlNodePtr node,
3043 xmlSchemaBasicItemPtr ownerItem,
3044 const xmlSchemaAttributeUsePtr attruse,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003045 const char *message,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003046 const xmlChar *str1, const xmlChar *str2,
3047 const xmlChar *str3,const xmlChar *str4)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003048{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003049 xmlChar *str = NULL, *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00003050
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003051 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003052 msg = xmlStrcat(msg, BAD_CAST ", ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003053 msg = xmlStrcat(msg,
3054 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003055 WXS_BASIC_CAST attruse, NULL));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003056 FREE_AND_NULL(str);
3057 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003058 msg = xmlStrcat(msg, (const xmlChar *) message);
3059 msg = xmlStrcat(msg, BAD_CAST ".\n");
Daniel Veillarddee23482008-04-11 12:58:43 +00003060 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003061 (const char *) msg, str1, str2, str3, str4);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003062 xmlFree(msg);
3063}
3064
William M. Brack2f2a6632004-08-20 23:09:47 +00003065/**
3066 * xmlSchemaPIllegalFacetAtomicErr:
3067 * @ctxt: the schema parser context
3068 * @error: the error code
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003069 * @type: the schema type
3070 * @baseType: the base type of type
William M. Brack2f2a6632004-08-20 23:09:47 +00003071 * @facet: the illegal facet
3072 *
3073 * Reports an illegal facet for atomic simple types.
3074 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003075static void
3076xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003077 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003078 xmlSchemaTypePtr type,
3079 xmlSchemaTypePtr baseType,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003080 xmlSchemaFacetPtr facet)
3081{
3082 xmlChar *des = NULL, *strT = NULL;
3083
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003084 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3085 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003086 "%s: The facet '%s' is not allowed on types derived from the "
3087 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003088 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003089 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00003090 NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003091 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003092 FREE_AND_NULL(strT);
3093}
3094
William M. Brack2f2a6632004-08-20 23:09:47 +00003095/**
3096 * xmlSchemaPIllegalFacetListUnionErr:
3097 * @ctxt: the schema parser context
3098 * @error: the error code
3099 * @itemDes: the designation of the schema item involved
3100 * @item: the schema item involved
3101 * @facet: the illegal facet
3102 *
3103 * Reports an illegal facet for <list> and <union>.
3104 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003105static void
3106xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003107 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003108 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003109 xmlSchemaFacetPtr facet)
3110{
Daniel Veillardb2947172006-03-27 09:45:01 +00003111 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003112
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003113 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3114 type->node);
3115 xmlSchemaPErr(ctxt, type->node, error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003116 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003117 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003118 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003119}
3120
3121/**
3122 * xmlSchemaPMutualExclAttrErr:
3123 * @ctxt: the schema validation context
3124 * @error: the error code
3125 * @elemDes: the designation of the parent element node
3126 * @attr: the bad attribute node
3127 * @type: the corresponding type of the attribute node
3128 *
3129 * Reports an illegal attribute.
3130 */
3131static void
3132xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3133 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003134 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003135 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003136 const char *name1,
3137 const char *name2)
3138{
3139 xmlChar *des = NULL;
3140
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003141 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003142 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003143 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003144 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003145 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003146}
3147
3148/**
3149 * xmlSchemaPSimpleTypeErr:
3150 * @ctxt: the schema validation context
3151 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003152 * @type: the type specifier
Daniel Veillarddee23482008-04-11 12:58:43 +00003153 * @ownerItem: the schema object if existent
Daniel Veillardc0826a72004-08-10 14:17:33 +00003154 * @node: the validated node
3155 * @value: the validated value
3156 *
3157 * Reports a simple type validation error.
3158 * TODO: Should this report the value of an element as well?
3159 */
David Kilzer4472c3a2016-05-13 15:13:17 +08003160static void LIBXML_ATTR_FORMAT(8,0)
Daniel Veillarddee23482008-04-11 12:58:43 +00003161xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003162 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003163 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003164 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00003165 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003166 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003167 const xmlChar *value,
3168 const char *message,
3169 const xmlChar *str1,
3170 const xmlChar *str2)
3171{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003172 xmlChar *msg = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00003173
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003174 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003175 if (message == NULL) {
3176 /*
3177 * Use default messages.
Daniel Veillarddee23482008-04-11 12:58:43 +00003178 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003179 if (type != NULL) {
3180 if (node->type == XML_ATTRIBUTE_NODE)
3181 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3182 else
3183 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
Daniel Veillarddee23482008-04-11 12:58:43 +00003184 "valid value of ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003185 if (! xmlSchemaIsGlobalItem(type))
3186 msg = xmlStrcat(msg, BAD_CAST "the local ");
3187 else
3188 msg = xmlStrcat(msg, BAD_CAST "the ");
Daniel Veillarddee23482008-04-11 12:58:43 +00003189
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003190 if (WXS_IS_ATOMIC(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003191 msg = xmlStrcat(msg, BAD_CAST "atomic type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003192 else if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003193 msg = xmlStrcat(msg, BAD_CAST "list type");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003194 else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003195 msg = xmlStrcat(msg, BAD_CAST "union type");
Daniel Veillarddee23482008-04-11 12:58:43 +00003196
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003197 if (xmlSchemaIsGlobalItem(type)) {
3198 xmlChar *str = NULL;
3199 msg = xmlStrcat(msg, BAD_CAST " '");
3200 if (type->builtInType != 0) {
3201 msg = xmlStrcat(msg, BAD_CAST "xs:");
David Kilzer502f6a62016-05-23 14:58:41 +08003202 str = xmlStrdup(type->name);
3203 } else {
3204 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3205 if (!str)
3206 str = xmlStrdup(qName);
3207 }
3208 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003209 msg = xmlStrcat(msg, BAD_CAST "'.");
3210 FREE_AND_NULL(str);
3211 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003212 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003213 if (node->type == XML_ATTRIBUTE_NODE)
3214 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3215 else
3216 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3217 "valid.");
Daniel Veillarddee23482008-04-11 12:58:43 +00003218 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003219 if (expected) {
David Kilzer502f6a62016-05-23 14:58:41 +08003220 xmlChar *expectedEscaped = xmlCharStrdup(expected);
Chun-wei Fand77e5fc2016-05-31 21:04:50 +08003221 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
David Kilzer502f6a62016-05-23 14:58:41 +08003222 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3223 FREE_AND_NULL(expectedEscaped);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003224 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3225 } else
3226 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00003227 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003228 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3229 else
3230 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3231 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003232 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003233 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003234 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00003235 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003236 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003237 /* Cleanup. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003238 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003239}
3240
William M. Brack2f2a6632004-08-20 23:09:47 +00003241/**
3242 * xmlSchemaPContentErr:
3243 * @ctxt: the schema parser context
3244 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 * @ownerItem: the owner item of the holder of the content
3246 * @ownerElem: the node of the holder of the content
3247 * @child: the invalid child node
3248 * @message: the optional error message
3249 * @content: the optional string describing the correct content
3250 *
3251 * Reports an error concerning the content of a schema element.
3252 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00003253static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003254xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003255 xmlParserErrors error,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003256 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003257 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003258 xmlNodePtr child,
3259 const char *message,
3260 const char *content)
3261{
3262 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003263
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003264 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003265 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003266 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3267 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003268 BAD_CAST des, BAD_CAST message);
3269 else {
3270 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003271 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3272 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003273 BAD_CAST des, BAD_CAST content);
3274 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003275 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3276 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00003277 BAD_CAST des, NULL);
3278 }
3279 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003280 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003281}
3282
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003283/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003284 * *
3285 * Streamable error functions *
3286 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003287 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00003288
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003289
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003290
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003291
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003292/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003293 * *
3294 * Validation helper functions *
3295 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003296 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00003297
Daniel Veillardc0826a72004-08-10 14:17:33 +00003298
Daniel Veillard4255d502002-04-16 15:50:10 +00003299/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08003300 * *
3301 * Allocation functions *
3302 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003303 ************************************************************************/
3304
3305/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003306 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00003307 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003308 *
3309 * Allocate a new Schema structure.
3310 *
3311 * Returns the newly allocated structure or NULL in case or error
3312 */
3313static xmlSchemaPtr
3314xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3315{
3316 xmlSchemaPtr ret;
3317
3318 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3319 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003320 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003321 return (NULL);
3322 }
3323 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003324 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00003325 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003326
3327 return (ret);
3328}
3329
3330/**
3331 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00003332 *
3333 * Allocate a new Facet structure.
3334 *
3335 * Returns the newly allocated structure or NULL in case or error
3336 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003337xmlSchemaFacetPtr
3338xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00003339{
3340 xmlSchemaFacetPtr ret;
3341
3342 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3343 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003344 return (NULL);
3345 }
3346 memset(ret, 0, sizeof(xmlSchemaFacet));
3347
3348 return (ret);
3349}
3350
3351/**
3352 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00003353 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00003354 * @node: a node
3355 *
3356 * Allocate a new annotation structure.
3357 *
3358 * Returns the newly allocated structure or NULL in case or error
3359 */
3360static xmlSchemaAnnotPtr
3361xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3362{
3363 xmlSchemaAnnotPtr ret;
3364
3365 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3366 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003367 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003368 return (NULL);
3369 }
3370 memset(ret, 0, sizeof(xmlSchemaAnnot));
3371 ret->content = node;
3372 return (ret);
3373}
3374
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003375static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003376xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003377{
3378 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003379
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003380 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3381 if (ret == NULL) {
3382 xmlSchemaPErrMemory(NULL,
3383 "allocating an item list structure", NULL);
3384 return (NULL);
3385 }
3386 memset(ret, 0, sizeof(xmlSchemaItemList));
3387 return (ret);
3388}
3389
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003390static void
3391xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3392{
3393 if (list->items != NULL) {
3394 xmlFree(list->items);
3395 list->items = NULL;
3396 }
3397 list->nbItems = 0;
3398 list->sizeItems = 0;
3399}
3400
3401static int
3402xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3403{
3404 if (list->items == NULL) {
3405 list->items = (void **) xmlMalloc(
3406 20 * sizeof(void *));
3407 if (list->items == NULL) {
3408 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3409 return(-1);
3410 }
3411 list->sizeItems = 20;
3412 } else if (list->sizeItems <= list->nbItems) {
3413 list->sizeItems *= 2;
3414 list->items = (void **) xmlRealloc(list->items,
3415 list->sizeItems * sizeof(void *));
3416 if (list->items == NULL) {
3417 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3418 list->sizeItems = 0;
3419 return(-1);
3420 }
3421 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003422 list->items[list->nbItems++] = item;
3423 return(0);
3424}
3425
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003426static int
3427xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3428 int initialSize,
3429 void *item)
3430{
3431 if (list->items == NULL) {
3432 if (initialSize <= 0)
3433 initialSize = 1;
3434 list->items = (void **) xmlMalloc(
3435 initialSize * sizeof(void *));
3436 if (list->items == NULL) {
3437 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3438 return(-1);
3439 }
3440 list->sizeItems = initialSize;
3441 } else if (list->sizeItems <= list->nbItems) {
3442 list->sizeItems *= 2;
3443 list->items = (void **) xmlRealloc(list->items,
3444 list->sizeItems * sizeof(void *));
3445 if (list->items == NULL) {
3446 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3447 list->sizeItems = 0;
3448 return(-1);
3449 }
3450 }
3451 list->items[list->nbItems++] = item;
3452 return(0);
3453}
3454
3455static int
3456xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003457{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003458 if (list->items == NULL) {
3459 list->items = (void **) xmlMalloc(
3460 20 * sizeof(void *));
3461 if (list->items == NULL) {
3462 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3463 return(-1);
3464 }
3465 list->sizeItems = 20;
3466 } else if (list->sizeItems <= list->nbItems) {
3467 list->sizeItems *= 2;
3468 list->items = (void **) xmlRealloc(list->items,
3469 list->sizeItems * sizeof(void *));
3470 if (list->items == NULL) {
3471 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3472 list->sizeItems = 0;
3473 return(-1);
3474 }
3475 }
3476 /*
3477 * Just append if the index is greater/equal than the item count.
3478 */
3479 if (idx >= list->nbItems) {
3480 list->items[list->nbItems++] = item;
3481 } else {
3482 int i;
3483 for (i = list->nbItems; i > idx; i--)
3484 list->items[i] = list->items[i-1];
3485 list->items[idx] = item;
3486 list->nbItems++;
3487 }
3488 return(0);
3489}
3490
3491#if 0 /* enable if ever needed */
3492static int
3493xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3494 int initialSize,
3495 void *item,
3496 int idx)
Daniel Veillarddee23482008-04-11 12:58:43 +00003497{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003498 if (list->items == NULL) {
3499 if (initialSize <= 0)
3500 initialSize = 1;
3501 list->items = (void **) xmlMalloc(
3502 initialSize * sizeof(void *));
3503 if (list->items == NULL) {
3504 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3505 return(-1);
3506 }
3507 list->sizeItems = initialSize;
3508 } else if (list->sizeItems <= list->nbItems) {
3509 list->sizeItems *= 2;
3510 list->items = (void **) xmlRealloc(list->items,
3511 list->sizeItems * sizeof(void *));
3512 if (list->items == NULL) {
3513 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3514 list->sizeItems = 0;
3515 return(-1);
3516 }
3517 }
3518 /*
3519 * Just append if the index is greater/equal than the item count.
3520 */
3521 if (idx >= list->nbItems) {
3522 list->items[list->nbItems++] = item;
3523 } else {
3524 int i;
3525 for (i = list->nbItems; i > idx; i--)
3526 list->items[i] = list->items[i-1];
3527 list->items[idx] = item;
3528 list->nbItems++;
3529 }
3530 return(0);
3531}
3532#endif
3533
3534static int
3535xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3536{
3537 int i;
3538 if ((list->items == NULL) || (idx >= list->nbItems)) {
3539 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3540 "index error.\n");
3541 return(-1);
3542 }
3543
3544 if (list->nbItems == 1) {
3545 /* TODO: Really free the list? */
3546 xmlFree(list->items);
3547 list->items = NULL;
3548 list->nbItems = 0;
3549 list->sizeItems = 0;
3550 } else if (list->nbItems -1 == idx) {
3551 list->nbItems--;
Daniel Veillarddee23482008-04-11 12:58:43 +00003552 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003553 for (i = idx; i < list->nbItems -1; i++)
3554 list->items[i] = list->items[i+1];
3555 list->nbItems--;
3556 }
3557 return(0);
3558}
3559
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003560/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003561 * xmlSchemaItemListFree:
3562 * @annot: a schema type structure
3563 *
3564 * Deallocate a annotation structure
3565 */
3566static void
3567xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3568{
3569 if (list == NULL)
3570 return;
3571 if (list->items != NULL)
3572 xmlFree(list->items);
3573 xmlFree(list);
3574}
3575
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576static void
3577xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003578{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003579 if (bucket == NULL)
3580 return;
3581 if (bucket->globals != NULL) {
3582 xmlSchemaComponentListFree(bucket->globals);
3583 xmlSchemaItemListFree(bucket->globals);
3584 }
3585 if (bucket->locals != NULL) {
3586 xmlSchemaComponentListFree(bucket->locals);
Daniel Veillarddee23482008-04-11 12:58:43 +00003587 xmlSchemaItemListFree(bucket->locals);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003588 }
3589 if (bucket->relations != NULL) {
3590 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3591 do {
Daniel Veillarddee23482008-04-11 12:58:43 +00003592 prev = cur;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003593 cur = cur->next;
3594 xmlFree(prev);
3595 } while (cur != NULL);
3596 }
3597 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3598 xmlFreeDoc(bucket->doc);
Daniel Veillarddee23482008-04-11 12:58:43 +00003599 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003600 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003601 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3602 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003603 }
3604 xmlFree(bucket);
3605}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003606
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01003607static void
3608xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3609{
3610 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3611}
3612
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003613static xmlSchemaBucketPtr
3614xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003615 int type, const xmlChar *targetNamespace)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003616{
3617 xmlSchemaBucketPtr ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003618 int size;
3619 xmlSchemaPtr mainSchema;
3620
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003621 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003622 PERROR_INT("xmlSchemaBucketCreate",
3623 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003624 return(NULL);
3625 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003626 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003627 /* Create the schema bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003628 if (WXS_IS_BUCKET_INCREDEF(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003629 size = sizeof(xmlSchemaInclude);
3630 else
3631 size = sizeof(xmlSchemaImport);
3632 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3633 if (ret == NULL) {
3634 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3635 return(NULL);
3636 }
3637 memset(ret, 0, size);
3638 ret->targetNamespace = targetNamespace;
3639 ret->type = type;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003640 ret->globals = xmlSchemaItemListCreate();
3641 if (ret->globals == NULL) {
3642 xmlFree(ret);
3643 return(NULL);
3644 }
3645 ret->locals = xmlSchemaItemListCreate();
3646 if (ret->locals == NULL) {
3647 xmlFree(ret);
3648 return(NULL);
3649 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003650 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003651 * The following will assure that only the first bucket is marked as
3652 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3653 * For each following import buckets an xmlSchema will be created.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003654 * An xmlSchema will be created for every distinct targetNamespace.
3655 * We assign the targetNamespace to the schemata here.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003656 */
3657 if (! WXS_HAS_BUCKETS(pctxt)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003658 if (WXS_IS_BUCKET_INCREDEF(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003659 PERROR_INT("xmlSchemaBucketCreate",
3660 "first bucket but it's an include or redefine");
3661 xmlSchemaBucketFree(ret);
3662 return(NULL);
3663 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003664 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003665 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3666 /* Point to the *main* schema. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003667 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3668 WXS_IMPBUCKET(ret)->schema = mainSchema;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003669 /*
3670 * Ensure that the main schema gets a targetNamespace.
3671 */
3672 mainSchema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003673 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +00003674 if (type == XML_SCHEMA_SCHEMA_MAIN) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003675 PERROR_INT("xmlSchemaBucketCreate",
3676 "main bucket but it's not the first one");
3677 xmlSchemaBucketFree(ret);
3678 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003679 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003680 /*
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003681 * Create a schema for imports and assign the
3682 * targetNamespace.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003683 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003684 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3685 if (WXS_IMPBUCKET(ret)->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003686 xmlSchemaBucketFree(ret);
3687 return(NULL);
3688 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003689 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003690 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003691 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003692 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003693 int res;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00003694 /*
3695 * Imports go into the "schemasImports" slot of the main *schema*.
3696 * Note that we create an import entry for the main schema as well; i.e.,
3697 * even if there's only one schema, we'll get an import.
3698 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003699 if (mainSchema->schemasImports == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003700 mainSchema->schemasImports = xmlHashCreateDict(5,
3701 WXS_CONSTRUCTOR(pctxt)->dict);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003702 if (mainSchema->schemasImports == NULL) {
3703 xmlSchemaBucketFree(ret);
3704 return(NULL);
3705 }
3706 }
3707 if (targetNamespace == NULL)
3708 res = xmlHashAddEntry(mainSchema->schemasImports,
3709 XML_SCHEMAS_NO_NAMESPACE, ret);
3710 else
3711 res = xmlHashAddEntry(mainSchema->schemasImports,
3712 targetNamespace, ret);
3713 if (res != 0) {
3714 PERROR_INT("xmlSchemaBucketCreate",
3715 "failed to add the schema bucket to the hash");
3716 xmlSchemaBucketFree(ret);
3717 return(NULL);
3718 }
3719 } else {
3720 /* Set the @ownerImport of an include bucket. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003721 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3722 WXS_INCBUCKET(ret)->ownerImport =
3723 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003724 else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003725 WXS_INCBUCKET(ret)->ownerImport =
3726 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003727
3728 /* Includes got into the "includes" slot of the *main* schema. */
3729 if (mainSchema->includes == NULL) {
3730 mainSchema->includes = xmlSchemaItemListCreate();
3731 if (mainSchema->includes == NULL) {
3732 xmlSchemaBucketFree(ret);
3733 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00003734 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003735 }
3736 xmlSchemaItemListAdd(mainSchema->includes, ret);
3737 }
Daniel Veillarddee23482008-04-11 12:58:43 +00003738 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003739 * Add to list of all buckets; this is used for lookup
3740 * during schema construction time only.
3741 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003742 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003743 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003744 return(ret);
3745}
3746
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003747static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003748xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003749{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003750 if (*list == NULL) {
3751 *list = xmlSchemaItemListCreate();
3752 if (*list == NULL)
3753 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003754 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003755 xmlSchemaItemListAddSize(*list, initialSize, item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003756 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003757}
3758
3759/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003760 * xmlSchemaFreeAnnot:
3761 * @annot: a schema type structure
3762 *
3763 * Deallocate a annotation structure
3764 */
3765static void
3766xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3767{
3768 if (annot == NULL)
3769 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003770 if (annot->next == NULL) {
3771 xmlFree(annot);
3772 } else {
3773 xmlSchemaAnnotPtr prev;
3774
3775 do {
3776 prev = annot;
3777 annot = annot->next;
3778 xmlFree(prev);
3779 } while (annot != NULL);
3780 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003781}
3782
3783/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 * xmlSchemaFreeNotation:
3785 * @schema: a schema notation structure
3786 *
3787 * Deallocate a Schema Notation structure.
3788 */
3789static void
3790xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3791{
3792 if (nota == NULL)
3793 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003794 xmlFree(nota);
3795}
3796
3797/**
3798 * xmlSchemaFreeAttribute:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003799 * @attr: an attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003800 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003801 * Deallocates an attribute declaration structure.
Daniel Veillard4255d502002-04-16 15:50:10 +00003802 */
3803static void
3804xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3805{
3806 if (attr == NULL)
3807 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003808 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003809 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003810 if (attr->defVal != NULL)
3811 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003812 xmlFree(attr);
3813}
3814
3815/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003816 * xmlSchemaFreeAttributeUse:
3817 * @use: an attribute use
3818 *
3819 * Deallocates an attribute use structure.
3820 */
3821static void
3822xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3823{
3824 if (use == NULL)
3825 return;
3826 if (use->annot != NULL)
3827 xmlSchemaFreeAnnot(use->annot);
3828 if (use->defVal != NULL)
3829 xmlSchemaFreeValue(use->defVal);
3830 xmlFree(use);
3831}
3832
3833/**
3834 * xmlSchemaFreeAttributeUseProhib:
3835 * @prohib: an attribute use prohibition
3836 *
3837 * Deallocates an attribute use structure.
3838 */
3839static void
3840xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3841{
3842 if (prohib == NULL)
3843 return;
3844 xmlFree(prohib);
3845}
3846
3847/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003848 * xmlSchemaFreeWildcardNsSet:
3849 * set: a schema wildcard namespace
3850 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003851 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003852 */
3853static void
3854xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3855{
3856 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003857
Daniel Veillard3646d642004-06-02 19:19:14 +00003858 while (set != NULL) {
3859 next = set->next;
3860 xmlFree(set);
3861 set = next;
3862 }
3863}
3864
3865/**
3866 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003867 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003868 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003869 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003870 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003871void
Daniel Veillard3646d642004-06-02 19:19:14 +00003872xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3873{
3874 if (wildcard == NULL)
3875 return;
3876 if (wildcard->annot != NULL)
3877 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003878 if (wildcard->nsSet != NULL)
3879 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3880 if (wildcard->negNsSet != NULL)
3881 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003882 xmlFree(wildcard);
3883}
3884
3885/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 * xmlSchemaFreeAttributeGroup:
3887 * @schema: a schema attribute group structure
3888 *
3889 * Deallocate a Schema Attribute Group structure.
3890 */
3891static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003892xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillard4255d502002-04-16 15:50:10 +00003893{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003894 if (attrGr == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00003896 if (attrGr->annot != NULL)
3897 xmlSchemaFreeAnnot(attrGr->annot);
3898 if (attrGr->attrUses != NULL)
3899 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3900 xmlFree(attrGr);
Daniel Veillard3646d642004-06-02 19:19:14 +00003901}
3902
3903/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003904 * xmlSchemaFreeQNameRef:
3905 * @item: a QName reference structure
3906 *
3907 * Deallocatea a QName reference structure.
3908 */
3909static void
3910xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3911{
3912 xmlFree(item);
3913}
3914
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003915/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003916 * xmlSchemaFreeTypeLinkList:
3917 * @alink: a type link
3918 *
3919 * Deallocate a list of types.
3920 */
3921static void
3922xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3923{
3924 xmlSchemaTypeLinkPtr next;
3925
3926 while (link != NULL) {
3927 next = link->next;
3928 xmlFree(link);
3929 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003930 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003931}
3932
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003933static void
3934xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3935{
3936 xmlSchemaIDCStateObjPtr next;
3937 while (sto != NULL) {
3938 next = sto->next;
3939 if (sto->history != NULL)
3940 xmlFree(sto->history);
3941 if (sto->xpathCtxt != NULL)
3942 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3943 xmlFree(sto);
3944 sto = next;
3945 }
3946}
3947
3948/**
3949 * xmlSchemaFreeIDC:
3950 * @idc: a identity-constraint definition
3951 *
3952 * Deallocates an identity-constraint definition.
3953 */
3954static void
3955xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3956{
3957 xmlSchemaIDCSelectPtr cur, prev;
3958
3959 if (idcDef == NULL)
3960 return;
3961 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003962 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003963 /* Selector */
3964 if (idcDef->selector != NULL) {
3965 if (idcDef->selector->xpathComp != NULL)
3966 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3967 xmlFree(idcDef->selector);
3968 }
3969 /* Fields */
3970 if (idcDef->fields != NULL) {
3971 cur = idcDef->fields;
3972 do {
3973 prev = cur;
3974 cur = cur->next;
3975 if (prev->xpathComp != NULL)
3976 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003977 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003978 } while (cur != NULL);
3979 }
3980 xmlFree(idcDef);
3981}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003982
Daniel Veillard01fa6152004-06-29 17:04:39 +00003983/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003984 * xmlSchemaFreeElement:
3985 * @schema: a schema element structure
3986 *
3987 * Deallocate a Schema Element structure.
3988 */
3989static void
3990xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3991{
3992 if (elem == NULL)
3993 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003994 if (elem->annot != NULL)
3995 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003996 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003998 if (elem->defVal != NULL)
3999 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00004000 xmlFree(elem);
4001}
4002
4003/**
4004 * xmlSchemaFreeFacet:
4005 * @facet: a schema facet structure
4006 *
4007 * Deallocate a Schema Facet structure.
4008 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004009void
Daniel Veillard4255d502002-04-16 15:50:10 +00004010xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4011{
4012 if (facet == NULL)
4013 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004014 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004015 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00004016 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004017 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00004018 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004020 xmlFree(facet);
4021}
4022
4023/**
4024 * xmlSchemaFreeType:
4025 * @type: a schema type structure
4026 *
4027 * Deallocate a Schema Type structure.
4028 */
4029void
4030xmlSchemaFreeType(xmlSchemaTypePtr type)
4031{
4032 if (type == NULL)
4033 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004034 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00004035 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00004036 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004038
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004039 facet = type->facets;
4040 while (facet != NULL) {
4041 next = facet->next;
4042 xmlSchemaFreeFacet(facet);
4043 facet = next;
4044 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004045 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004046 if (type->attrUses != NULL)
4047 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004048 if (type->memberTypes != NULL)
4049 xmlSchemaFreeTypeLinkList(type->memberTypes);
4050 if (type->facetSet != NULL) {
4051 xmlSchemaFacetLinkPtr next, link;
4052
4053 link = type->facetSet;
4054 do {
4055 next = link->next;
4056 xmlFree(link);
4057 link = next;
4058 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004059 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004060 if (type->contModel != NULL)
4061 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004062 xmlFree(type);
4063}
4064
4065/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004066 * xmlSchemaFreeModelGroupDef:
4067 * @item: a schema model group definition
4068 *
4069 * Deallocates a schema model group definition.
4070 */
4071static void
4072xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4073{
4074 if (item->annot != NULL)
4075 xmlSchemaFreeAnnot(item->annot);
4076 xmlFree(item);
4077}
4078
4079/**
4080 * xmlSchemaFreeModelGroup:
4081 * @item: a schema model group
4082 *
4083 * Deallocates a schema model group structure.
4084 */
4085static void
4086xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4087{
4088 if (item->annot != NULL)
4089 xmlSchemaFreeAnnot(item->annot);
4090 xmlFree(item);
4091}
4092
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004093static void
4094xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4095{
4096 if ((list == NULL) || (list->nbItems == 0))
4097 return;
4098 {
4099 xmlSchemaTreeItemPtr item;
4100 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4101 int i;
4102
4103 for (i = 0; i < list->nbItems; i++) {
4104 item = items[i];
4105 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004106 continue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004107 switch (item->type) {
4108 case XML_SCHEMA_TYPE_SIMPLE:
4109 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004110 xmlSchemaFreeType((xmlSchemaTypePtr) item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004111 break;
4112 case XML_SCHEMA_TYPE_ATTRIBUTE:
4113 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004114 break;
4115 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4116 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4117 break;
4118 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4119 xmlSchemaFreeAttributeUseProhib(
4120 (xmlSchemaAttributeUseProhibPtr) item);
4121 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004122 case XML_SCHEMA_TYPE_ELEMENT:
4123 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4124 break;
4125 case XML_SCHEMA_TYPE_PARTICLE:
4126 if (item->annot != NULL)
4127 xmlSchemaFreeAnnot(item->annot);
4128 xmlFree(item);
4129 break;
4130 case XML_SCHEMA_TYPE_SEQUENCE:
4131 case XML_SCHEMA_TYPE_CHOICE:
4132 case XML_SCHEMA_TYPE_ALL:
4133 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4134 break;
4135 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4136 xmlSchemaFreeAttributeGroup(
4137 (xmlSchemaAttributeGroupPtr) item);
4138 break;
4139 case XML_SCHEMA_TYPE_GROUP:
4140 xmlSchemaFreeModelGroupDef(
4141 (xmlSchemaModelGroupDefPtr) item);
4142 break;
4143 case XML_SCHEMA_TYPE_ANY:
4144 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4145 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4146 break;
4147 case XML_SCHEMA_TYPE_IDC_KEY:
4148 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4149 case XML_SCHEMA_TYPE_IDC_KEYREF:
4150 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4151 break;
4152 case XML_SCHEMA_TYPE_NOTATION:
4153 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4154 break;
4155 case XML_SCHEMA_EXTRA_QNAMEREF:
4156 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4157 break;
4158 default: {
4159 /* TODO: This should never be hit. */
4160 xmlSchemaPSimpleInternalErr(NULL,
4161 "Internal error: xmlSchemaComponentListFree, "
4162 "unexpected component type '%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004163 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004164 }
4165 break;
4166 }
4167 }
4168 list->nbItems = 0;
4169 }
4170}
4171
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004172/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004173 * xmlSchemaFree:
4174 * @schema: a schema structure
4175 *
4176 * Deallocate a Schema structure.
4177 */
4178void
4179xmlSchemaFree(xmlSchemaPtr schema)
4180{
4181 if (schema == NULL)
4182 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004183 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004184 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004185 TODO
4186 /*
4187 * Note that those slots are not responsible for freeing
4188 * schema components anymore; this will now be done by
4189 * the schema buckets.
4190 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004191 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004192 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004193 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004194 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004195 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004196 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004197 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004198 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004200 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004201 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004202 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004203 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004204 xmlHashFree(schema->idcDef, NULL);
4205
Daniel Veillard1d913862003-11-21 00:28:39 +00004206 if (schema->schemasImports != NULL)
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01004207 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004208 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004209 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4210 int i;
4211 for (i = 0; i < list->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +00004212 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004213 }
4214 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004215 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004216 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004218 /* Never free the doc here, since this will be done by the buckets. */
4219
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004220 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004221 xmlFree(schema);
4222}
4223
4224/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004225 * *
4226 * Debug functions *
4227 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004228 ************************************************************************/
4229
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004230#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004231
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004232static void
4233xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4234
Daniel Veillard4255d502002-04-16 15:50:10 +00004235/**
4236 * xmlSchemaElementDump:
4237 * @elem: an element
4238 * @output: the file output
4239 *
4240 * Dump the element
4241 */
4242static void
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01004243xmlSchemaElementDump(void *payload, void *data,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004244 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004245 const xmlChar * namespace ATTRIBUTE_UNUSED,
4246 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004247{
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01004248 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4249 FILE *output = (FILE *) data;
Daniel Veillard4255d502002-04-16 15:50:10 +00004250 if (elem == NULL)
4251 return;
4252
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004253
4254 fprintf(output, "Element");
4255 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4256 fprintf(output, " (global)");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004257 fprintf(output, ": '%s' ", elem->name);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004258 if (namespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004259 fprintf(output, "ns '%s'", namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004261#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004262 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004263 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 if (elem->maxOccurs >= UNBOUNDED)
4265 fprintf(output, "max: unbounded\n");
4266 else if (elem->maxOccurs != 1)
4267 fprintf(output, "max: %d\n", elem->maxOccurs);
4268 else
4269 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004271#endif
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004272 /*
4273 * Misc other properties.
4274 */
4275 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4276 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4277 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004278 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004279 fprintf(output, " props: ");
4280 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4281 fprintf(output, "[fixed] ");
4282 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4283 fprintf(output, "[default] ");
4284 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4285 fprintf(output, "[abstract] ");
4286 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4287 fprintf(output, "[nillable] ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004288 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004290 /*
4291 * Default/fixed value.
4292 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004293 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004294 fprintf(output, " value: '%s'\n", elem->value);
4295 /*
4296 * Type.
4297 */
4298 if (elem->namedType != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004299 fprintf(output, " type: '%s' ", elem->namedType);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004300 if (elem->namedTypeNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004301 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004302 else
4303 fprintf(output, "\n");
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004304 } else if (elem->subtypes != NULL) {
4305 /*
4306 * Dump local types.
4307 */
4308 xmlSchemaTypeDump(elem->subtypes, output);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004309 }
4310 /*
4311 * Substitution group.
4312 */
4313 if (elem->substGroup != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004314 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004315 if (elem->substGroupNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004316 fprintf(output, "ns '%s'\n", elem->substGroupNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004317 else
4318 fprintf(output, "\n");
4319 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004320}
4321
4322/**
4323 * xmlSchemaAnnotDump:
4324 * @output: the file output
4325 * @annot: a annotation
4326 *
4327 * Dump the annotation
4328 */
4329static void
4330xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4331{
4332 xmlChar *content;
4333
4334 if (annot == NULL)
4335 return;
4336
4337 content = xmlNodeGetContent(annot->content);
4338 if (content != NULL) {
4339 fprintf(output, " Annot: %s\n", content);
4340 xmlFree(content);
4341 } else
4342 fprintf(output, " Annot: empty\n");
4343}
4344
4345/**
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004346 * xmlSchemaContentModelDump:
4347 * @particle: the schema particle
4348 * @output: the file output
Haibo Huangcfd91dc2020-07-30 23:01:33 -07004349 * @depth: the depth used for indentation
Daniel Veillard4255d502002-04-16 15:50:10 +00004350 *
4351 * Dump a SchemaType structure
4352 */
4353static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004354xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4355{
4356 xmlChar *str = NULL;
4357 xmlSchemaTreeItemPtr term;
4358 char shift[100];
4359 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004361 if (particle == NULL)
4362 return;
4363 for (i = 0;((i < depth) && (i < 25));i++)
4364 shift[2 * i] = shift[2 * i + 1] = ' ';
4365 shift[2 * i] = shift[2 * i + 1] = 0;
Daniel Veillardbccae2d2009-06-04 11:22:45 +02004366 fprintf(output, "%s", shift);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004367 if (particle->children == NULL) {
4368 fprintf(output, "MISSING particle term\n");
4369 return;
4370 }
4371 term = particle->children;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004372 if (term == NULL) {
4373 fprintf(output, "(NULL)");
4374 } else {
4375 switch (term->type) {
4376 case XML_SCHEMA_TYPE_ELEMENT:
4377 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4378 ((xmlSchemaElementPtr)term)->targetNamespace,
4379 ((xmlSchemaElementPtr)term)->name));
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004380 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004381 break;
4382 case XML_SCHEMA_TYPE_SEQUENCE:
4383 fprintf(output, "SEQUENCE");
4384 break;
4385 case XML_SCHEMA_TYPE_CHOICE:
4386 fprintf(output, "CHOICE");
4387 break;
4388 case XML_SCHEMA_TYPE_ALL:
4389 fprintf(output, "ALL");
4390 break;
4391 case XML_SCHEMA_TYPE_ANY:
4392 fprintf(output, "ANY");
4393 break;
4394 default:
4395 fprintf(output, "UNKNOWN\n");
4396 return;
4397 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004398 }
4399 if (particle->minOccurs != 1)
4400 fprintf(output, " min: %d", particle->minOccurs);
4401 if (particle->maxOccurs >= UNBOUNDED)
4402 fprintf(output, " max: unbounded");
4403 else if (particle->maxOccurs != 1)
4404 fprintf(output, " max: %d", particle->maxOccurs);
4405 fprintf(output, "\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004406 if (term &&
4407 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4408 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4409 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4410 (term->children != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004411 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4412 output, depth +1);
4413 }
4414 if (particle->next != NULL)
4415 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4416 output, depth);
4417}
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004418
4419/**
4420 * xmlSchemaAttrUsesDump:
4421 * @uses: attribute uses list
Daniel Veillarddee23482008-04-11 12:58:43 +00004422 * @output: the file output
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004423 *
4424 * Dumps a list of attribute use components.
4425 */
4426static void
4427xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4428{
4429 xmlSchemaAttributeUsePtr use;
4430 xmlSchemaAttributeUseProhibPtr prohib;
4431 xmlSchemaQNameRefPtr ref;
4432 const xmlChar *name, *tns;
4433 xmlChar *str = NULL;
4434 int i;
4435
4436 if ((uses == NULL) || (uses->nbItems == 0))
4437 return;
4438
Daniel Veillarddee23482008-04-11 12:58:43 +00004439 fprintf(output, " attributes:\n");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004440 for (i = 0; i < uses->nbItems; i++) {
4441 use = uses->items[i];
4442 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4443 fprintf(output, " [prohibition] ");
4444 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4445 name = prohib->name;
4446 tns = prohib->targetNamespace;
4447 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4448 fprintf(output, " [reference] ");
4449 ref = (xmlSchemaQNameRefPtr) use;
4450 name = ref->name;
4451 tns = ref->targetNamespace;
4452 } else {
4453 fprintf(output, " [use] ");
4454 name = WXS_ATTRUSE_DECL_NAME(use);
4455 tns = WXS_ATTRUSE_DECL_TNS(use);
4456 }
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004457 fprintf(output, "'%s'\n",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004458 (const char *) xmlSchemaFormatQName(&str, tns, name));
4459 FREE_AND_NULL(str);
4460 }
4461}
4462
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004463/**
4464 * xmlSchemaTypeDump:
4465 * @output: the file output
4466 * @type: a type structure
4467 *
4468 * Dump a SchemaType structure
4469 */
4470static void
Daniel Veillard4255d502002-04-16 15:50:10 +00004471xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4472{
4473 if (type == NULL) {
4474 fprintf(output, "Type: NULL\n");
4475 return;
4476 }
4477 fprintf(output, "Type: ");
4478 if (type->name != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004479 fprintf(output, "'%s' ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004480 else
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004481 fprintf(output, "(no name) ");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004482 if (type->targetNamespace != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004483 fprintf(output, "ns '%s' ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 switch (type->type) {
4485 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004486 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 break;
4488 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004489 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 break;
4491 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004492 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004493 break;
4494 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004495 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004496 break;
4497 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004498 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004499 break;
4500 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004501 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 break;
4503 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004504 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 break;
4506 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004507 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 break;
4509 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004510 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004511 break;
4512 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004513 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004515 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004516 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00004517 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004519 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 break;
4521 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004522 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004523 break;
4524 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004525 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004526 break;
4527 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004528 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004529 break;
4530 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004531 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004532 break;
4533 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004534 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004535 break;
4536 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004537 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 break;
4539 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004540 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004541 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00004542 }
4543 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004544 if (type->base != NULL) {
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004545 fprintf(output, " base type: '%s'", type->base);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004546 if (type->baseNs != NULL)
Kasimier T. Buchcikee8e8ae2005-10-17 14:15:37 +00004547 fprintf(output, " ns '%s'\n", type->baseNs);
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00004548 else
4549 fprintf(output, "\n");
4550 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004551 if (type->attrUses != NULL)
4552 xmlSchemaAttrUsesDump(type->attrUses, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 if (type->annot != NULL)
4554 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004555#ifdef DUMP_CONTENT_MODEL
4556 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4557 (type->subtypes != NULL)) {
4558 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4559 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004561#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004562}
4563
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01004564static void
4565xmlSchemaTypeDumpEntry(void *type, void *output,
4566 const xmlChar *name ATTRIBUTE_UNUSED)
4567{
4568 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4569}
4570
Daniel Veillard4255d502002-04-16 15:50:10 +00004571/**
4572 * xmlSchemaDump:
4573 * @output: the file output
4574 * @schema: a schema structure
4575 *
4576 * Dump a Schema structure.
4577 */
4578void
4579xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4580{
Daniel Veillardce682bc2004-11-05 17:22:25 +00004581 if (output == NULL)
4582 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004583 if (schema == NULL) {
4584 fprintf(output, "Schemas: NULL\n");
4585 return;
4586 }
4587 fprintf(output, "Schemas: ");
4588 if (schema->name != NULL)
4589 fprintf(output, "%s, ", schema->name);
4590 else
4591 fprintf(output, "no name, ");
4592 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004593 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004594 else
4595 fprintf(output, "no target namespace");
4596 fprintf(output, "\n");
4597 if (schema->annot != NULL)
4598 xmlSchemaAnnotDump(output, schema->annot);
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01004599 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4600 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004601}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004602
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004603#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004604/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004605 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004606 * @vctxt: the WXS validation context
4607 *
4608 * Displays the current IDC table for debug purposes.
4609 */
4610static void
4611xmlSchemaDebugDumpIDCTable(FILE * output,
4612 const xmlChar *namespaceName,
4613 const xmlChar *localName,
4614 xmlSchemaPSVIIDCBindingPtr bind)
4615{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004616 xmlChar *str = NULL;
4617 const xmlChar *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004618 xmlSchemaPSVIIDCNodePtr tab;
4619 xmlSchemaPSVIIDCKeyPtr key;
4620 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004621
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004622 fprintf(output, "IDC: TABLES on '%s'\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004623 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004624 FREE_AND_NULL(str)
4625
4626 if (bind == NULL)
4627 return;
4628 do {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004629 fprintf(output, "IDC: BINDING '%s' (%d)\n",
Daniel Veillarddee23482008-04-11 12:58:43 +00004630 xmlSchemaGetComponentQName(&str,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004631 bind->definition), bind->nbNodes);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004632 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004633 for (i = 0; i < bind->nbNodes; i++) {
4634 tab = bind->nodeTable[i];
4635 fprintf(output, " ( ");
4636 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004637 key = tab->keys[j];
4638 if ((key != NULL) && (key->val != NULL)) {
4639 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004640 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004641 fprintf(output, "'%s' ", value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004642 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004643 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004644 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004645 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004646 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004647 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004648 else
4649 fprintf(output, "(key missing), ");
4650 }
4651 fprintf(output, ")\n");
4652 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004653 if (bind->dupls && bind->dupls->nbItems) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004654 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004655 for (i = 0; i < bind->dupls->nbItems; i++) {
4656 tab = bind->dupls->items[i];
4657 fprintf(output, " ( ");
4658 for (j = 0; j < bind->definition->nbFields; j++) {
4659 key = tab->keys[j];
4660 if ((key != NULL) && (key->val != NULL)) {
4661 res = xmlSchemaGetCanonValue(key->val, &value);
4662 if (res >= 0)
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +00004663 fprintf(output, "'%s' ", value);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +00004664 else
4665 fprintf(output, "CANON-VALUE-FAILED ");
4666 if (res == 0)
4667 FREE_AND_NULL(value)
4668 } else if (key != NULL)
4669 fprintf(output, "(no val), ");
4670 else
4671 fprintf(output, "(key missing), ");
4672 }
4673 fprintf(output, ")\n");
4674 }
4675 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004676 bind = bind->next;
4677 } while (bind != NULL);
4678}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004679#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004680#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004681
4682/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004683 * *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004684 * Utilities *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004685 * *
4686 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004687
Daniel Veillardc0826a72004-08-10 14:17:33 +00004688/**
4689 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004690 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004691 * @name: the name of the attribute
4692 *
4693 * Seeks an attribute with a name of @name in
4694 * no namespace.
4695 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004696 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004697 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004698static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004699xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004700{
4701 xmlAttrPtr prop;
4702
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004703 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004704 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004705 prop = node->properties;
4706 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004707 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004708 return(prop);
4709 prop = prop->next;
4710 }
4711 return (NULL);
4712}
4713
4714/**
4715 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004716 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004717 * @uri: the uri
4718 * @name: the name of the attribute
4719 *
4720 * Seeks an attribute with a local name of @name and
4721 * a namespace URI of @uri.
4722 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004723 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004724 */
4725static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004726xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004727{
4728 xmlAttrPtr prop;
4729
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004730 if ((node == NULL) || (name == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00004731 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004732 prop = node->properties;
4733 while (prop != NULL) {
4734 if ((prop->ns != NULL) &&
4735 xmlStrEqual(prop->name, BAD_CAST name) &&
4736 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004737 return(prop);
4738 prop = prop->next;
4739 }
4740 return (NULL);
4741}
4742
4743static const xmlChar *
4744xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4745{
4746 xmlChar *val;
4747 const xmlChar *ret;
4748
4749 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004750 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004751 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004752 ret = xmlDictLookup(ctxt->dict, val, -1);
4753 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004754 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004755}
4756
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004757static const xmlChar *
4758xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4759{
4760 return((const xmlChar*) xmlNodeGetContent(node));
4761}
4762
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004763/**
4764 * xmlSchemaGetProp:
4765 * @ctxt: the parser context
4766 * @node: the node
4767 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004768 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004769 * Read a attribute value and internalize the string
4770 *
4771 * Returns the string or NULL if not present.
4772 */
4773static const xmlChar *
4774xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4775 const char *name)
4776{
4777 xmlChar *val;
4778 const xmlChar *ret;
4779
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004780 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004781 if (val == NULL)
4782 return(NULL);
4783 ret = xmlDictLookup(ctxt->dict, val, -1);
4784 xmlFree(val);
4785 return(ret);
4786}
4787
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004788/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08004789 * *
4790 * Parsing functions *
4791 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00004792 ************************************************************************/
4793
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004794#define WXS_FIND_GLOBAL_ITEM(slot) \
4795 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4796 ret = xmlHashLookup(schema->slot, name); \
4797 if (ret != NULL) goto exit; \
4798 } \
4799 if (xmlHashSize(schema->schemasImports) > 1) { \
4800 xmlSchemaImportPtr import; \
4801 if (nsName == NULL) \
4802 import = xmlHashLookup(schema->schemasImports, \
4803 XML_SCHEMAS_NO_NAMESPACE); \
4804 else \
4805 import = xmlHashLookup(schema->schemasImports, nsName); \
4806 if (import == NULL) \
4807 goto exit; \
4808 ret = xmlHashLookup(import->schema->slot, name); \
4809 }
4810
Daniel Veillard4255d502002-04-16 15:50:10 +00004811/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004812 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004813 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004814 * @name: the element name
4815 * @ns: the element namespace
4816 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004817 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004818 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004819 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004820 */
4821static xmlSchemaElementPtr
4822xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004823 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004824{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004825 xmlSchemaElementPtr ret = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00004826
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004827 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004828 return(NULL);
4829 if (schema != NULL) {
4830 WXS_FIND_GLOBAL_ITEM(elemDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004831 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004832exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004833#ifdef DEBUG
4834 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004835 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004836 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004837 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004838 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004839 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004840 }
4841#endif
4842 return (ret);
4843}
4844
4845/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004846 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004847 * @schema: the main schema
4848 * @name: the type's name
4849 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 *
4851 * Lookup a type in the schemas or the predefined types
4852 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004853 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004854 */
4855static xmlSchemaTypePtr
4856xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004857 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004858{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004859 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004860
4861 if (name == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00004862 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004863 /* First try the built-in types. */
Daniel Veillarddee23482008-04-11 12:58:43 +00004864 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004865 ret = xmlSchemaGetPredefinedType(name, nsName);
4866 if (ret != NULL)
4867 goto exit;
4868 /*
4869 * Note that we try the parsed schemas as well here
4870 * since one might have parsed the S4S, which contain more
4871 * than the built-in types.
4872 * TODO: Can we optimize this?
4873 */
4874 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004875 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004876 WXS_FIND_GLOBAL_ITEM(typeDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +00004877 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004878exit:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00004879
Daniel Veillard4255d502002-04-16 15:50:10 +00004880#ifdef DEBUG
4881 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004882 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004883 fprintf(stderr, "Unable to lookup type %s", name);
4884 else
4885 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004886 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004887 }
4888#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004889 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004890}
4891
Daniel Veillard3646d642004-06-02 19:19:14 +00004892/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004893 * xmlSchemaGetAttributeDecl:
4894 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004895 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004896 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004897 *
4898 * Lookup a an attribute in the schema or imported schemas
4899 *
4900 * Returns the attribute declaration or NULL if not found.
4901 */
4902static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004903xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004904 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004905{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004906 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004907
4908 if ((name == NULL) || (schema == NULL))
4909 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004910 if (schema != NULL) {
4911 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004912 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004913exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004914#ifdef DEBUG
4915 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004916 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004917 fprintf(stderr, "Unable to lookup attribute %s", name);
4918 else
4919 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004920 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004921 }
4922#endif
4923 return (ret);
4924}
4925
4926/**
4927 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004928 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004929 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004930 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004931 *
4932 * Lookup a an attribute group in the schema or imported schemas
4933 *
4934 * Returns the attribute group definition or NULL if not found.
4935 */
4936static xmlSchemaAttributeGroupPtr
4937xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004938 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004939{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004940 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004941
4942 if ((name == NULL) || (schema == NULL))
4943 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004944 if (schema != NULL) {
4945 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4946 }
4947exit:
4948 /* TODO:
4949 if ((ret != NULL) && (ret->redef != NULL)) {
4950 * Return the last redefinition. *
4951 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004952 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004953 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004954#ifdef DEBUG
4955 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004956 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004957 fprintf(stderr, "Unable to lookup attribute group %s", name);
4958 else
4959 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004960 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004961 }
4962#endif
4963 return (ret);
4964}
4965
4966/**
4967 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004968 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004969 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004970 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004971 *
4972 * Lookup a group in the schema or imported schemas
4973 *
4974 * Returns the group definition or NULL if not found.
4975 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004976static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004977xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004978 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004979{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004980 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004981
4982 if ((name == NULL) || (schema == NULL))
4983 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004984 if (schema != NULL) {
4985 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004986 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004987exit:
Daniel Veillarddee23482008-04-11 12:58:43 +00004988
Daniel Veillard3646d642004-06-02 19:19:14 +00004989#ifdef DEBUG
4990 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004991 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004992 fprintf(stderr, "Unable to lookup group %s", name);
4993 else
4994 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004995 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004996 }
4997#endif
4998 return (ret);
4999}
5000
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005001static xmlSchemaNotationPtr
5002xmlSchemaGetNotation(xmlSchemaPtr schema,
5003 const xmlChar *name,
5004 const xmlChar *nsName)
5005{
5006 xmlSchemaNotationPtr ret = NULL;
5007
5008 if ((name == NULL) || (schema == NULL))
5009 return (NULL);
5010 if (schema != NULL) {
5011 WXS_FIND_GLOBAL_ITEM(notaDecl)
5012 }
5013exit:
5014 return (ret);
5015}
5016
5017static xmlSchemaIDCPtr
5018xmlSchemaGetIDC(xmlSchemaPtr schema,
5019 const xmlChar *name,
5020 const xmlChar *nsName)
5021{
5022 xmlSchemaIDCPtr ret = NULL;
5023
5024 if ((name == NULL) || (schema == NULL))
5025 return (NULL);
5026 if (schema != NULL) {
5027 WXS_FIND_GLOBAL_ITEM(idcDef)
5028 }
5029exit:
5030 return (ret);
5031}
5032
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005033/**
5034 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005035 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005036 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005037 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005038 *
5039 * Lookup a group in the schema or imported schemas
5040 *
5041 * Returns the group definition or NULL if not found.
5042 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005043static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005044xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5045 xmlSchemaTypeType itemType,
5046 const xmlChar *name,
5047 const xmlChar *targetNs)
5048{
5049 switch (itemType) {
5050 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005051 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005052 name, targetNs));
5053 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005054 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005055 name, targetNs));
5056 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005057 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005058 return (NULL);
5059 }
5060}
5061
Daniel Veillard4255d502002-04-16 15:50:10 +00005062/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005063 * *
5064 * Parsing functions *
5065 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005066 ************************************************************************/
5067
5068#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005069 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00005070
5071/**
5072 * xmlSchemaIsBlank:
5073 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005074 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 *
5076 * Check if a string is ignorable
5077 *
5078 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5079 */
5080static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005081xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082{
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005085 if (len < 0) {
5086 while (*str != 0) {
5087 if (!(IS_BLANK_CH(*str)))
5088 return (0);
5089 str++;
5090 }
5091 } else while ((*str != 0) && (len != 0)) {
5092 if (!(IS_BLANK_CH(*str)))
5093 return (0);
5094 str++;
5095 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00005096 }
Daniel Veillarddee23482008-04-11 12:58:43 +00005097
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005098 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005099}
5100
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005101#define WXS_COMP_NAME(c, t) ((t) (c))->name
5102#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5103/*
5104* xmlSchemaFindRedefCompInGraph:
5105* ATTENTION TODO: This uses pointer comp. for strings.
5106*/
5107static xmlSchemaBasicItemPtr
5108xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5109 xmlSchemaTypeType type,
5110 const xmlChar *name,
5111 const xmlChar *nsName)
5112{
5113 xmlSchemaBasicItemPtr ret;
5114 int i;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005115
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005116 if ((bucket == NULL) || (name == NULL))
5117 return(NULL);
5118 if ((bucket->globals == NULL) ||
5119 (bucket->globals->nbItems == 0))
5120 goto subschemas;
5121 /*
5122 * Search in global components.
5123 */
5124 for (i = 0; i < bucket->globals->nbItems; i++) {
5125 ret = bucket->globals->items[i];
5126 if (ret->type == type) {
5127 switch (type) {
5128 case XML_SCHEMA_TYPE_COMPLEX:
5129 case XML_SCHEMA_TYPE_SIMPLE:
5130 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5131 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5132 nsName))
5133 {
5134 return(ret);
5135 }
5136 break;
5137 case XML_SCHEMA_TYPE_GROUP:
5138 if ((WXS_COMP_NAME(ret,
5139 xmlSchemaModelGroupDefPtr) == name) &&
5140 (WXS_COMP_TNS(ret,
5141 xmlSchemaModelGroupDefPtr) == nsName))
5142 {
5143 return(ret);
5144 }
5145 break;
5146 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5147 if ((WXS_COMP_NAME(ret,
5148 xmlSchemaAttributeGroupPtr) == name) &&
5149 (WXS_COMP_TNS(ret,
5150 xmlSchemaAttributeGroupPtr) == nsName))
5151 {
5152 return(ret);
5153 }
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +00005154 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005155 default:
5156 /* Should not be hit. */
5157 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005158 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005159 }
5160 }
5161subschemas:
5162 /*
5163 * Process imported/included schemas.
5164 */
5165 if (bucket->relations != NULL) {
5166 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5167
5168 /*
5169 * TODO: Marking the bucket will not avoid multiple searches
5170 * in the same schema, but avoids at least circularity.
5171 */
5172 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5173 do {
5174 if ((rel->bucket != NULL) &&
5175 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5176 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5177 type, name, nsName);
5178 if (ret != NULL)
5179 return(ret);
5180 }
5181 rel = rel->next;
5182 } while (rel != NULL);
5183 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5184 }
5185 return(NULL);
5186}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005187
5188/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005190 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005191 * @schema: the schema being built
5192 * @name: the item name
5193 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005194 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 * *WARNING* this interface is highly subject to change
5196 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005197 * Returns the new structure or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00005198 */
5199static xmlSchemaNotationPtr
5200xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005201 const xmlChar *name, const xmlChar *nsName,
5202 xmlNodePtr node ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005203{
5204 xmlSchemaNotationPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005205
5206 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5207 return (NULL);
5208
Daniel Veillard4255d502002-04-16 15:50:10 +00005209 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5210 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005211 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005212 return (NULL);
5213 }
5214 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005215 ret->type = XML_SCHEMA_TYPE_NOTATION;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005216 ret->name = name;
5217 ret->targetNamespace = nsName;
5218 /* TODO: do we need the node to be set?
5219 * ret->node = node;*/
5220 WXS_ADD_GLOBAL(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 return (ret);
5222}
5223
Daniel Veillard4255d502002-04-16 15:50:10 +00005224/**
5225 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005226 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005227 * @schema: the schema being built
5228 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005229 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005230 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005231 * Add an XML schema Attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 * *WARNING* this interface is highly subject to change
5233 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005234 * Returns the new structure or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00005235 */
5236static xmlSchemaAttributePtr
5237xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005238 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005239 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005240{
5241 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005242
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005243 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 return (NULL);
5245
5246 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5247 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005248 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 return (NULL);
5250 }
5251 memset(ret, 0, sizeof(xmlSchemaAttribute));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005252 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5253 ret->node = node;
5254 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005255 ret->targetNamespace = nsName;
5256
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005257 if (topLevel)
5258 WXS_ADD_GLOBAL(ctxt, ret);
5259 else
5260 WXS_ADD_LOCAL(ctxt, ret);
5261 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005262 return (ret);
5263}
5264
5265/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005266 * xmlSchemaAddAttributeUse:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005267 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005268 * @schema: the schema being built
5269 * @name: the item name
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005270 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005271 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005272 * Add an XML schema Attribute declaration
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005273 * *WARNING* this interface is highly subject to change
5274 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005275 * Returns the new structure or NULL in case of error
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005276 */
5277static xmlSchemaAttributeUsePtr
5278xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5279 xmlNodePtr node)
5280{
5281 xmlSchemaAttributeUsePtr ret = NULL;
5282
5283 if (pctxt == NULL)
5284 return (NULL);
5285
5286 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5287 if (ret == NULL) {
5288 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5289 return (NULL);
5290 }
5291 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5292 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5293 ret->node = node;
5294
5295 WXS_ADD_LOCAL(pctxt, ret);
5296 return (ret);
5297}
5298
5299/*
5300* xmlSchemaAddRedef:
5301*
5302* Adds a redefinition information. This is used at a later stage to:
5303* resolve references to the redefined components and to check constraints.
5304*/
5305static xmlSchemaRedefPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00005306xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005307 xmlSchemaBucketPtr targetBucket,
5308 void *item,
5309 const xmlChar *refName,
5310 const xmlChar *refTargetNs)
5311{
5312 xmlSchemaRedefPtr ret;
5313
5314 ret = (xmlSchemaRedefPtr)
5315 xmlMalloc(sizeof(xmlSchemaRedef));
5316 if (ret == NULL) {
5317 xmlSchemaPErrMemory(pctxt,
5318 "allocating redefinition info", NULL);
5319 return (NULL);
5320 }
5321 memset(ret, 0, sizeof(xmlSchemaRedef));
5322 ret->item = item;
5323 ret->targetBucket = targetBucket;
5324 ret->refName = refName;
5325 ret->refTargetNs = refTargetNs;
5326 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5327 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5328 else
5329 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5330 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5331
5332 return (ret);
5333}
5334
5335/**
5336 * xmlSchemaAddAttributeGroupDefinition:
5337 * @ctxt: a schema parser context
5338 * @schema: the schema being built
5339 * @name: the item name
5340 * @nsName: the target namespace
5341 * @node: the corresponding node
5342 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005343 * Add an XML schema Attribute Group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00005344 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005345 * Returns the new structure or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00005346 */
5347static xmlSchemaAttributeGroupPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005348xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5349 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5350 const xmlChar *name,
5351 const xmlChar *nsName,
5352 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005353{
5354 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005355
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005356 if ((pctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005357 return (NULL);
5358
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005359 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00005361 if (ret == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005362 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005363 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005364 }
5365 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005366 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005367 ret->name = name;
5368 ret->targetNamespace = nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +00005369 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005370
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005371 /* TODO: Remove the flag. */
5372 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5373 if (pctxt->isRedefine) {
5374 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5375 ret, name, nsName);
5376 if (pctxt->redef == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005377 xmlFree(ret);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005378 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005379 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005380 pctxt->redefCounter = 0;
5381 }
5382 WXS_ADD_GLOBAL(pctxt, ret);
5383 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 return (ret);
5385}
5386
5387/**
5388 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005389 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005390 * @schema: the schema being built
5391 * @name: the type name
5392 * @namespace: the type namespace
5393 *
5394 * Add an XML schema Element declaration
5395 * *WARNING* this interface is highly subject to change
5396 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005397 * Returns the new structure or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00005398 */
5399static xmlSchemaElementPtr
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005400xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005401 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00005402 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005403{
5404 xmlSchemaElementPtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005405
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005406 if ((ctxt == NULL) || (name == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005407 return (NULL);
5408
Daniel Veillard4255d502002-04-16 15:50:10 +00005409 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5410 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005411 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005412 return (NULL);
5413 }
5414 memset(ret, 0, sizeof(xmlSchemaElement));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005415 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5416 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005417 ret->targetNamespace = nsName;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005418 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005419
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005420 if (topLevel)
5421 WXS_ADD_GLOBAL(ctxt, ret);
5422 else
5423 WXS_ADD_LOCAL(ctxt, ret);
5424 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005425 return (ret);
5426}
5427
5428/**
5429 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005430 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00005431 * @schema: the schema being built
5432 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005433 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00005434 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005435 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 * *WARNING* this interface is highly subject to change
5437 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005438 * Returns the new structure or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00005439 */
5440static xmlSchemaTypePtr
5441xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005442 xmlSchemaTypeType type,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00005443 const xmlChar * name, const xmlChar * nsName,
5444 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005445{
5446 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005447
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005448 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00005449 return (NULL);
5450
5451 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5452 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005453 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005454 return (NULL);
5455 }
5456 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005457 ret->type = type;
5458 ret->name = name;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005459 ret->targetNamespace = nsName;
5460 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005461 if (topLevel) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005462 if (ctxt->isRedefine) {
5463 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5464 ret, name, nsName);
5465 if (ctxt->redef == NULL) {
5466 xmlFree(ret);
5467 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005468 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005469 ctxt->redefCounter = 0;
5470 }
5471 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005472 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005473 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005474 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005475 return (ret);
5476}
5477
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005478static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005479xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005480 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005481 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005482 const xmlChar *refNs)
5483{
5484 xmlSchemaQNameRefPtr ret;
5485
5486 ret = (xmlSchemaQNameRefPtr)
5487 xmlMalloc(sizeof(xmlSchemaQNameRef));
5488 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005489 xmlSchemaPErrMemory(pctxt,
5490 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005491 return (NULL);
5492 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005493 ret->node = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005494 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5495 ret->name = refName;
5496 ret->targetNamespace = refNs;
5497 ret->item = NULL;
5498 ret->itemType = refType;
5499 /*
5500 * Store the reference item in the schema.
5501 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005502 WXS_ADD_LOCAL(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005503 return (ret);
5504}
5505
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005506static xmlSchemaAttributeUseProhibPtr
5507xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5508{
5509 xmlSchemaAttributeUseProhibPtr ret;
5510
5511 ret = (xmlSchemaAttributeUseProhibPtr)
5512 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5513 if (ret == NULL) {
5514 xmlSchemaPErrMemory(pctxt,
5515 "allocating attribute use prohibition", NULL);
5516 return (NULL);
5517 }
5518 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5519 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5520 WXS_ADD_LOCAL(pctxt, ret);
5521 return (ret);
5522}
5523
5524
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005525/**
5526 * xmlSchemaAddModelGroup:
5527 * @ctxt: a schema parser context
5528 * @schema: the schema being built
5529 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005530 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005531 *
5532 * Adds a schema model group
5533 * *WARNING* this interface is highly subject to change
5534 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005535 * Returns the new structure or NULL in case of error
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005536 */
5537static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005538xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5539 xmlSchemaPtr schema,
5540 xmlSchemaTypeType type,
5541 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005542{
5543 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005544
5545 if ((ctxt == NULL) || (schema == NULL))
5546 return (NULL);
5547
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005548 ret = (xmlSchemaModelGroupPtr)
5549 xmlMalloc(sizeof(xmlSchemaModelGroup));
5550 if (ret == NULL) {
5551 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5552 NULL);
5553 return (NULL);
5554 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005555 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005556 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005557 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005558 WXS_ADD_LOCAL(ctxt, ret);
5559 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5560 (type == XML_SCHEMA_TYPE_CHOICE))
5561 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005562 return (ret);
5563}
5564
5565
5566/**
5567 * xmlSchemaAddParticle:
5568 * @ctxt: a schema parser context
5569 * @schema: the schema being built
5570 * @node: the corresponding node in the schema doc
5571 * @min: the minOccurs
5572 * @max: the maxOccurs
5573 *
5574 * Adds an XML schema particle component.
5575 * *WARNING* this interface is highly subject to change
5576 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005577 * Returns the new structure or NULL in case of error
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005578 */
5579static xmlSchemaParticlePtr
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005580xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005581 xmlNodePtr node, int min, int max)
5582{
5583 xmlSchemaParticlePtr ret = NULL;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00005584 if (ctxt == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005585 return (NULL);
5586
5587#ifdef DEBUG
5588 fprintf(stderr, "Adding particle component\n");
5589#endif
5590 ret = (xmlSchemaParticlePtr)
5591 xmlMalloc(sizeof(xmlSchemaParticle));
5592 if (ret == NULL) {
5593 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5594 NULL);
5595 return (NULL);
5596 }
5597 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5598 ret->annot = NULL;
5599 ret->node = node;
5600 ret->minOccurs = min;
5601 ret->maxOccurs = max;
5602 ret->next = NULL;
5603 ret->children = NULL;
5604
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005605 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00005606 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005607 * Note that addition to pending components will be done locally
5608 * to the specific parsing function, since the most particles
5609 * need not to be fixed up (i.e. the reference to be resolved).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005610 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005611 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005612 return (ret);
5613}
5614
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005615/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005616 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005617 * @ctxt: a schema validation context
5618 * @schema: the schema being built
5619 * @name: the group name
5620 *
5621 * Add an XML schema Group definition
5622 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005623 * Returns the new structure or NULL in case of error
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005624 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005625static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005626xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5627 xmlSchemaPtr schema,
5628 const xmlChar *name,
5629 const xmlChar *nsName,
5630 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005631{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005632 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005633
5634 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5635 return (NULL);
5636
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005637 ret = (xmlSchemaModelGroupDefPtr)
5638 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005639 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005641 return (NULL);
5642 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005643 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005644 ret->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005645 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005646 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005647 ret->targetNamespace = nsName;
5648
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005649 if (ctxt->isRedefine) {
5650 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5651 ret, name, nsName);
5652 if (ctxt->redef == NULL) {
5653 xmlFree(ret);
5654 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00005655 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005656 ctxt->redefCounter = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005657 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005658 WXS_ADD_GLOBAL(ctxt, ret);
5659 WXS_ADD_PENDING(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 return (ret);
5661}
5662
Daniel Veillard3646d642004-06-02 19:19:14 +00005663/**
5664 * xmlSchemaNewWildcardNs:
5665 * @ctxt: a schema validation context
5666 *
5667 * Creates a new wildcard namespace constraint.
5668 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005669 * Returns the new structure or NULL in case of error
Daniel Veillard3646d642004-06-02 19:19:14 +00005670 */
5671static xmlSchemaWildcardNsPtr
5672xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5673{
5674 xmlSchemaWildcardNsPtr ret;
5675
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005676 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005677 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5678 if (ret == NULL) {
5679 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005680 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005681 }
5682 ret->value = NULL;
5683 ret->next = NULL;
5684 return (ret);
5685}
5686
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005687static xmlSchemaIDCPtr
5688xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5689 const xmlChar *name, const xmlChar *nsName,
5690 int category, xmlNodePtr node)
5691{
Daniel Veillarddee23482008-04-11 12:58:43 +00005692 xmlSchemaIDCPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005693
5694 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5695 return (NULL);
5696
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005697 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5698 if (ret == NULL) {
5699 xmlSchemaPErrMemory(ctxt,
5700 "allocating an identity-constraint definition", NULL);
5701 return (NULL);
5702 }
5703 memset(ret, 0, sizeof(xmlSchemaIDC));
5704 /* The target namespace of the parent element declaration. */
5705 ret->targetNamespace = nsName;
5706 ret->name = name;
5707 ret->type = category;
Daniel Veillarddee23482008-04-11 12:58:43 +00005708 ret->node = node;
5709
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005710 WXS_ADD_GLOBAL(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005711 /*
5712 * Only keyrefs need to be fixup up.
5713 */
5714 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005715 WXS_ADD_PENDING(ctxt, ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005716 return (ret);
5717}
5718
Daniel Veillard3646d642004-06-02 19:19:14 +00005719/**
5720 * xmlSchemaAddWildcard:
5721 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005722 * @schema: a schema
5723 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005724 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005725 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005726 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005727 * Returns the new structure or NULL in case of error
Daniel Veillard3646d642004-06-02 19:19:14 +00005728 */
5729static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005730xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5731 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005732{
5733 xmlSchemaWildcardPtr ret = NULL;
5734
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005735 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005736 return (NULL);
5737
5738 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5739 if (ret == NULL) {
5740 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5741 return (NULL);
5742 }
5743 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005744 ret->type = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00005745 ret->node = node;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005746 WXS_ADD_LOCAL(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005747 return (ret);
5748}
5749
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005750static void
5751xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5752{
5753 if (group == NULL)
5754 return;
5755 if (group->members != NULL)
5756 xmlSchemaItemListFree(group->members);
5757 xmlFree(group);
5758}
5759
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01005760static void
5761xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5762{
5763 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5764}
5765
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005766static xmlSchemaSubstGroupPtr
5767xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5768 xmlSchemaElementPtr head)
5769{
5770 xmlSchemaSubstGroupPtr ret;
5771
5772 /* Init subst group hash. */
5773 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5774 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5775 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5776 return(NULL);
5777 }
5778 /* Create a new substitution group. */
5779 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5780 if (ret == NULL) {
5781 xmlSchemaPErrMemory(NULL,
5782 "allocating a substitution group container", NULL);
5783 return(NULL);
5784 }
5785 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5786 ret->head = head;
5787 /* Create list of members. */
5788 ret->members = xmlSchemaItemListCreate();
5789 if (ret->members == NULL) {
5790 xmlSchemaSubstGroupFree(ret);
5791 return(NULL);
5792 }
5793 /* Add subst group to hash. */
5794 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5795 head->name, head->targetNamespace, ret) != 0) {
5796 PERROR_INT("xmlSchemaSubstGroupAdd",
5797 "failed to add a new substitution container");
5798 xmlSchemaSubstGroupFree(ret);
5799 return(NULL);
5800 }
5801 return(ret);
5802}
5803
5804static xmlSchemaSubstGroupPtr
5805xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5806 xmlSchemaElementPtr head)
Daniel Veillarddee23482008-04-11 12:58:43 +00005807{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005808 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5809 return(NULL);
5810 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5811 head->name, head->targetNamespace));
5812
5813}
5814
5815/**
5816 * xmlSchemaAddElementSubstitutionMember:
5817 * @pctxt: a schema parser context
5818 * @head: the head of the substitution group
5819 * @member: the new member of the substitution group
5820 *
5821 * Allocate a new annotation structure.
5822 *
5823 * Returns the newly allocated structure or NULL in case or error
5824 */
5825static int
5826xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5827 xmlSchemaElementPtr head,
5828 xmlSchemaElementPtr member)
5829{
5830 xmlSchemaSubstGroupPtr substGroup = NULL;
5831
5832 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5833 return (-1);
5834
5835 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5836 if (substGroup == NULL)
5837 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5838 if (substGroup == NULL)
5839 return(-1);
5840 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5841 return(-1);
5842 return(0);
5843}
5844
Daniel Veillard4255d502002-04-16 15:50:10 +00005845/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005846 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 * Utilities for parsing *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08005848 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 ************************************************************************/
5850
Daniel Veillard4255d502002-04-16 15:50:10 +00005851/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005852 * xmlSchemaPValAttrNodeQNameValue:
5853 * @ctxt: a schema parser context
5854 * @schema: the schema context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005855 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005856 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005857 * @uri: the resulting namespace URI if found
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005858 * @local: the resulting local part if found, the attribute value otherwise
Daniel Veillardc0826a72004-08-10 14:17:33 +00005859 *
5860 * Extracts the local name and the URI of a QName value and validates it.
5861 * This one is intended to be used on attribute values that
5862 * should resolve to schema components.
5863 *
5864 * Returns 0, in case the QName is valid, a positive error code
5865 * if not valid and -1 if an internal error occurs.
5866 */
5867static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005868xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005870 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005871 xmlAttrPtr attr,
5872 const xmlChar *value,
5873 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005874 const xmlChar **local)
5875{
5876 const xmlChar *pref;
5877 xmlNsPtr ns;
5878 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005879
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880 *uri = NULL;
5881 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005883 if (ret > 0) {
5884 xmlSchemaPSimpleTypeErr(ctxt,
5885 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5886 ownerItem, (xmlNodePtr) attr,
5887 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5888 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005889 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005890 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005891 } else if (ret < 0)
5892 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005893
5894 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005895 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005896 if (ns)
5897 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5898 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005899 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5900 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005901 /*
5902 * This one takes care of included schemas with no
5903 * target namespace.
5904 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005905 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005906 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005907 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005908 return (0);
5909 }
5910 /*
5911 * At this point xmlSplitQName3 has to return a local name.
5912 */
5913 *local = xmlSplitQName3(value, &len);
5914 *local = xmlDictLookup(ctxt->dict, *local, -1);
5915 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005916 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5917 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005918 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005919 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005920 ownerItem, (xmlNodePtr) attr,
5921 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5922 "The value '%s' of simple type 'xs:QName' has no "
5923 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 return (ctxt->err);
5925 } else {
5926 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005927 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 return (0);
5929}
5930
5931/**
5932 * xmlSchemaPValAttrNodeQName:
5933 * @ctxt: a schema parser context
5934 * @schema: the schema context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005935 * @ownerItem: the owner as a schema object
5936 * @attr: the attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00005937 * @uri: the resulting namespace URI if found
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005938 * @local: the resulting local part if found, the attribute value otherwise
Daniel Veillardc0826a72004-08-10 14:17:33 +00005939 *
5940 * Extracts and validates the QName of an attribute value.
5941 * This one is intended to be used on attribute values that
5942 * should resolve to schema components.
5943 *
5944 * Returns 0, in case the QName is valid, a positive error code
5945 * if not valid and -1 if an internal error occurs.
5946 */
5947static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005948xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005949 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005950 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005951 xmlAttrPtr attr,
5952 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 const xmlChar **local)
5954{
5955 const xmlChar *value;
5956
5957 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005958 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005959 ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005960}
5961
5962/**
5963 * xmlSchemaPValAttrQName:
5964 * @ctxt: a schema parser context
5965 * @schema: the schema context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005966 * @ownerItem: the owner as a schema object
5967 * @ownerElem: the parent node of the attribute
5968 * @name: the name of the attribute
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 * @uri: the resulting namespace URI if found
Haibo Huangcfd91dc2020-07-30 23:01:33 -07005970 * @local: the resulting local part if found, the attribute value otherwise
Daniel Veillardc0826a72004-08-10 14:17:33 +00005971 *
5972 * Extracts and validates the QName of an attribute value.
5973 *
5974 * Returns 0, in case the QName is valid, a positive error code
5975 * if not valid and -1 if an internal error occurs.
5976 */
5977static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5979 xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005980 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 xmlNodePtr ownerElem,
5982 const char *name,
5983 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 const xmlChar **local)
5985{
5986 xmlAttrPtr attr;
5987
5988 attr = xmlSchemaGetPropNode(ownerElem, name);
5989 if (attr == NULL) {
5990 *local = NULL;
5991 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005992 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005994 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00005995 ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005996}
5997
5998/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005999 * xmlSchemaPValAttrID:
6000 * @ctxt: a schema parser context
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006001 *
6002 * Extracts and validates the ID of an attribute value.
6003 *
6004 * Returns 0, in case the ID is valid, a positive error code
6005 * if not valid and -1 if an internal error occurs.
6006 */
6007static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006008xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006009{
6010 int ret;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006011 const xmlChar *value;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006012
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006013 if (attr == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006014 return(0);
6015 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6016 ret = xmlValidateNCName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006017 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006018 /*
6019 * NOTE: the IDness might have already be declared in the DTD
6020 */
6021 if (attr->atype != XML_ATTRIBUTE_ID) {
6022 xmlIDPtr res;
6023 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024
6025 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006026 * TODO: Use xmlSchemaStrip here; it's not exported at this
6027 * moment.
6028 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006029 strip = xmlSchemaCollapseString(value);
6030 if (strip != NULL) {
6031 xmlFree((xmlChar *) value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006032 value = strip;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006033 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006034 res = xmlAddID(NULL, attr->doc, value, attr);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006035 if (res == NULL) {
6036 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006037 xmlSchemaPSimpleTypeErr(ctxt,
6038 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006039 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006040 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6041 NULL, NULL, "Duplicate value '%s' of simple "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006042 "type 'xs:ID'", value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006043 } else
6044 attr->atype = XML_ATTRIBUTE_ID;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006045 }
6046 } else if (ret > 0) {
6047 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006048 xmlSchemaPSimpleTypeErr(ctxt,
6049 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006050 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006051 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6052 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6053 "not a valid 'xs:NCName'",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006054 value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006055 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006056 if (value != NULL)
6057 xmlFree((xmlChar *)value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006058
6059 return (ret);
6060}
6061
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006062static int
6063xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6064 xmlNodePtr ownerElem,
6065 const xmlChar *name)
6066{
6067 xmlAttrPtr attr;
6068
6069 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6070 if (attr == NULL)
6071 return(0);
6072 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6073
6074}
6075
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006076/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006077 * xmlGetMaxOccurs:
6078 * @ctxt: a schema validation context
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006079 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006080 *
6081 * Get the maxOccurs property
6082 *
6083 * Returns the default if not found, or the value
6084 */
6085static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006086xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6087 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006089 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006090 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006091 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006092
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006093 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6094 if (attr == NULL)
6095 return (def);
6096 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006097
6098 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006099 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006100 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006101 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6102 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006103 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006104 val, NULL, NULL, NULL);
6105 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006106 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006107 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00006108 }
6109
6110 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006111 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006112 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006113 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006114 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006115 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6116 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006117 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006118 val, NULL, NULL, NULL);
6119 return (def);
6120 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006121 while ((*cur >= '0') && (*cur <= '9')) {
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006122 if (ret > INT_MAX / 10) {
6123 ret = INT_MAX;
6124 } else {
6125 int digit = *cur - '0';
6126 ret *= 10;
6127 if (ret > INT_MAX - digit)
6128 ret = INT_MAX;
6129 else
6130 ret += digit;
6131 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006132 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006133 }
William M. Brack76e95df2003-10-18 16:20:14 +00006134 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006135 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006136 /*
6137 * TODO: Restrict the maximal value to Integer.
6138 */
6139 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006140 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006141 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6142 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006144 val, NULL, NULL, NULL);
6145 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006147 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006148}
6149
6150/**
6151 * xmlGetMinOccurs:
6152 * @ctxt: a schema validation context
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006153 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006154 *
6155 * Get the minOccurs property
6156 *
6157 * Returns the default if not found, or the value
6158 */
6159static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006160xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006161 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006162{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006163 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006165 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006166
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006167 attr = xmlSchemaGetPropNode(node, "minOccurs");
6168 if (attr == NULL)
6169 return (def);
6170 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00006172 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006174 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006175 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006176 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6177 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006178 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006179 val, NULL, NULL, NULL);
6180 return (def);
6181 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006182 while ((*cur >= '0') && (*cur <= '9')) {
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006183 if (ret > INT_MAX / 10) {
6184 ret = INT_MAX;
6185 } else {
6186 int digit = *cur - '0';
6187 ret *= 10;
6188 if (ret > INT_MAX - digit)
6189 ret = INT_MAX;
6190 else
6191 ret += digit;
6192 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006193 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 }
William M. Brack76e95df2003-10-18 16:20:14 +00006195 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006196 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006197 /*
6198 * TODO: Restrict the maximal value to Integer.
6199 */
6200 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006201 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006202 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6203 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006204 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006205 val, NULL, NULL, NULL);
6206 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006207 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006208 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006209}
6210
6211/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006212 * xmlSchemaPGetBoolNodeValue:
6213 * @ctxt: a schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006214 * @ownerItem: the owner as a schema item
6215 * @node: the node holding the value
6216 *
6217 * Converts a boolean string value into 1 or 0.
6218 *
6219 * Returns 0 or 1.
6220 */
6221static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006223 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006224 xmlNodePtr node)
6225{
6226 xmlChar *value = NULL;
6227 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006228
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006229 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006230 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006231 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006232 * An instance of a datatype that is defined as `boolean`
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006233 * can have the following legal literals {true, false, 1, 0}.
6234 */
6235 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6236 res = 1;
6237 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6238 res = 0;
6239 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6240 res = 1;
6241 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006242 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006243 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006244 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006245 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006246 ownerItem, node,
6247 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6248 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006249 NULL, NULL, NULL);
6250 }
6251 if (value != NULL)
6252 xmlFree(value);
6253 return (res);
6254}
6255
6256/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 * xmlGetBooleanProp:
6258 * @ctxt: a schema validation context
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006259 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006260 * @name: the attribute name
6261 * @def: the default value
6262 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006263 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00006264 *
6265 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00006267 */
6268static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006271 const char *name, int def)
6272{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006273 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00006274
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006275 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006276 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006277 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006278 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006279 * 3.2.2.1 Lexical representation
Jan Pokorný761c9e92013-11-29 23:26:27 +01006280 * An instance of a datatype that is defined as `boolean`
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 * can have the following legal literals {true, false, 1, 0}.
6282 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006283 if (xmlStrEqual(val, BAD_CAST "true"))
6284 def = 1;
6285 else if (xmlStrEqual(val, BAD_CAST "false"))
6286 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006287 else if (xmlStrEqual(val, BAD_CAST "1"))
6288 def = 1;
6289 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006290 def = 0;
6291 else {
6292 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006293 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006294 NULL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006295 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6297 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006298 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006299 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00006300}
6301
6302/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006303 * *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006304 * Schema extraction from an Infoset *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08006305 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00006306 ************************************************************************/
6307static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6308 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006309 xmlNodePtr node,
6310 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006311static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6312 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006313 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006314 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00006315 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006316static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6317 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00006318 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006319 xmlNodePtr node,
6320 xmlSchemaTypeType parentType);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006321static xmlSchemaBasicItemPtr
6322xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6323 xmlSchemaPtr schema,
6324 xmlNodePtr node,
6325 xmlSchemaItemListPtr uses,
6326 int parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006327static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6328 xmlSchemaPtr schema,
6329 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00006330static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006331xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6332 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006333
6334/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006335 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006336 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006337 * @pctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 * @ownerItem: the schema object owner if existent
6339 * @attr: the schema attribute node being validated
6340 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006341 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00006342 *
6343 * Validates a value against the given built-in type.
6344 * This one is intended to be used internally for validation
6345 * of schema attribute values during parsing of the schema.
6346 *
6347 * Returns 0 if the value is valid, a positive error code
6348 * number otherwise and -1 in case of an internal or API error.
6349 */
6350static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006351xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006352 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006353 xmlAttrPtr attr,
6354 const xmlChar *value,
6355 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006356{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006357
6358 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006359
6360 /*
6361 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6362 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006363 */
6364 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00006365 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6367 PERROR_INT("xmlSchemaPValAttrNodeValue",
6368 "the given type is not a built-in type");
6369 return (-1);
6370 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006371 switch (type->builtInType) {
6372 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006373 case XML_SCHEMAS_QNAME:
6374 case XML_SCHEMAS_ANYURI:
6375 case XML_SCHEMAS_TOKEN:
6376 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6378 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006379 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006380 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006381 PERROR_INT("xmlSchemaPValAttrNodeValue",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +00006382 "validation using the given type is not supported while "
6383 "parsing a schema");
Daniel Veillard01fa6152004-06-29 17:04:39 +00006384 return (-1);
6385 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006386 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006387 /*
6388 * TODO: Should we use the S4S error codes instead?
6389 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006390 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006391 PERROR_INT("xmlSchemaPValAttrNodeValue",
6392 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006393 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006394 } else if (ret > 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006395 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006396 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6397 else
6398 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +00006399 xmlSchemaPSimpleTypeErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006400 ret, ownerItem, (xmlNodePtr) attr,
6401 type, NULL, value, NULL, NULL, NULL);
6402 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006403 return (ret);
6404}
6405
6406/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006408 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006409 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00006410 * @ownerItem: the schema object owner if existent
6411 * @attr: the schema attribute node being validated
6412 * @type: the built-in type to be validated against
6413 * @value: the resulting value if any
6414 *
6415 * Extracts and validates a value against the given built-in type.
6416 * This one is intended to be used internally for validation
6417 * of schema attribute values during parsing of the schema.
6418 *
6419 * Returns 0 if the value is valid, a positive error code
6420 * number otherwise and -1 in case of an internal or API error.
6421 */
6422static int
6423xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006424 xmlSchemaBasicItemPtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006425 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 xmlSchemaTypePtr type,
6427 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006428{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429 const xmlChar *val;
6430
6431 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006432 return (-1);
6433
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6435 if (value != NULL)
6436 *value = val;
6437
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006438 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006439 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00006440}
6441
6442/**
6443 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006444 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00006445 * @ctxt: a schema parser context
6446 * @node: the element node of the attribute
Daniel Veillardc0826a72004-08-10 14:17:33 +00006447 * @ownerItem: the schema object owner if existent
6448 * @ownerElem: the owner element node
6449 * @name: the name of the schema attribute node
6450 * @type: the built-in type to be validated against
6451 * @value: the resulting value if any
6452 *
6453 * Extracts and validates a value against the given built-in type.
6454 * This one is intended to be used internally for validation
6455 * of schema attribute values during parsing of the schema.
6456 *
6457 * Returns 0 if the value is valid, a positive error code
6458 * number otherwise and -1 in case of an internal or API error.
6459 */
6460static int
Daniel Veillarddee23482008-04-11 12:58:43 +00006461xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006462 xmlSchemaBasicItemPtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006463 xmlNodePtr ownerElem,
6464 const char *name,
6465 xmlSchemaTypePtr type,
6466 const xmlChar **value)
6467{
6468 xmlAttrPtr attr;
6469
6470 if ((ctxt == NULL) || (type == NULL)) {
6471 if (value != NULL)
6472 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006473 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 }
6475 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6476 if (value != NULL)
6477 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006478 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006479 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 "Internal error: xmlSchemaPValAttr, the given "
6481 "type '%s' is not a built-in type.\n",
6482 type->name, NULL);
6483 return (-1);
6484 }
6485 attr = xmlSchemaGetPropNode(ownerElem, name);
6486 if (attr == NULL) {
6487 if (value != NULL)
6488 *value = NULL;
6489 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006491 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 type, value));
6493}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006494
6495static int
6496xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006497 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006498 xmlNodePtr node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006499 xmlAttrPtr attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006500 const xmlChar *namespaceName)
6501{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006502 /* TODO: Pointer comparison instead? */
6503 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006504 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006505 if (xmlStrEqual(xmlSchemaNs, namespaceName))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006506 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006507 /*
6508 * Check if the referenced namespace was <import>ed.
6509 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006510 if (WXS_BUCKET(pctxt)->relations != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006511 xmlSchemaSchemaRelationPtr rel;
6512
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006513 rel = WXS_BUCKET(pctxt)->relations;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006514 do {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006515 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006516 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006517 return (0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006518 rel = rel->next;
6519 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006520 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006521 /*
6522 * No matching <import>ed namespace found.
6523 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006524 {
6525 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6526
6527 if (namespaceName == NULL)
6528 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6529 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6530 "References from this schema to components in no "
6531 "namespace are not allowed, since not indicated by an "
6532 "import statement", NULL, NULL);
6533 else
6534 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 "References from this schema to components in the "
6537 "namespace '%s' are not allowed, since not indicated by an "
6538 "import statement", namespaceName, NULL);
6539 }
6540 return (XML_SCHEMAP_SRC_RESOLVE);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006541}
6542
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006544 * xmlSchemaParseLocalAttributes:
Daniel Veillard4255d502002-04-16 15:50:10 +00006545 * @ctxt: a schema validation context
6546 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006547 * @node: a subtree containing XML Schema information
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006548 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00006549 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006550 * Parses attribute uses and attribute declarations and
Daniel Veillarddee23482008-04-11 12:58:43 +00006551 * attribute group references.
Daniel Veillard4255d502002-04-16 15:50:10 +00006552 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006553static int
6554xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6555 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6556 int parentType, int *hasRefs)
Daniel Veillard4255d502002-04-16 15:50:10 +00006557{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006558 void *item;
Daniel Veillard4255d502002-04-16 15:50:10 +00006559
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006560 while ((IS_SCHEMA((*child), "attribute")) ||
6561 (IS_SCHEMA((*child), "attributeGroup"))) {
6562 if (IS_SCHEMA((*child), "attribute")) {
6563 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6564 *list, parentType);
6565 } else {
6566 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6567 if ((item != NULL) && (hasRefs != NULL))
6568 *hasRefs = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006569 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006570 if (item != NULL) {
6571 if (*list == NULL) {
6572 /* TODO: Customize grow factor. */
6573 *list = xmlSchemaItemListCreate();
6574 if (*list == NULL)
6575 return(-1);
6576 }
6577 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6578 return(-1);
6579 }
6580 *child = (*child)->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006581 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006582 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006583}
6584
6585/**
6586 * xmlSchemaParseAnnotation:
6587 * @ctxt: a schema validation context
6588 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006589 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006591 * parse a XML schema Attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00006592 * *WARNING* this interface is highly subject to change
6593 *
William M. Bracke7091952004-05-11 15:09:58 +00006594 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 * 1 in case of success.
6596 */
6597static xmlSchemaAnnotPtr
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006598xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
Daniel Veillard4255d502002-04-16 15:50:10 +00006599{
6600 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 xmlNodePtr child = NULL;
6602 xmlAttrPtr attr;
6603 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006604
Daniel Veillardc0826a72004-08-10 14:17:33 +00006605 /*
6606 * INFO: S4S completed.
6607 */
6608 /*
6609 * id = ID
6610 * {any attributes with non-schema namespace . . .}>
6611 * Content: (appinfo | documentation)*
6612 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006613 if ((ctxt == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006615 if (needed)
6616 ret = xmlSchemaNewAnnot(ctxt, node);
6617 else
6618 ret = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006619 attr = node->properties;
6620 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006621 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006622 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006623 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006624 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006625
6626 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006627 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006628 }
6629 attr = attr->next;
6630 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006631 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006632 /*
6633 * And now for the children...
6634 */
6635 child = node->children;
6636 while (child != NULL) {
6637 if (IS_SCHEMA(child, "appinfo")) {
6638 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006639 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006640 * source = anyURI
6641 * {any attributes with non-schema namespace . . .}>
6642 * Content: ({any})*
6643 */
6644 attr = child->properties;
6645 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006646 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006647 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006648 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006649 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006650
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006651 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006653 }
6654 attr = attr->next;
6655 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006656 xmlSchemaPValAttr(ctxt, NULL, child, "source",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006657 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006658 child = child->next;
6659 } else if (IS_SCHEMA(child, "documentation")) {
6660 /* TODO: make available the content of "documentation". */
6661 /*
6662 * source = anyURI
6663 * {any attributes with non-schema namespace . . .}>
6664 * Content: ({any})*
6665 */
6666 attr = child->properties;
6667 while (attr != NULL) {
6668 if (attr->ns == NULL) {
6669 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006670 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006671 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006672 }
6673 } else {
6674 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6675 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6676 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677
6678 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006680 }
6681 }
6682 attr = attr->next;
6683 }
6684 /*
6685 * Attribute "xml:lang".
6686 */
6687 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6688 if (attr != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006689 xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006690 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006691 child = child->next;
6692 } else {
6693 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006694 xmlSchemaPContentErr(ctxt,
6695 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006696 NULL, node, child, NULL, "(appinfo | documentation)*");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006697 barked = 1;
6698 child = child->next;
6699 }
6700 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006701
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 return (ret);
6703}
6704
6705/**
6706 * xmlSchemaParseFacet:
6707 * @ctxt: a schema validation context
6708 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006709 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006710 *
6711 * parse a XML schema Facet declaration
6712 * *WARNING* this interface is highly subject to change
6713 *
6714 * Returns the new type structure or NULL in case of error
6715 */
6716static xmlSchemaFacetPtr
6717xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006718 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006719{
6720 xmlSchemaFacetPtr facet;
6721 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006722 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006723
6724 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6725 return (NULL);
6726
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006727 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006728 if (facet == NULL) {
6729 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6730 return (NULL);
6731 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006732 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006733 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006734 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006735 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6736 "Facet %s has no value\n", node->name, NULL);
6737 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006738 return (NULL);
6739 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006740 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006741 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006742 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006744 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006745 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006746 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006747 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006748 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006749 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006750 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006751 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006752 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006753 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006754 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006755 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006756 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006757 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006758 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006759 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006760 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006761 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6762 } else if (IS_SCHEMA(node, "minLength")) {
6763 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6764 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006765 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6766 "Unknown facet type %s\n", node->name, NULL);
6767 xmlSchemaFreeFacet(facet);
6768 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006769 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006770 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006771 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006772 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6773 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6774 const xmlChar *fixed;
6775
6776 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6777 if (fixed != NULL) {
6778 if (xmlStrEqual(fixed, BAD_CAST "true"))
6779 facet->fixed = 1;
6780 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006781 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006782 child = node->children;
6783
6784 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00006785 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006786 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006787 }
6788 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006789 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6790 "Facet %s has unexpected child content\n",
6791 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006792 }
6793 return (facet);
6794}
6795
6796/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 * xmlSchemaParseWildcardNs:
6798 * @ctxt: a schema parser context
6799 * @wildc: the wildcard, already created
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006800 * @node: a subtree containing XML Schema information
Daniel Veillardc0826a72004-08-10 14:17:33 +00006801 *
6802 * Parses the attribute "processContents" and "namespace"
6803 * of a xsd:anyAttribute and xsd:any.
6804 * *WARNING* this interface is highly subject to change
6805 *
6806 * Returns 0 if everything goes fine, a positive error code
6807 * if something is not valid and -1 if an internal error occurs.
6808 */
6809static int
6810xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006811 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 xmlSchemaWildcardPtr wildc,
6813 xmlNodePtr node)
6814{
6815 const xmlChar *pc, *ns, *dictnsItem;
6816 int ret = 0;
6817 xmlChar *nsItem;
6818 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6819 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006820
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6822 if ((pc == NULL)
6823 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6824 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6825 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6826 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6827 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6828 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6829 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006830 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006831 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006832 NULL, node,
6833 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006834 NULL, NULL, NULL);
6835 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006836 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006837 }
6838 /*
6839 * Build the namespace constraints.
6840 */
6841 attr = xmlSchemaGetPropNode(node, "namespace");
6842 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006843 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006844 wildc->any = 1;
6845 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6846 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006848 return (-1);
6849 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006850 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006851 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006852 const xmlChar *end, *cur;
6853
6854 cur = ns;
6855 do {
6856 while (IS_BLANK_CH(*cur))
6857 cur++;
6858 end = cur;
6859 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6860 end++;
6861 if (end == cur)
6862 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006864 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6865 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006867 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006868 NULL, (xmlNodePtr) attr,
6869 NULL,
6870 "((##any | ##other) | List of (xs:anyURI | "
6871 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006872 nsItem, NULL, NULL, NULL);
6873 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6874 } else {
6875 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006876 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006877 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6878 dictnsItem = NULL;
6879 } else {
6880 /*
6881 * Validate the item (anyURI).
6882 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00006883 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006884 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6885 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6886 }
6887 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006888 * Avoid duplicate namespaces.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006889 */
6890 tmp = wildc->nsSet;
6891 while (tmp != NULL) {
6892 if (dictnsItem == tmp->value)
6893 break;
6894 tmp = tmp->next;
6895 }
6896 if (tmp == NULL) {
6897 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6898 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006899 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006900 return (-1);
6901 }
6902 tmp->value = dictnsItem;
6903 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006904 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006905 wildc->nsSet = tmp;
Daniel Veillard76d36452009-09-07 11:19:33 +02006906 else if (lastNs != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006907 lastNs->next = tmp;
6908 lastNs = tmp;
6909 }
6910
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006911 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006912 xmlFree(nsItem);
6913 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006914 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006915 }
6916 return (ret);
6917}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006918
6919static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006920xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6921 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006922 xmlNodePtr node,
6923 int minOccurs,
6924 int maxOccurs) {
6925
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006926 if ((maxOccurs == 0) && ( minOccurs == 0))
6927 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006928 if (maxOccurs != UNBOUNDED) {
6929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006930 * TODO: Maybe we should better not create the particle,
6931 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006932 * content model.
6933 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006934 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006935 * 3.9.6 Schema Component Constraint: Particle Correct
6936 *
6937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006938 if (maxOccurs < 1) {
6939 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006940 * 2.2 {max occurs} must be greater than or equal to 1.
6941 */
6942 xmlSchemaPCustomAttrErr(ctxt,
6943 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006944 NULL, NULL,
6945 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006946 "The value must be greater than or equal to 1");
6947 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6948 } else if (minOccurs > maxOccurs) {
6949 /*
6950 * 2.1 {min occurs} must not be greater than {max occurs}.
6951 */
6952 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006953 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006954 NULL, NULL,
6955 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006956 "The value must not be greater than the value of 'maxOccurs'");
6957 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6958 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006959 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006960 return (0);
6961}
6962
Daniel Veillardc0826a72004-08-10 14:17:33 +00006963/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 * xmlSchemaParseAny:
6965 * @ctxt: a schema validation context
6966 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07006967 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00006968 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006969 * Parsea a XML schema <any> element. A particle and wildcard
6970 * will be created (except if minOccurs==maxOccurs==0, in this case
6971 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 * *WARNING* this interface is highly subject to change
6973 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006974 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006975 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006976static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006977xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6978 xmlNodePtr node)
6979{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006980 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006981 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006982 xmlSchemaWildcardPtr wild;
6983 int min, max;
6984 xmlAttrPtr attr;
6985 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006986
6987 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6988 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006989 /*
6990 * Check for illegal attributes.
6991 */
6992 attr = node->properties;
6993 while (attr != NULL) {
6994 if (attr->ns == NULL) {
6995 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6996 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6997 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6998 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6999 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007000 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007001 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007002 }
7003 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007004 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007005 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007006 }
7007 attr = attr->next;
7008 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007009 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007010 /*
7011 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007012 */
7013 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7014 "(xs:nonNegativeInteger | unbounded)");
7015 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7016 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007017 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7018 /*
7019 * Create & parse the wildcard.
7020 */
7021 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7022 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007023 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007024 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007025 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007026 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007027 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007028 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007029 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007030 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007031 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007032 }
7033 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007034 xmlSchemaPContentErr(ctxt,
7035 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007036 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007037 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007038 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007039 /*
7040 * No component if minOccurs==maxOccurs==0.
7041 */
7042 if ((min == 0) && (max == 0)) {
7043 /* Don't free the wildcard, since it's already on the list. */
7044 return (NULL);
7045 }
7046 /*
7047 * Create the particle.
7048 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00007049 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007050 if (particle == NULL)
7051 return (NULL);
7052 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007053 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00007054
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007055 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00007056}
7057
7058/**
7059 * xmlSchemaParseNotation:
7060 * @ctxt: a schema validation context
7061 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007062 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00007063 *
7064 * parse a XML schema Notation declaration
7065 *
7066 * Returns the new structure or NULL in case of error
7067 */
7068static xmlSchemaNotationPtr
7069xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007070 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007071{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007072 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007073 xmlSchemaNotationPtr ret;
7074 xmlNodePtr child = NULL;
7075
7076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7077 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007078 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007079 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007080 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7081 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007082 return (NULL);
7083 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007084 ret = xmlSchemaAddNotation(ctxt, schema, name,
7085 ctxt->targetNamespace, node);
7086 if (ret == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00007087 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007088 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007089
Daniel Veillard4255d502002-04-16 15:50:10 +00007090 child = node->children;
7091 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007092 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007094 }
7095 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007096 xmlSchemaPContentErr(ctxt,
7097 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007098 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007099 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007100 }
7101
7102 return (ret);
7103}
7104
7105/**
7106 * xmlSchemaParseAnyAttribute:
7107 * @ctxt: a schema validation context
7108 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007109 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00007110 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007111 * parse a XML schema AnyAttribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007112 * *WARNING* this interface is highly subject to change
7113 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007114 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00007115 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007116static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007117xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7118 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007119{
Daniel Veillard3646d642004-06-02 19:19:14 +00007120 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007121 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007122 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007123
7124 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7125 return (NULL);
7126
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007127 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7128 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007129 if (ret == NULL) {
7130 return (NULL);
7131 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007132 /*
7133 * Check for illegal attributes.
7134 */
7135 attr = node->properties;
7136 while (attr != NULL) {
7137 if (attr->ns == NULL) {
7138 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7139 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7140 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007141 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007142 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007143 }
7144 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007145 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007147 }
7148 attr = attr->next;
7149 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007150 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007151 /*
7152 * Parse the namespace list.
7153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007155 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007156 /*
7157 * And now for the children...
7158 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007159 child = node->children;
7160 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007161 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007163 }
7164 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007165 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007166 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007167 NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007168 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007169 }
7170
7171 return (ret);
7172}
7173
7174
7175/**
7176 * xmlSchemaParseAttribute:
7177 * @ctxt: a schema validation context
7178 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007179 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00007180 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007181 * parse a XML schema Attribute declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007182 * *WARNING* this interface is highly subject to change
7183 *
William M. Bracke7091952004-05-11 15:09:58 +00007184 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007185 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007186static xmlSchemaBasicItemPtr
7187xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7188 xmlSchemaPtr schema,
7189 xmlNodePtr node,
7190 xmlSchemaItemListPtr uses,
7191 int parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00007192{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007193 const xmlChar *attrValue, *name = NULL, *ns = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007194 xmlSchemaAttributeUsePtr use = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007195 xmlNodePtr child = NULL;
7196 xmlAttrPtr attr;
7197 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7198 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7199 int nberrors, hasForm = 0, defValueType = 0;
7200
7201#define WXS_ATTR_DEF_VAL_DEFAULT 1
7202#define WXS_ATTR_DEF_VAL_FIXED 2
7203
7204 /*
7205 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7206 */
7207
7208 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7209 return (NULL);
7210 attr = xmlSchemaGetPropNode(node, "ref");
7211 if (attr != NULL) {
7212 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7213 NULL, attr, &tmpNs, &tmpName) != 0) {
7214 return (NULL);
7215 }
7216 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7217 return(NULL);
7218 isRef = 1;
7219 }
7220 nberrors = pctxt->nberrors;
7221 /*
7222 * Check for illegal attributes.
7223 */
7224 attr = node->properties;
7225 while (attr != NULL) {
7226 if (attr->ns == NULL) {
7227 if (isRef) {
7228 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7229 xmlSchemaPValAttrNodeID(pctxt, attr);
7230 goto attr_next;
7231 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7232 goto attr_next;
7233 }
7234 } else {
7235 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7236 goto attr_next;
7237 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7238 xmlSchemaPValAttrNodeID(pctxt, attr);
7239 goto attr_next;
7240 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7241 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7242 attr, &tmpNs, &tmpName);
7243 goto attr_next;
7244 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7245 /*
7246 * Evaluate the target namespace
7247 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007248 hasForm = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007249 attrValue = xmlSchemaGetNodeContent(pctxt,
7250 (xmlNodePtr) attr);
7251 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7252 ns = pctxt->targetNamespace;
7253 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7254 {
7255 xmlSchemaPSimpleTypeErr(pctxt,
7256 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7257 NULL, (xmlNodePtr) attr,
7258 NULL, "(qualified | unqualified)",
7259 attrValue, NULL, NULL, NULL);
7260 }
7261 goto attr_next;
7262 }
7263 }
7264 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7265
7266 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7267 /* TODO: Maybe we need to normalize the value beforehand. */
7268 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7269 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7270 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7271 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7272 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7273 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7274 else {
7275 xmlSchemaPSimpleTypeErr(pctxt,
7276 XML_SCHEMAP_INVALID_ATTR_USE,
7277 NULL, (xmlNodePtr) attr,
7278 NULL, "(optional | prohibited | required)",
7279 attrValue, NULL, NULL, NULL);
7280 }
7281 goto attr_next;
7282 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7283 /*
7284 * 3.2.3 : 1
7285 * default and fixed must not both be present.
7286 */
7287 if (defValue) {
7288 xmlSchemaPMutualExclAttrErr(pctxt,
7289 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7290 NULL, attr, "default", "fixed");
7291 } else {
7292 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7293 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7294 }
7295 goto attr_next;
7296 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7297 /*
7298 * 3.2.3 : 1
7299 * default and fixed must not both be present.
7300 */
7301 if (defValue) {
7302 xmlSchemaPMutualExclAttrErr(pctxt,
7303 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7304 NULL, attr, "default", "fixed");
7305 } else {
7306 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7307 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7308 }
7309 goto attr_next;
7310 }
7311 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7312 goto attr_next;
7313
7314 xmlSchemaPIllegalAttrErr(pctxt,
7315 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7316
7317attr_next:
7318 attr = attr->next;
Daniel Veillarddee23482008-04-11 12:58:43 +00007319 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007320 /*
7321 * 3.2.3 : 2
7322 * If default and use are both present, use must have
7323 * the actual value optional.
7324 */
7325 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7326 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7327 xmlSchemaPSimpleTypeErr(pctxt,
7328 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7329 NULL, node, NULL,
7330 "(optional | prohibited | required)", NULL,
7331 "The value of the attribute 'use' must be 'optional' "
7332 "if the attribute 'default' is present",
7333 NULL, NULL);
7334 }
7335 /*
7336 * We want correct attributes.
7337 */
7338 if (nberrors != pctxt->nberrors)
7339 return(NULL);
7340 if (! isRef) {
7341 xmlSchemaAttributePtr attrDecl;
7342
7343 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7344 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
Daniel Veillarddee23482008-04-11 12:58:43 +00007345 ns = pctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007346 /*
7347 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7348 * TODO: Move this to the component layer.
7349 */
7350 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7351 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7352 XML_SCHEMAP_NO_XSI,
7353 node, NULL,
7354 "The target namespace must not match '%s'",
7355 xmlSchemaInstanceNs, NULL);
7356 }
7357 attr = xmlSchemaGetPropNode(node, "name");
7358 if (attr == NULL) {
7359 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7360 NULL, node, "name", NULL);
7361 return (NULL);
7362 }
7363 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7364 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7365 return (NULL);
7366 }
7367 /*
7368 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7369 * TODO: Move this to the component layer.
7370 */
7371 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7372 xmlSchemaPSimpleTypeErr(pctxt,
7373 XML_SCHEMAP_NO_XMLNS,
7374 NULL, (xmlNodePtr) attr,
7375 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7376 "The value of the attribute must not match 'xmlns'",
7377 NULL, NULL);
7378 return (NULL);
7379 }
7380 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7381 goto check_children;
7382 /*
7383 * Create the attribute use component.
7384 */
7385 use = xmlSchemaAddAttributeUse(pctxt, node);
7386 if (use == NULL)
7387 return(NULL);
7388 use->occurs = occurs;
7389 /*
7390 * Create the attribute declaration.
7391 */
7392 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7393 if (attrDecl == NULL)
7394 return (NULL);
7395 if (tmpName != NULL) {
7396 attrDecl->typeName = tmpName;
7397 attrDecl->typeNs = tmpNs;
7398 }
7399 use->attrDecl = attrDecl;
7400 /*
7401 * Value constraint.
Daniel Veillarddee23482008-04-11 12:58:43 +00007402 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007403 if (defValue != NULL) {
7404 attrDecl->defValue = defValue;
7405 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7406 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7407 }
7408 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7409 xmlSchemaQNameRefPtr ref;
7410
7411 /*
7412 * Create the attribute use component.
7413 */
7414 use = xmlSchemaAddAttributeUse(pctxt, node);
7415 if (use == NULL)
7416 return(NULL);
7417 /*
7418 * We need to resolve the reference at later stage.
7419 */
7420 WXS_ADD_PENDING(pctxt, use);
7421 use->occurs = occurs;
7422 /*
7423 * Create a QName reference to the attribute declaration.
7424 */
7425 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7426 tmpName, tmpNs);
7427 if (ref == NULL)
7428 return(NULL);
7429 /*
7430 * Assign the reference. This will be substituted for the
7431 * referenced attribute declaration when the QName is resolved.
7432 */
7433 use->attrDecl = WXS_ATTR_CAST ref;
7434 /*
7435 * Value constraint.
7436 */
7437 if (defValue != NULL)
7438 use->defValue = defValue;
Nick Wellnhofer359e7502017-11-13 21:13:46 +01007439 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7440 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007441 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007442
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007443check_children:
7444 /*
7445 * And now for the children...
7446 */
7447 child = node->children;
7448 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007449 xmlSchemaAttributeUseProhibPtr prohib;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007450
7451 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007452 xmlSchemaParseAnnotation(pctxt, child, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007453 child = child->next;
7454 }
7455 if (child != NULL) {
7456 xmlSchemaPContentErr(pctxt,
7457 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7458 NULL, node, child, NULL,
7459 "(annotation?)");
7460 }
7461 /*
7462 * Check for pointlessness of attribute prohibitions.
7463 */
Daniel Veillarddee23482008-04-11 12:58:43 +00007464 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007465 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7466 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7467 node, NULL,
7468 "Skipping attribute use prohibition, since it is "
7469 "pointless inside an <attributeGroup>",
7470 NULL, NULL, NULL);
7471 return(NULL);
7472 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7473 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7474 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7475 node, NULL,
7476 "Skipping attribute use prohibition, since it is "
7477 "pointless when extending a type",
7478 NULL, NULL, NULL);
7479 return(NULL);
7480 }
7481 if (! isRef) {
Daniel Veillarddee23482008-04-11 12:58:43 +00007482 tmpName = name;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007483 tmpNs = ns;
7484 }
7485 /*
7486 * Check for duplicate attribute prohibitions.
7487 */
7488 if (uses) {
7489 int i;
Daniel Veillarddee23482008-04-11 12:58:43 +00007490
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007491 for (i = 0; i < uses->nbItems; i++) {
7492 use = uses->items[i];
7493 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7494 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7495 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7496 {
7497 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007498
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007499 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7500 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7501 node, NULL,
7502 "Skipping duplicate attribute use prohibition '%s'",
7503 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7504 NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007505 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007506 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007507 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007508 }
7509 }
7510 /*
7511 * Create the attribute prohibition helper component.
7512 */
7513 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7514 if (prohib == NULL)
7515 return(NULL);
7516 prohib->node = node;
7517 prohib->name = tmpName;
7518 prohib->targetNamespace = tmpNs;
7519 if (isRef) {
7520 /*
7521 * We need at least to resolve to the attribute declaration.
7522 */
7523 WXS_ADD_PENDING(pctxt, prohib);
7524 }
7525 return(WXS_BASIC_CAST prohib);
Daniel Veillarddee23482008-04-11 12:58:43 +00007526 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007527 if (IS_SCHEMA(child, "annotation")) {
7528 /*
7529 * TODO: Should this go into the attr decl?
7530 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007531 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007532 child = child->next;
7533 }
7534 if (isRef) {
7535 if (child != NULL) {
7536 if (IS_SCHEMA(child, "simpleType"))
7537 /*
7538 * 3.2.3 : 3.2
7539 * If ref is present, then all of <simpleType>,
7540 * form and type must be absent.
7541 */
7542 xmlSchemaPContentErr(pctxt,
7543 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7544 NULL, node, child, NULL,
7545 "(annotation?)");
7546 else
7547 xmlSchemaPContentErr(pctxt,
7548 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7549 NULL, node, child, NULL,
7550 "(annotation?)");
7551 }
7552 } else {
7553 if (IS_SCHEMA(child, "simpleType")) {
7554 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7555 /*
7556 * 3.2.3 : 4
7557 * type and <simpleType> must not both be present.
7558 */
7559 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7560 NULL, node, child,
7561 "The attribute 'type' and the <simpleType> child "
7562 "are mutually exclusive", NULL);
7563 } else
7564 WXS_ATTRUSE_TYPEDEF(use) =
7565 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7566 child = child->next;
7567 }
7568 if (child != NULL)
7569 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7570 NULL, node, child, NULL,
7571 "(annotation?, simpleType?)");
7572 }
Daniel Veillarddee23482008-04-11 12:58:43 +00007573 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007574 return (WXS_BASIC_CAST use);
7575}
7576
7577
7578static xmlSchemaAttributePtr
7579xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7580 xmlSchemaPtr schema,
7581 xmlNodePtr node)
7582{
7583 const xmlChar *attrValue;
Daniel Veillard4255d502002-04-16 15:50:10 +00007584 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007585 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007586 xmlAttrPtr attr;
William M. Bracke7091952004-05-11 15:09:58 +00007587
7588 /*
7589 * Note that the w3c spec assumes the schema to be validated with schema
7590 * for schemas beforehand.
7591 *
7592 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00007593 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007594 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillarddee23482008-04-11 12:58:43 +00007595 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007596 /*
7597 * 3.2.3 : 3.1
7598 * One of ref or name must be present, but not both
7599 */
7600 attr = xmlSchemaGetPropNode(node, "name");
7601 if (attr == NULL) {
7602 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7603 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 return (NULL);
7605 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007606 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7607 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7608 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007610 /*
7611 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7612 * TODO: Move this to the component layer.
7613 */
7614 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7615 xmlSchemaPSimpleTypeErr(pctxt,
7616 XML_SCHEMAP_NO_XMLNS,
7617 NULL, (xmlNodePtr) attr,
7618 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7619 "The value of the attribute must not match 'xmlns'",
7620 NULL, NULL);
7621 return (NULL);
7622 }
7623 /*
7624 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7625 * TODO: Move this to the component layer.
7626 * Or better leave it here and add it to the component layer
7627 * if we have a schema construction API.
7628 */
7629 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7630 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7631 XML_SCHEMAP_NO_XSI, node, NULL,
7632 "The target namespace must not match '%s'",
7633 xmlSchemaInstanceNs, NULL);
7634 }
7635
7636 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7637 pctxt->targetNamespace, node, 1);
7638 if (ret == NULL)
7639 return (NULL);
7640 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007641
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007642 /*
7643 * Check for illegal attributes.
7644 */
7645 attr = node->properties;
7646 while (attr != NULL) {
7647 if (attr->ns == NULL) {
7648 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7649 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7650 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7651 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7652 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7653 {
7654 xmlSchemaPIllegalAttrErr(pctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00007655 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007656 }
7657 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7658 xmlSchemaPIllegalAttrErr(pctxt,
7659 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7660 }
7661 attr = attr->next;
7662 }
7663 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7664 node, "type", &ret->typeNs, &ret->typeName);
Daniel Veillarddee23482008-04-11 12:58:43 +00007665
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007666 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00007667 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007668 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00007669 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007670 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 if (ret->defValue != NULL)
7672 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007673 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007674 * Attribute "default".
7675 */
7676 attr = xmlSchemaGetPropNode(node, "default");
7677 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007678 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007679 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007680 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 */
7682 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007683 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7684 WXS_BASIC_CAST ret, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007686 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 /*
7689 * And now for the children...
7690 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007691 child = node->children;
7692 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007693 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007694 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007695 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007696 if (IS_SCHEMA(child, "simpleType")) {
7697 if (ret->typeName != NULL) {
7698 /*
7699 * 3.2.3 : 4
7700 * type and <simpleType> must not both be present.
7701 */
7702 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7703 NULL, node, child,
7704 "The attribute 'type' and the <simpleType> child "
7705 "are mutually exclusive", NULL);
7706 } else
7707 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7708 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007709 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007710 if (child != NULL)
7711 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7712 NULL, node, child, NULL,
7713 "(annotation?, simpleType?)");
7714
Daniel Veillard4255d502002-04-16 15:50:10 +00007715 return (ret);
7716}
7717
7718/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007719 * xmlSchemaParseAttributeGroupRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00007720 * @ctxt: a schema validation context
7721 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007722 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00007723 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007724 * Parse an attribute group definition reference.
7725 * Note that a reference to an attribute group does not
7726 * correspond to any component at all.
Daniel Veillard4255d502002-04-16 15:50:10 +00007727 * *WARNING* this interface is highly subject to change
7728 *
7729 * Returns the attribute group or NULL in case of error.
7730 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007731static xmlSchemaQNameRefPtr
7732xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7733 xmlSchemaPtr schema,
7734 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007735{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007736 xmlSchemaQNameRefPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00007737 xmlNodePtr child = NULL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007738 xmlAttrPtr attr;
7739 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007740
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007741 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00007742 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007743
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007744 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007745 if (attr == NULL) {
7746 xmlSchemaPMissingAttrErr(pctxt,
7747 XML_SCHEMAP_S4S_ATTR_MISSING,
7748 NULL, node, "ref", NULL);
7749 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007750 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007751 xmlSchemaPValAttrNodeQName(pctxt, schema,
7752 NULL, attr, &refNs, &ref);
7753 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7754 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +00007755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007756 /*
7757 * Check for illegal attributes.
7758 */
7759 attr = node->properties;
7760 while (attr != NULL) {
7761 if (attr->ns == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007762 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007763 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007764 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007765 xmlSchemaPIllegalAttrErr(pctxt,
7766 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007767 }
7768 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007769 xmlSchemaPIllegalAttrErr(pctxt,
7770 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007771 }
7772 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007773 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007774 /* Attribute ID */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007775 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7776
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007777 /*
7778 * And now for the children...
7779 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007780 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00007781 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007782 /*
7783 * TODO: We do not have a place to store the annotation, do we?
7784 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007785 xmlSchemaParseAnnotation(pctxt, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007786 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007787 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007788 if (child != NULL) {
7789 xmlSchemaPContentErr(pctxt,
7790 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7791 NULL, node, child, NULL,
7792 "(annotation?)");
7793 }
7794
7795 /*
7796 * Handle attribute group redefinitions.
7797 */
7798 if (pctxt->isRedefine && pctxt->redef &&
7799 (pctxt->redef->item->type ==
7800 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7801 (ref == pctxt->redef->refName) &&
7802 (refNs == pctxt->redef->refTargetNs))
7803 {
7804 /*
7805 * SPEC src-redefine:
7806 * (7.1) "If it has an <attributeGroup> among its contents
Jan Pokorný761c9e92013-11-29 23:26:27 +01007807 * the `actual value` of whose ref [attribute] is the same
7808 * as the `actual value` of its own name attribute plus
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007809 * target namespace, then it must have exactly one such group."
7810 */
7811 if (pctxt->redefCounter != 0) {
7812 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +00007813
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007814 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7815 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7816 "The redefining attribute group definition "
7817 "'%s' must not contain more than one "
7818 "reference to the redefined definition",
7819 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7820 FREE_AND_NULL(str);
7821 return(NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007822 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007823 pctxt->redefCounter++;
7824 /*
7825 * URGENT TODO: How to ensure that the reference will not be
7826 * handled by the normal component resolution mechanism?
7827 */
7828 ret = xmlSchemaNewQNameRef(pctxt,
7829 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7830 if (ret == NULL)
7831 return(NULL);
7832 ret->node = node;
7833 pctxt->redef->reference = WXS_BASIC_CAST ret;
7834 } else {
7835 /*
7836 * Create a QName-reference helper component. We will substitute this
7837 * component for the attribute uses of the referenced attribute group
7838 * definition.
7839 */
7840 ret = xmlSchemaNewQNameRef(pctxt,
7841 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7842 if (ret == NULL)
7843 return(NULL);
7844 ret->node = node;
7845 /* Add to pending items, to be able to resolve the reference. */
7846 WXS_ADD_PENDING(pctxt, ret);
Daniel Veillarddee23482008-04-11 12:58:43 +00007847 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007848 return (ret);
7849}
7850
7851/**
7852 * xmlSchemaParseAttributeGroupDefinition:
7853 * @pctxt: a schema validation context
7854 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07007855 * @node: a subtree containing XML Schema information
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007856 *
7857 * parse a XML schema Attribute Group declaration
7858 * *WARNING* this interface is highly subject to change
7859 *
7860 * Returns the attribute group definition or NULL in case of error.
7861 */
7862static xmlSchemaAttributeGroupPtr
7863xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7864 xmlSchemaPtr schema,
7865 xmlNodePtr node)
7866{
7867 const xmlChar *name;
7868 xmlSchemaAttributeGroupPtr ret;
7869 xmlNodePtr child = NULL;
7870 xmlAttrPtr attr;
7871 int hasRefs = 0;
7872
7873 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7874 return (NULL);
7875
7876 attr = xmlSchemaGetPropNode(node, "name");
7877 if (attr == NULL) {
7878 xmlSchemaPMissingAttrErr(pctxt,
7879 XML_SCHEMAP_S4S_ATTR_MISSING,
7880 NULL, node, "name", NULL);
7881 return (NULL);
7882 }
7883 /*
7884 * The name is crucial, exit if invalid.
7885 */
7886 if (xmlSchemaPValAttrNode(pctxt,
7887 NULL, attr,
7888 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7889 return (NULL);
7890 }
7891 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7892 name, pctxt->targetNamespace, node);
7893 if (ret == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00007894 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007895 /*
7896 * Check for illegal attributes.
7897 */
7898 attr = node->properties;
7899 while (attr != NULL) {
7900 if (attr->ns == NULL) {
7901 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7902 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7903 {
7904 xmlSchemaPIllegalAttrErr(pctxt,
7905 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7906 }
7907 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7908 xmlSchemaPIllegalAttrErr(pctxt,
7909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7910 }
7911 attr = attr->next;
7912 }
7913 /* Attribute ID */
7914 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7915 /*
7916 * And now for the children...
7917 */
7918 child = node->children;
7919 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00007920 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007921 child = child->next;
7922 }
7923 /*
7924 * Parse contained attribute decls/refs.
7925 */
7926 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7927 (xmlSchemaItemListPtr *) &(ret->attrUses),
7928 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7929 return(NULL);
7930 if (hasRefs)
7931 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7932 /*
7933 * Parse the attribute wildcard.
7934 */
7935 if (IS_SCHEMA(child, "anyAttribute")) {
7936 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7937 schema, child);
7938 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007939 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007940 if (child != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007941 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007942 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00007943 NULL, node, child, NULL,
7944 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007945 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007946 return (ret);
7947}
7948
7949/**
William M. Brack2f2a6632004-08-20 23:09:47 +00007950 * xmlSchemaPValAttrFormDefault:
7951 * @value: the value
7952 * @flags: the flags to be modified
7953 * @flagQualified: the specific flag for "qualified"
7954 *
7955 * Returns 0 if the value is valid, 1 otherwise.
7956 */
7957static int
7958xmlSchemaPValAttrFormDefault(const xmlChar *value,
7959 int *flags,
7960 int flagQualified)
7961{
7962 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7963 if ((*flags & flagQualified) == 0)
7964 *flags |= flagQualified;
7965 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007966 return (1);
7967
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 return (0);
7969}
7970
7971/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007972 * xmlSchemaPValAttrBlockFinal:
7973 * @value: the value
7974 * @flags: the flags to be modified
7975 * @flagAll: the specific flag for "#all"
7976 * @flagExtension: the specific flag for "extension"
7977 * @flagRestriction: the specific flag for "restriction"
7978 * @flagSubstitution: the specific flag for "substitution"
7979 * @flagList: the specific flag for "list"
7980 * @flagUnion: the specific flag for "union"
7981 *
7982 * Validates the value of the attribute "final" and "block". The value
7983 * is converted into the specified flag values and returned in @flags.
7984 *
7985 * Returns 0 if the value is valid, 1 otherwise.
7986 */
7987
7988static int
7989xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007991 int flagAll,
7992 int flagExtension,
7993 int flagRestriction,
7994 int flagSubstitution,
7995 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007996 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007997{
7998 int ret = 0;
7999
8000 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008001 * TODO: This does not check for duplicate entries.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008002 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008003 if ((flags == NULL) || (value == NULL))
8004 return (-1);
8005 if (value[0] == 0)
8006 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008007 if (xmlStrEqual(value, BAD_CAST "#all")) {
8008 if (flagAll != -1)
8009 *flags |= flagAll;
8010 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008011 if (flagExtension != -1)
8012 *flags |= flagExtension;
8013 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00008014 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008015 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00008016 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008017 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00008018 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008019 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00008020 *flags |= flagUnion;
8021 }
8022 } else {
8023 const xmlChar *end, *cur = value;
8024 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008025
Daniel Veillardc0826a72004-08-10 14:17:33 +00008026 do {
8027 while (IS_BLANK_CH(*cur))
8028 cur++;
8029 end = cur;
8030 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8031 end++;
8032 if (end == cur)
8033 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008035 if (xmlStrEqual(item, BAD_CAST "extension")) {
8036 if (flagExtension != -1) {
8037 if ((*flags & flagExtension) == 0)
8038 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008039 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008040 ret = 1;
8041 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8042 if (flagRestriction != -1) {
8043 if ((*flags & flagRestriction) == 0)
8044 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008045 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008046 ret = 1;
8047 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8048 if (flagSubstitution != -1) {
8049 if ((*flags & flagSubstitution) == 0)
8050 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008051 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008052 ret = 1;
8053 } else if (xmlStrEqual(item, BAD_CAST "list")) {
8054 if (flagList != -1) {
8055 if ((*flags & flagList) == 0)
8056 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008057 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008058 ret = 1;
8059 } else if (xmlStrEqual(item, BAD_CAST "union")) {
8060 if (flagUnion != -1) {
8061 if ((*flags & flagUnion) == 0)
8062 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008063 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008064 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008065 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008066 ret = 1;
8067 if (item != NULL)
8068 xmlFree(item);
8069 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008070 } while ((ret == 0) && (*cur != 0));
8071 }
8072
Daniel Veillardc0826a72004-08-10 14:17:33 +00008073 return (ret);
8074}
8075
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008076static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008077xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008078 xmlSchemaIDCPtr idc,
8079 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008080 xmlAttrPtr attr,
8081 int isField)
8082{
8083 xmlNodePtr node;
8084
8085 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008086 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008087 * Schema Component Constraint: Selector Value OK
8088 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008089 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008090 * in [XPath].
8091 */
8092 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008094 XML_SCHEMAP_INTERNAL,
8095 "Internal error: xmlSchemaCheckCSelectorXPath, "
8096 "the selector is not specified.\n", NULL, NULL);
8097 return (-1);
8098 }
8099 if (attr == NULL)
8100 node = idc->node;
8101 else
8102 node = (xmlNodePtr) attr;
8103 if (selector->xpath == NULL) {
8104 xmlSchemaPCustomErr(ctxt,
8105 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008107 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008108 "The XPath expression of the selector is not valid", NULL);
8109 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8110 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008111 const xmlChar **nsArray = NULL;
8112 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008113 /*
8114 * Compile the XPath expression.
8115 */
8116 /*
8117 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008118 * TODO: Call xmlPatterncompile with different options for selector/
8119 * field.
8120 */
Daniel Veillard14b56432006-03-09 18:41:40 +00008121 if (attr == NULL)
Daniel Veillardaac7c682006-03-10 13:40:16 +00008122 nsList = NULL;
Daniel Veillard14b56432006-03-09 18:41:40 +00008123 else
8124 nsList = xmlGetNsList(attr->doc, attr->parent);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008125 /*
8126 * Build an array of prefixes and namespaces.
8127 */
8128 if (nsList != NULL) {
8129 int i, count = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008130
8131 for (i = 0; nsList[i] != NULL; i++)
8132 count++;
8133
8134 nsArray = (const xmlChar **) xmlMalloc(
8135 (count * 2 + 1) * sizeof(const xmlChar *));
8136 if (nsArray == NULL) {
8137 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8138 NULL);
Kasimier T. Buchcik940ab0c2005-10-19 17:00:53 +00008139 xmlFree(nsList);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008140 return (-1);
8141 }
8142 for (i = 0; i < count; i++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008143 nsArray[2 * i] = nsList[i]->href;
8144 nsArray[2 * i + 1] = nsList[i]->prefix;
8145 }
8146 nsArray[count * 2] = NULL;
8147 xmlFree(nsList);
8148 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008149 /*
8150 * TODO: Differentiate between "selector" and "field".
8151 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008152 if (isField)
8153 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008154 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008155 else
8156 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008157 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008158 if (nsArray != NULL)
8159 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00008161 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008162 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00008163 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008165 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008166 "The XPath expression '%s' could not be "
8167 "compiled", selector->xpath);
8168 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008169 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008170 }
8171 return (0);
8172}
8173
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008174#define ADD_ANNOTATION(annot) \
8175 xmlSchemaAnnotPtr cur = item->annot; \
8176 if (item->annot == NULL) { \
8177 item->annot = annot; \
8178 return (annot); \
8179 } \
8180 cur = item->annot; \
8181 if (cur->next != NULL) { \
8182 cur = cur->next; \
8183 } \
8184 cur->next = annot;
8185
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008186/**
8187 * xmlSchemaAssignAnnotation:
8188 * @item: the schema component
8189 * @annot: the annotation
8190 *
8191 * Adds the annotation to the given schema component.
8192 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008193 * Returns the given annotation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008194 */
8195static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008196xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8197 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008198{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008199 if ((annItem == NULL) || (annot == NULL))
8200 return (NULL);
8201 switch (annItem->type) {
8202 case XML_SCHEMA_TYPE_ELEMENT: {
8203 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8204 ADD_ANNOTATION(annot)
8205 }
8206 break;
8207 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8208 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8209 ADD_ANNOTATION(annot)
8210 }
8211 break;
8212 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8213 case XML_SCHEMA_TYPE_ANY: {
8214 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8215 ADD_ANNOTATION(annot)
8216 }
8217 break;
8218 case XML_SCHEMA_TYPE_PARTICLE:
8219 case XML_SCHEMA_TYPE_IDC_KEY:
8220 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008222 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8223 ADD_ANNOTATION(annot)
8224 }
8225 break;
8226 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8227 xmlSchemaAttributeGroupPtr item =
8228 (xmlSchemaAttributeGroupPtr) annItem;
8229 ADD_ANNOTATION(annot)
8230 }
8231 break;
8232 case XML_SCHEMA_TYPE_NOTATION: {
8233 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8234 ADD_ANNOTATION(annot)
8235 }
8236 break;
8237 case XML_SCHEMA_FACET_MININCLUSIVE:
8238 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8239 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8240 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8241 case XML_SCHEMA_FACET_TOTALDIGITS:
8242 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8243 case XML_SCHEMA_FACET_PATTERN:
8244 case XML_SCHEMA_FACET_ENUMERATION:
8245 case XML_SCHEMA_FACET_WHITESPACE:
8246 case XML_SCHEMA_FACET_LENGTH:
8247 case XML_SCHEMA_FACET_MAXLENGTH:
8248 case XML_SCHEMA_FACET_MINLENGTH: {
8249 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8250 ADD_ANNOTATION(annot)
8251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 case XML_SCHEMA_TYPE_SIMPLE:
8254 case XML_SCHEMA_TYPE_COMPLEX: {
8255 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8256 ADD_ANNOTATION(annot)
8257 }
8258 break;
8259 case XML_SCHEMA_TYPE_GROUP: {
8260 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8261 ADD_ANNOTATION(annot)
8262 }
8263 break;
8264 case XML_SCHEMA_TYPE_SEQUENCE:
8265 case XML_SCHEMA_TYPE_CHOICE:
8266 case XML_SCHEMA_TYPE_ALL: {
8267 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8268 ADD_ANNOTATION(annot)
8269 }
8270 break;
8271 default:
8272 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008274 NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008275 "Internal error: xmlSchemaAddAnnotation, "
8276 "The item is not a annotated schema component", NULL);
8277 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008278 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008279 return (annot);
8280}
8281
8282/**
8283 * xmlSchemaParseIDCSelectorAndField:
8284 * @ctxt: a schema validation context
8285 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008286 * @node: a subtree containing XML Schema information
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008287 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008288 * Parses a XML Schema identity-constraint definition's
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008289 * <selector> and <field> elements.
8290 *
8291 * Returns the parsed identity-constraint definition.
8292 */
8293static xmlSchemaIDCSelectPtr
Daniel Veillarddee23482008-04-11 12:58:43 +00008294xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008295 xmlSchemaIDCPtr idc,
8296 xmlNodePtr node,
8297 int isField)
8298{
8299 xmlSchemaIDCSelectPtr item;
8300 xmlNodePtr child = NULL;
8301 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008302
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008303 /*
8304 * Check for illegal attributes.
8305 */
8306 attr = node->properties;
8307 while (attr != NULL) {
8308 if (attr->ns == NULL) {
8309 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8310 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008311 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008312 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008313 }
8314 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008315 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008316 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008317 }
8318 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008320 /*
8321 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008322 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008323 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8324 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008325 xmlSchemaPErrMemory(ctxt,
8326 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008327 NULL);
8328 return (NULL);
8329 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008331 /*
8332 * Attribute "xpath" (mandatory).
8333 */
8334 attr = xmlSchemaGetPropNode(node, "xpath");
8335 if (attr == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08008336 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008337 XML_SCHEMAP_S4S_ATTR_MISSING,
8338 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008339 "name", NULL);
8340 } else {
8341 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8342 /*
8343 * URGENT TODO: "field"s have an other syntax than "selector"s.
8344 */
8345
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00008346 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8347 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008348 xmlSchemaPErr(ctxt,
8349 (xmlNodePtr) attr,
8350 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008351 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008352 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008353 NULL, NULL);
8354 }
8355
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008356 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008357 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008358 /*
8359 * And now for the children...
8360 */
8361 child = node->children;
8362 if (IS_SCHEMA(child, "annotation")) {
8363 /*
8364 * Add the annotation to the parent IDC.
8365 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008366 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008367 xmlSchemaParseAnnotation(ctxt, child, 1));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008368 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008369 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008370 if (child != NULL) {
8371 xmlSchemaPContentErr(ctxt,
8372 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008373 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008374 NULL, "(annotation?)");
8375 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008376
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008377 return (item);
8378}
8379
8380/**
8381 * xmlSchemaParseIDC:
8382 * @ctxt: a schema validation context
8383 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008384 * @node: a subtree containing XML Schema information
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008385 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008386 * Parses a XML Schema identity-constraint definition.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008387 *
8388 * Returns the parsed identity-constraint definition.
8389 */
8390static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008391xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008392 xmlSchemaPtr schema,
8393 xmlNodePtr node,
8394 xmlSchemaTypeType idcCategory,
8395 const xmlChar *targetNamespace)
8396{
8397 xmlSchemaIDCPtr item = NULL;
8398 xmlNodePtr child = NULL;
8399 xmlAttrPtr attr;
8400 const xmlChar *name = NULL;
8401 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008402
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008403 /*
8404 * Check for illegal attributes.
8405 */
8406 attr = node->properties;
8407 while (attr != NULL) {
8408 if (attr->ns == NULL) {
8409 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8410 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8411 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8412 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008413 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008414 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008415 }
8416 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008417 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008418 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008419 }
8420 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008421 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008422 /*
8423 * Attribute "name" (mandatory).
8424 */
8425 attr = xmlSchemaGetPropNode(node, "name");
8426 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008427 xmlSchemaPMissingAttrErr(ctxt,
8428 XML_SCHEMAP_S4S_ATTR_MISSING,
8429 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008430 "name", NULL);
8431 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008432 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008433 NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008434 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8435 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008436 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008437 /* Create the component. */
8438 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8439 idcCategory, node);
8440 if (item == NULL)
8441 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008442
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008443 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008444 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8445 /*
8446 * Attribute "refer" (mandatory).
8447 */
8448 attr = xmlSchemaGetPropNode(node, "refer");
8449 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008450 xmlSchemaPMissingAttrErr(ctxt,
8451 XML_SCHEMAP_S4S_ATTR_MISSING,
8452 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008453 "refer", NULL);
8454 } else {
8455 /*
8456 * Create a reference item.
8457 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008458 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008459 NULL, NULL);
8460 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008461 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008462 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008463 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008464 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008465 &(item->ref->name));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008466 xmlSchemaCheckReference(ctxt, schema, node, attr,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008467 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008468 }
8469 }
8470 /*
8471 * And now for the children...
8472 */
8473 child = node->children;
8474 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008475 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008476 child = child->next;
8477 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008478 if (child == NULL) {
8479 xmlSchemaPContentErr(ctxt,
8480 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008481 NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008482 "A child element is missing",
8483 "(annotation?, (selector, field+))");
8484 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008485 /*
8486 * Child element <selector>.
8487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008488 if (IS_SCHEMA(child, "selector")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008489 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008490 item, child, 0);
8491 child = child->next;
8492 /*
8493 * Child elements <field>.
8494 */
8495 if (IS_SCHEMA(child, "field")) {
8496 do {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008497 field = xmlSchemaParseIDCSelectorAndField(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008498 item, child, 1);
8499 if (field != NULL) {
8500 field->index = item->nbFields;
8501 item->nbFields++;
8502 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008503 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008504 else
8505 item->fields = field;
8506 lastField = field;
8507 }
8508 child = child->next;
8509 } while (IS_SCHEMA(child, "field"));
8510 } else {
8511 xmlSchemaPContentErr(ctxt,
8512 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008513 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008514 NULL, "(annotation?, (selector, field+))");
8515 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008516 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008517 if (child != NULL) {
8518 xmlSchemaPContentErr(ctxt,
8519 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008520 NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008521 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008522 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008523
8524 return (item);
8525}
8526
Daniel Veillardc0826a72004-08-10 14:17:33 +00008527/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008528 * xmlSchemaParseElement:
8529 * @ctxt: a schema validation context
8530 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008531 * @node: a subtree containing XML Schema information
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008532 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00008533 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008534 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00008535 * *WARNING* this interface is highly subject to change
8536 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008537 * Returns the element declaration or a particle; NULL in case
8538 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00008539 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008540static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00008541xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008542 xmlNodePtr node, int *isElemRef, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008543{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008544 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008545 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008546 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008547 xmlNodePtr child = NULL;
8548 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008549 int min, max, isRef = 0;
8550 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008551
8552 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8553 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008554
Daniel Veillard4255d502002-04-16 15:50:10 +00008555 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008556 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008557
8558 if (isElemRef != NULL)
8559 *isElemRef = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008560 /*
8561 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008562 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008563 * robust.
8564 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008565 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008567 if ((topLevel) || (attr == NULL)) {
8568 if (nameAttr == NULL) {
8569 xmlSchemaPMissingAttrErr(ctxt,
8570 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008572 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008574 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00008575 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008576
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008577 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008578 child = node->children;
8579 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00008580 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008581 child = child->next;
8582 }
8583 /*
8584 * Skip particle part if a global declaration.
8585 */
8586 if (topLevel)
8587 goto declaration_part;
8588 /*
8589 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008590 */
8591 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8592 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8593 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00008594 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008595 if (particle == NULL)
8596 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008598 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8599
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008601 const xmlChar *refNs = NULL, *ref = NULL;
8602 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008603 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008604 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00008605 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008606 if (isElemRef != NULL)
8607 *isElemRef = 1;
8608
Daniel Veillardc0826a72004-08-10 14:17:33 +00008609 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008610 NULL, attr, &refNs, &ref);
8611 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008612 /*
8613 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00008614 */
8615 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008616 xmlSchemaPMutualExclAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008617 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008619 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008620 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008622 attr = node->properties;
8623 while (attr != NULL) {
8624 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008625 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8626 xmlStrEqual(attr->name, BAD_CAST "name") ||
8627 xmlStrEqual(attr->name, BAD_CAST "id") ||
8628 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8629 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8630 {
8631 attr = attr->next;
8632 continue;
8633 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008634 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008636 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008637 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008638 "Only the attributes 'minOccurs', 'maxOccurs' and "
8639 "'id' are allowed in addition to 'ref'");
8640 break;
8641 }
8642 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8643 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008644 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008645 }
8646 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008647 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008648 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008649 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008650 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008651 if (child != NULL) {
8652 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008653 NULL, node, child, NULL, "(annotation?)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008654 }
8655 if ((min == 0) && (max == 0))
8656 goto return_null;
8657 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008658 * Create the reference item and attach it to the particle.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008659 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008660 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008661 ref, refNs);
8662 if (refer == NULL)
8663 goto return_null;
8664 particle->children = (xmlSchemaTreeItemPtr) refer;
8665 particle->annot = annot;
8666 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008667 * Add the particle to pending components, since the reference
8668 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008669 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008670 WXS_ADD_PENDING(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008671 return ((xmlSchemaBasicItemPtr) particle);
8672 }
8673 /*
8674 * The declaration part ===============================================
8675 */
8676declaration_part:
8677 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008678 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008679 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8680
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008681 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008682 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008683 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008684 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008685 * Evaluate the target namespace.
8686 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008687 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008688 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008689 } else {
8690 attr = xmlSchemaGetPropNode(node, "form");
8691 if (attr != NULL) {
8692 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008694 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008695 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008696 xmlSchemaPSimpleTypeErr(ctxt,
8697 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8698 NULL, (xmlNodePtr) attr,
8699 NULL, "(qualified | unqualified)",
8700 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008701 }
8702 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008703 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008704 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008705 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008706 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008707 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00008708 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008709 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008710 * Check for illegal attributes.
8711 */
William M. Bracke7091952004-05-11 15:09:58 +00008712 attr = node->properties;
8713 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008714 if (attr->ns == NULL) {
8715 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8716 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008717 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008718 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008719 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008720 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008721 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8722 {
8723 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008724 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008725 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008726 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008727 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008728 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008730 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008731 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8732 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00008733 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8734
8735 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008736 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008737 }
8738 }
8739 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008740
Daniel Veillardc0826a72004-08-10 14:17:33 +00008741 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008742 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Bracke7091952004-05-11 15:09:58 +00008743 }
8744 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008745 }
William M. Bracke7091952004-05-11 15:09:58 +00008746 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008747 * Extract/validate attributes.
8748 */
8749 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008751 * Process top attributes of global element declarations here.
8752 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008753 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8754 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008755 xmlSchemaPValAttrQName(ctxt, schema,
8756 NULL, node, "substitutionGroup",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008757 &(decl->substGroupNs), &(decl->substGroup));
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008758 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008760 /*
8761 * Attribute "final".
8762 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008763 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008765 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8766 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8767 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8768 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008769 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008770 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8771 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008772 -1,
8773 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8774 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008775 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008776 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008777 NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008778 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008779 attrValue, NULL, NULL, NULL);
8780 }
8781 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008782 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008783 /*
8784 * Attribute "block".
8785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008786 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008787 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00008788 /*
8789 * Apply default "block" values.
8790 */
8791 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8792 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8793 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8794 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8795 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8796 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008797 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008798 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8799 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00008800 -1,
8801 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008802 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008803 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8804 xmlSchemaPSimpleTypeErr(ctxt,
8805 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008806 NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008807 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008808 "restriction | substitution))", attrValue,
8809 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008810 }
8811 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008812 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008813 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008815 attr = xmlSchemaGetPropNode(node, "type");
8816 if (attr != NULL) {
8817 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008818 NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008819 &(decl->namedTypeNs), &(decl->namedType));
8820 xmlSchemaCheckReference(ctxt, schema, node,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008821 attr, decl->namedTypeNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 }
8823 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8824 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008825 if (attr != NULL) {
8826 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008827 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008828 /*
8829 * 3.3.3 : 1
8830 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008831 */
8832 xmlSchemaPMutualExclAttrErr(ctxt,
8833 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008834 NULL, attr, "default", "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008835 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008836 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8837 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008838 }
William M. Bracke7091952004-05-11 15:09:58 +00008839 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008840 /*
8841 * And now for the children...
8842 */
William M. Bracke7091952004-05-11 15:09:58 +00008843 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008844 /*
8845 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008846 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008847 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008848 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008849 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008850 xmlSchemaPContentErr(ctxt,
8851 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008852 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008853 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008854 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008855 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008856 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008857 child = child->next;
8858 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 /*
8860 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00008861 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00008863 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008864 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008865 xmlSchemaPContentErr(ctxt,
8866 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008867 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008868 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008869 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008870 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008871 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00008872 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 }
William M. Bracke7091952004-05-11 15:09:58 +00008874 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00008875 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008876 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008877 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008878 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008879 } else if (IS_SCHEMA(child, "key")) {
8880 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008881 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008882 } else if (IS_SCHEMA(child, "keyref")) {
8883 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008884 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008885 }
8886 if (lastIDC != NULL)
8887 lastIDC->next = curIDC;
8888 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008889 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008890 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00008891 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00008892 }
8893 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008894 xmlSchemaPContentErr(ctxt,
8895 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008896 NULL, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008897 NULL, "(annotation?, ((simpleType | complexType)?, "
8898 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008900 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008901 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008902 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00008904 * different layer.
8905 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008906 FREE_AND_NULL(des)
8907 if (topLevel)
8908 return ((xmlSchemaBasicItemPtr) decl);
8909 else {
8910 particle->children = (xmlSchemaTreeItemPtr) decl;
8911 return ((xmlSchemaBasicItemPtr) particle);
8912 }
8913
8914return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 FREE_AND_NULL(des);
8916 if (annot != NULL) {
8917 if (particle != NULL)
8918 particle->annot = NULL;
8919 if (decl != NULL)
8920 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008921 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008922 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008923 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008924}
8925
8926/**
8927 * xmlSchemaParseUnion:
8928 * @ctxt: a schema validation context
8929 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07008930 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00008931 *
8932 * parse a XML schema Union definition
8933 * *WARNING* this interface is highly subject to change
8934 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008935 * Returns -1 in case of internal error, 0 in case of success and a positive
8936 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008937 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008938static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008939xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008940 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008941{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008942 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008943 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008944 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008945 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008946
8947 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008948 return (-1);
8949 /* Not a component, don't create it. */
8950 type = ctxt->ctxtType;
8951 /*
8952 * Mark the simple type as being of variety "union".
8953 */
8954 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008956 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01008957 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008958 */
8959 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008960 /*
8961 * Check for illegal attributes.
8962 */
8963 attr = node->properties;
8964 while (attr != NULL) {
8965 if (attr->ns == NULL) {
8966 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8967 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008969 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008970 }
8971 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008972 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008973 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008974 }
8975 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008976 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008977 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008978 /*
8979 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008980 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008983 if (attr != NULL) {
8984 const xmlChar *end;
8985 xmlChar *tmp;
8986 const xmlChar *localName, *nsName;
8987 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8988 xmlSchemaQNameRefPtr ref;
8989
8990 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00008991 type->base = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008992 do {
8993 while (IS_BLANK_CH(*cur))
8994 cur++;
8995 end = cur;
8996 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8997 end++;
8998 if (end == cur)
8999 break;
9000 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009001 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009002 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009003 /*
9004 * Create the member type link.
9005 */
9006 link = (xmlSchemaTypeLinkPtr)
9007 xmlMalloc(sizeof(xmlSchemaTypeLink));
9008 if (link == NULL) {
9009 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9010 "allocating a type link", NULL);
9011 return (-1);
9012 }
9013 link->type = NULL;
9014 link->next = NULL;
9015 if (lastLink == NULL)
9016 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009017 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009018 lastLink->next = link;
9019 lastLink = link;
9020 /*
9021 * Create a reference item.
9022 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009023 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009024 localName, nsName);
9025 if (ref == NULL) {
9026 FREE_AND_NULL(tmp)
9027 return (-1);
9028 }
9029 /*
9030 * Assign the reference to the link, it will be resolved
9031 * later during fixup of the union simple type.
9032 */
9033 link->type = (xmlSchemaTypePtr) ref;
9034 }
9035 FREE_AND_NULL(tmp)
9036 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009037 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009038
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009039 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009040 /*
9041 * And now for the children...
9042 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009043 child = node->children;
9044 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009045 /*
9046 * Add the annotation to the simple type ancestor.
9047 */
9048 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009049 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009050 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009051 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009052 if (IS_SCHEMA(child, "simpleType")) {
9053 xmlSchemaTypePtr subtype, last = NULL;
9054
9055 /*
9056 * Anchor the member types in the "subtypes" field of the
9057 * simple type.
9058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009060 subtype = (xmlSchemaTypePtr)
9061 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9062 if (subtype != NULL) {
9063 if (last == NULL) {
9064 type->subtypes = subtype;
9065 last = subtype;
9066 } else {
9067 last->next = subtype;
9068 last = subtype;
9069 }
9070 last->next = NULL;
9071 }
9072 child = child->next;
9073 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009074 }
9075 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009076 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009077 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009078 NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009079 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009080 if ((attr == NULL) && (type->subtypes == NULL)) {
9081 /*
9082 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009083 * Either the memberTypes [attribute] of the <union> element must
9084 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009086 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009087 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009088 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009089 "Either the attribute 'memberTypes' or "
9090 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009091 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009092 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009093}
9094
9095/**
9096 * xmlSchemaParseList:
9097 * @ctxt: a schema validation context
9098 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07009099 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00009100 *
9101 * parse a XML schema List definition
9102 * *WARNING* this interface is highly subject to change
9103 *
William M. Bracke7091952004-05-11 15:09:58 +00009104 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009105 * 1 in case of success.
9106 */
9107static xmlSchemaTypePtr
9108xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009109 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009110{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009111 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009112 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009113 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009114
9115 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9116 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009117 /* Not a component, don't create it. */
9118 type = ctxt->ctxtType;
9119 /*
9120 * Mark the type as being of variety "list".
9121 */
9122 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009123 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009124 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009125 * then the `simple ur-type definition`."
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009126 */
9127 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00009128 /*
9129 * Check for illegal attributes.
9130 */
9131 attr = node->properties;
9132 while (attr != NULL) {
9133 if (attr->ns == NULL) {
9134 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9135 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009136 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009137 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009138 }
9139 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009140 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009141 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009142 }
9143 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009144 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009145
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009146 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009147
William M. Brack2f2a6632004-08-20 23:09:47 +00009148 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009149 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9150 * fields for holding the reference to the itemType.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009151 *
9152 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9153 * the "ref" fields.
William M. Brack2f2a6632004-08-20 23:09:47 +00009154 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009155 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9156 node, "itemType", &(type->baseNs), &(type->base));
William M. Brack2f2a6632004-08-20 23:09:47 +00009157 /*
9158 * And now for the children...
9159 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009160 child = node->children;
9161 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009162 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009163 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009164 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009165 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009166 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009167 /*
9168 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009169 * Either the itemType [attribute] or the <simpleType> [child] of
9170 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009171 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009172 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009174 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009175 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009176 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009177 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009178 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009179 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009180 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009181 child = child->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009182 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009183 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009184 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009185 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009186 "Either the attribute 'itemType' or the <simpleType> child "
9187 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009188 }
9189 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009190 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009191 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009192 NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00009193 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009194 if ((type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009195 (type->subtypes == NULL) &&
9196 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009197 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009198 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009199 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009200 "Either the attribute 'itemType' or the <simpleType> child "
9201 "must be present", NULL);
9202 }
9203 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009204}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009205
Daniel Veillard4255d502002-04-16 15:50:10 +00009206/**
9207 * xmlSchemaParseSimpleType:
9208 * @ctxt: a schema validation context
9209 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07009210 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +00009211 *
9212 * parse a XML schema Simple Type definition
9213 * *WARNING* this interface is highly subject to change
9214 *
William M. Bracke7091952004-05-11 15:09:58 +00009215 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00009216 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00009217 */
9218static xmlSchemaTypePtr
9219xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009220 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009221{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009222 xmlSchemaTypePtr type, oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009223 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009224 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009225 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009226 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009227
9228 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9229 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230
Daniel Veillardc0826a72004-08-10 14:17:33 +00009231 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009232 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009233 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009234 xmlSchemaPMissingAttrErr(ctxt,
9235 XML_SCHEMAP_S4S_ATTR_MISSING,
9236 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009237 "name", NULL);
9238 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009239 } else {
9240 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009241 NULL, attr,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009242 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9243 return (NULL);
9244 /*
9245 * Skip built-in types.
9246 */
9247 if (ctxt->isS4S) {
9248 xmlSchemaTypePtr biType;
9249
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009250 if (ctxt->isRedefine) {
9251 /*
9252 * REDEFINE: Disallow redefinition of built-in-types.
9253 * TODO: It seems that the spec does not say anything
9254 * about this case.
9255 */
9256 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009257 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009258 "Redefinition of built-in simple types is not "
9259 "supported", NULL);
9260 return(NULL);
9261 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009262 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9263 if (biType != NULL)
9264 return (biType);
9265 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009266 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009267 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009268 /*
9269 * TargetNamespace:
Jan Pokorný761c9e92013-11-29 23:26:27 +01009270 * SPEC "The `actual value` of the targetNamespace [attribute]
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009271 * of the <schema> ancestor element information item if present,
Jan Pokorný761c9e92013-11-29 23:26:27 +01009272 * otherwise `absent`.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009273 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009274 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009275#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009276 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009277#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00009278 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009279 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009280 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009281#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009282 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009283 type = xmlSchemaAddType(ctxt, schema,
9284 XML_SCHEMA_TYPE_SIMPLE,
9285 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009286 ctxt->targetNamespace, node, 0);
9287#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009288 type = xmlSchemaAddType(ctxt, schema,
9289 XML_SCHEMA_TYPE_SIMPLE,
9290 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009291#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00009292 if (type == NULL)
9293 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009294 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009295 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009296 /*
9297 * Check for illegal attributes.
9298 */
9299 attr = node->properties;
9300 while (attr != NULL) {
9301 if (attr->ns == NULL) {
9302 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009303 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +00009304 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009305 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009306 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009307 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009308 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009309 }
9310 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009311 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009312 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009313 /*
9314 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009315 *
9316 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009317 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009318 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9319 attrValue, ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009320 if (type == NULL)
9321 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009322 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009323 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009324 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9325 /*
9326 * Check for illegal attributes.
9327 */
9328 attr = node->properties;
9329 while (attr != NULL) {
9330 if (attr->ns == NULL) {
9331 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9332 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009333 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009334 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009336 }
9337 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009338 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009339 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009340 }
9341 attr = attr->next;
9342 }
9343 /*
9344 * Attribute "final".
9345 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009347 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009348 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9349 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9350 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9351 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9352 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9353 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009354 } else {
9355 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009356 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9357 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009358 XML_SCHEMAS_TYPE_FINAL_LIST,
9359 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9360
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009361 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009362 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009363 WXS_BASIC_CAST type, (xmlNodePtr) attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009364 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00009365 attrValue, NULL, NULL, NULL);
9366 }
9367 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009368 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009369 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009370 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009371 /*
9372 * And now for the children...
9373 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009374 oldCtxtType = ctxt->ctxtType;
Daniel Veillarddee23482008-04-11 12:58:43 +00009375
Daniel Veillardc0826a72004-08-10 14:17:33 +00009376 ctxt->ctxtType = type;
Daniel Veillarddee23482008-04-11 12:58:43 +00009377
Daniel Veillard4255d502002-04-16 15:50:10 +00009378 child = node->children;
9379 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009380 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009381 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009382 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009383 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009384 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009385 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009386 "(annotation?, (restriction | list | union))");
Daniel Veillarddee23482008-04-11 12:58:43 +00009387 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009388 xmlSchemaParseRestriction(ctxt, schema, child,
Daniel Veillarddee23482008-04-11 12:58:43 +00009389 XML_SCHEMA_TYPE_SIMPLE);
9390 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009391 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009392 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009393 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009394 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009395 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009396 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009397 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009398 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009399 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009400 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009401 NULL, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009402 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009403 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009404 /*
9405 * REDEFINE: SPEC src-redefine (5)
9406 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +01009407 * <restriction> among its [children] ... the `actual value` of whose
9408 * base [attribute] must be the same as the `actual value` of its own
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009409 * name attribute plus target namespace;"
9410 */
9411 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9412 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009413 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009414 "<simpleType> must have a <restriction> child", NULL);
9415 }
Daniel Veillarddee23482008-04-11 12:58:43 +00009416
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009417 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009418 return (type);
9419}
9420
Daniel Veillard4255d502002-04-16 15:50:10 +00009421/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422 * xmlSchemaParseModelGroupDefRef:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009423 * @ctxt: the parser context
9424 * @schema: the schema being built
9425 * @node: the node
Daniel Veillard4255d502002-04-16 15:50:10 +00009426 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009427 * Parses a reference to a model group definition.
Daniel Veillard4255d502002-04-16 15:50:10 +00009428 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009429 * We will return a particle component with a qname-component or
9430 * NULL in case of an error.
Daniel Veillard4255d502002-04-16 15:50:10 +00009431 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009432static xmlSchemaTreeItemPtr
9433xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9434 xmlSchemaPtr schema,
9435 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009436{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009437 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009438 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009439 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009440 const xmlChar *ref = NULL, *refNs = NULL;
9441 int min, max;
9442
9443 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009445
9446 attr = xmlSchemaGetPropNode(node, "ref");
9447 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448 xmlSchemaPMissingAttrErr(ctxt,
9449 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009450 NULL, node, "ref", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009451 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009452 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009453 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009454 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009455 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009456 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009457 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009458 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009459 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009460 /*
9461 * Check for illegal attributes.
9462 */
9463 attr = node->properties;
9464 while (attr != NULL) {
9465 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009466 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009467 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9468 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9469 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009470 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009471 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009472 }
9473 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009474 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009475 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009476 }
9477 attr = attr->next;
9478 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009479 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +00009480 item = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009481 if (item == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +00009482 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009483 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009484 * Create a qname-reference and set as the term; it will be substituted
9485 * for the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009486 */
9487 item->children = (xmlSchemaTreeItemPtr)
Daniel Veillarddee23482008-04-11 12:58:43 +00009488 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009489 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9490 /*
9491 * And now for the children...
9492 */
9493 child = node->children;
9494 /* TODO: Is annotation even allowed for a model group reference? */
9495 if (IS_SCHEMA(child, "annotation")) {
9496 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009497 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009498 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009499 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009500 child = child->next;
9501 }
9502 if (child != NULL) {
9503 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009505 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009506 "(annotation?)");
9507 }
9508 /*
9509 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9510 */
9511 if ((min == 0) && (max == 0))
9512 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009513
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009514 return ((xmlSchemaTreeItemPtr) item);
9515}
9516
9517/**
9518 * xmlSchemaParseModelGroupDefinition:
9519 * @ctxt: a schema validation context
9520 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -07009521 * @node: a subtree containing XML Schema information
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009522 *
9523 * Parses a XML schema model group definition.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009524 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -07009525 * Note that the constraint src-redefine (6.2) can't be applied until
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009526 * references have been resolved. So we will do this at the
9527 * component fixup level.
Daniel Veillarddee23482008-04-11 12:58:43 +00009528 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009529 * *WARNING* this interface is highly subject to change
9530 *
9531 * Returns -1 in case of error, 0 if the declaration is improper and
9532 * 1 in case of success.
9533 */
9534static xmlSchemaModelGroupDefPtr
9535xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9536 xmlSchemaPtr schema,
9537 xmlNodePtr node)
9538{
9539 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009540 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009541 xmlAttrPtr attr;
9542 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009543
9544 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009545 return (NULL);
9546
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009547 attr = xmlSchemaGetPropNode(node, "name");
9548 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009549 xmlSchemaPMissingAttrErr(ctxt,
9550 XML_SCHEMAP_S4S_ATTR_MISSING,
9551 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009552 "name", NULL);
9553 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009554 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009555 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9556 return (NULL);
9557 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009558 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9559 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009560 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009561 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009562 /*
9563 * Check for illegal attributes.
9564 */
9565 attr = node->properties;
9566 while (attr != NULL) {
9567 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009568 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009569 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009570 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009571 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009573 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009574 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009575 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009577 attr = attr->next;
9578 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009579 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009580 /*
9581 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009582 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 child = node->children;
9584 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009585 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009586 child = child->next;
9587 }
9588 if (IS_SCHEMA(child, "all")) {
9589 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9590 XML_SCHEMA_TYPE_ALL, 0);
9591 child = child->next;
9592 } else if (IS_SCHEMA(child, "choice")) {
9593 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9594 XML_SCHEMA_TYPE_CHOICE, 0);
9595 child = child->next;
9596 } else if (IS_SCHEMA(child, "sequence")) {
9597 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9598 XML_SCHEMA_TYPE_SEQUENCE, 0);
9599 child = child->next;
9600 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009601
Daniel Veillarddee23482008-04-11 12:58:43 +00009602
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009603
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009604 if (child != NULL) {
9605 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009606 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009607 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009609 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009610 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009611}
9612
9613/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009614 * xmlSchemaCleanupDoc:
9615 * @ctxt: a schema validation context
9616 * @node: the root of the document.
9617 *
9618 * removes unwanted nodes in a schemas document tree
9619 */
9620static void
9621xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9622{
9623 xmlNodePtr delete, cur;
9624
9625 if ((ctxt == NULL) || (root == NULL)) return;
9626
9627 /*
9628 * Remove all the blank text nodes
9629 */
9630 delete = NULL;
9631 cur = root;
9632 while (cur != NULL) {
9633 if (delete != NULL) {
9634 xmlUnlinkNode(delete);
9635 xmlFreeNode(delete);
9636 delete = NULL;
9637 }
9638 if (cur->type == XML_TEXT_NODE) {
9639 if (IS_BLANK_NODE(cur)) {
9640 if (xmlNodeGetSpacePreserve(cur) != 1) {
9641 delete = cur;
9642 }
9643 }
9644 } else if ((cur->type != XML_ELEMENT_NODE) &&
9645 (cur->type != XML_CDATA_SECTION_NODE)) {
9646 delete = cur;
9647 goto skip_children;
9648 }
9649
9650 /*
9651 * Skip to next node
9652 */
9653 if (cur->children != NULL) {
9654 if ((cur->children->type != XML_ENTITY_DECL) &&
9655 (cur->children->type != XML_ENTITY_REF_NODE) &&
9656 (cur->children->type != XML_ENTITY_NODE)) {
9657 cur = cur->children;
9658 continue;
9659 }
9660 }
9661 skip_children:
9662 if (cur->next != NULL) {
9663 cur = cur->next;
9664 continue;
9665 }
9666
9667 do {
9668 cur = cur->parent;
9669 if (cur == NULL)
9670 break;
9671 if (cur == root) {
9672 cur = NULL;
9673 break;
9674 }
9675 if (cur->next != NULL) {
9676 cur = cur->next;
9677 break;
9678 }
9679 } while (cur != NULL);
9680 }
9681 if (delete != NULL) {
9682 xmlUnlinkNode(delete);
9683 xmlFreeNode(delete);
9684 delete = NULL;
9685 }
9686}
9687
William M. Brack2f2a6632004-08-20 23:09:47 +00009688
William M. Brack2f2a6632004-08-20 23:09:47 +00009689static void
9690xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9691{
9692 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9693 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9694
9695 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9696 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9697
9698 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9699 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9700 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9701 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9702 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9703 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9704 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9705 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9706
9707 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9708 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9709 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9710 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9711 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9712 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9713}
9714
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009715static int
9716xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009717 xmlSchemaPtr schema,
9718 xmlNodePtr node)
9719{
9720 xmlAttrPtr attr;
9721 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009722 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00009723
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009724 /*
9725 * Those flags should be moved to the parser context flags,
9726 * since they are not visible at the component level. I.e.
9727 * they are used if processing schema *documents* only.
9728 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009729 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009730 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009731
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009732 /*
9733 * Since the version is of type xs:token, we won't bother to
9734 * check it.
9735 */
9736 /* REMOVED:
9737 attr = xmlSchemaGetPropNode(node, "version");
9738 if (attr != NULL) {
9739 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillarddee23482008-04-11 12:58:43 +00009740 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009741 HFAILURE;
9742 }
9743 */
9744 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9745 if (attr != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009746 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009747 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9748 HFAILURE;
9749 if (res != 0) {
9750 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9751 goto exit;
9752 }
9753 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009754 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009755 if (attr != NULL) {
9756 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009757 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9758 XML_SCHEMAS_QUALIF_ELEM);
9759 HFAILURE;
9760 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009761 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009762 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009763 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009764 "(qualified | unqualified)", val, NULL, NULL, NULL);
9765 }
9766 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009767 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009768 if (attr != NULL) {
9769 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009770 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9771 XML_SCHEMAS_QUALIF_ATTR);
9772 HFAILURE;
9773 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009775 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009776 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009777 "(qualified | unqualified)", val, NULL, NULL, NULL);
9778 }
9779 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009780 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009781 if (attr != NULL) {
9782 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009783 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9785 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9786 -1,
9787 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009788 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9789 HFAILURE;
9790 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009791 xmlSchemaPSimpleTypeErr(ctxt,
9792 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009793 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009794 "(#all | List of (extension | restriction | list | union))",
9795 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009796 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009797 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009798 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00009799 if (attr != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +00009800 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009801 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00009802 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9803 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009804 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9805 HFAILURE;
9806 if (res != 0) {
9807 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009808 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009809 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009810 "(#all | List of (extension | restriction | substitution))",
9811 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009812 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009813 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009814
9815exit:
9816 if (oldErrs != ctxt->nberrors)
9817 res = ctxt->err;
9818 return(res);
9819exit_failure:
9820 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009821}
9822
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009823/**
9824 * xmlSchemaParseSchemaTopLevel:
9825 * @ctxt: a schema validation context
9826 * @schema: the schemas
9827 * @nodes: the list of top level nodes
9828 *
9829 * Returns the internal XML Schema structure built from the resource or
9830 * NULL in case of error
9831 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009832static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009833xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9834 xmlSchemaPtr schema, xmlNodePtr nodes)
9835{
9836 xmlNodePtr child;
9837 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009838 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009839
9840 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009841 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009842
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009843 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009844 child = nodes;
9845 while ((IS_SCHEMA(child, "include")) ||
9846 (IS_SCHEMA(child, "import")) ||
9847 (IS_SCHEMA(child, "redefine")) ||
9848 (IS_SCHEMA(child, "annotation"))) {
9849 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009850 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009851 if (schema->annot == NULL)
9852 schema->annot = annot;
9853 else
9854 xmlSchemaFreeAnnot(annot);
9855 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009856 tmpOldErrs = ctxt->nberrors;
9857 res = xmlSchemaParseImport(ctxt, schema, child);
9858 HFAILURE;
9859 HSTOP(ctxt);
9860 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009861 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009862 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009863 tmpOldErrs = ctxt->nberrors;
9864 res = xmlSchemaParseInclude(ctxt, schema, child);
9865 HFAILURE;
9866 HSTOP(ctxt);
9867 if (tmpOldErrs != ctxt->nberrors)
Daniel Veillarddee23482008-04-11 12:58:43 +00009868 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009869 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009870 tmpOldErrs = ctxt->nberrors;
9871 res = xmlSchemaParseRedefine(ctxt, schema, child);
9872 HFAILURE;
9873 HSTOP(ctxt);
9874 if (tmpOldErrs != ctxt->nberrors)
9875 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009876 }
9877 child = child->next;
9878 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009879 /*
9880 * URGENT TODO: Change the functions to return int results.
9881 * We need especially to catch internal errors.
9882 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009883 while (child != NULL) {
9884 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009885 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009886 child = child->next;
9887 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009888 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009889 child = child->next;
9890 } else if (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009891 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009892 child = child->next;
9893 } else if (IS_SCHEMA(child, "attribute")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009894 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009895 child = child->next;
9896 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009897 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009898 child = child->next;
9899 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009900 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009901 child = child->next;
9902 } else if (IS_SCHEMA(child, "notation")) {
9903 xmlSchemaParseNotation(ctxt, schema, child);
9904 child = child->next;
9905 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009906 xmlSchemaPContentErr(ctxt,
9907 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009908 NULL, child->parent, child,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009909 NULL, "((include | import | redefine | annotation)*, "
9910 "(((simpleType | complexType | group | attributeGroup) "
9911 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009912 child = child->next;
9913 }
9914 while (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009915 /*
9916 * TODO: We should add all annotations.
9917 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +00009918 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009919 if (schema->annot == NULL)
9920 schema->annot = annot;
9921 else
9922 xmlSchemaFreeAnnot(annot);
9923 child = child->next;
9924 }
9925 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009926exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00009927 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009928 if (oldErrs != ctxt->nberrors)
9929 res = ctxt->err;
9930 return(res);
9931exit_failure:
9932 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009933}
9934
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009935static xmlSchemaSchemaRelationPtr
9936xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009937{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009938 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009939
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009940 ret = (xmlSchemaSchemaRelationPtr)
9941 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009942 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009943 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009944 return(NULL);
9945 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009946 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009947 return(ret);
9948}
9949
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009950#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009951static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009952xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009953{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009954 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009955}
9956#endif
9957
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009958static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009959xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9960{
9961 xmlSchemaRedefPtr prev;
9962
9963 while (redef != NULL) {
9964 prev = redef;
9965 redef = redef->next;
9966 xmlFree(prev);
9967 }
9968}
9969
9970static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009971xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9972{
9973 /*
9974 * After the construction context has been freed, there will be
9975 * no schema graph available any more. Only the schema buckets
9976 * will stay alive, which are put into the "schemasImports" and
9977 * "includes" slots of the xmlSchema.
9978 */
9979 if (con->buckets != NULL)
9980 xmlSchemaItemListFree(con->buckets);
9981 if (con->pending != NULL)
9982 xmlSchemaItemListFree(con->pending);
9983 if (con->substGroups != NULL)
Nick Wellnhofere03f0a12017-11-09 16:42:47 +01009984 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +00009985 if (con->redefs != NULL)
9986 xmlSchemaRedefListFree(con->redefs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009987 if (con->dict != NULL)
9988 xmlDictFree(con->dict);
9989 xmlFree(con);
9990}
9991
Daniel Veillarddee23482008-04-11 12:58:43 +00009992static xmlSchemaConstructionCtxtPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009993xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9994{
9995 xmlSchemaConstructionCtxtPtr ret;
9996
9997 ret = (xmlSchemaConstructionCtxtPtr)
9998 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9999 if (ret == NULL) {
10000 xmlSchemaPErrMemory(NULL,
10001 "allocating schema construction context", NULL);
10002 return (NULL);
10003 }
10004 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10005
10006 ret->buckets = xmlSchemaItemListCreate();
10007 if (ret->buckets == NULL) {
10008 xmlSchemaPErrMemory(NULL,
10009 "allocating list of schema buckets", NULL);
10010 xmlFree(ret);
10011 return (NULL);
10012 }
10013 ret->pending = xmlSchemaItemListCreate();
10014 if (ret->pending == NULL) {
10015 xmlSchemaPErrMemory(NULL,
10016 "allocating list of pending global components", NULL);
10017 xmlSchemaConstructionCtxtFree(ret);
10018 return (NULL);
10019 }
10020 ret->dict = dict;
10021 xmlDictReference(dict);
10022 return(ret);
10023}
10024
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010025static xmlSchemaParserCtxtPtr
10026xmlSchemaParserCtxtCreate(void)
10027{
10028 xmlSchemaParserCtxtPtr ret;
10029
10030 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10031 if (ret == NULL) {
10032 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10033 NULL);
10034 return (NULL);
10035 }
10036 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10037 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010038 ret->attrProhibs = xmlSchemaItemListCreate();
10039 if (ret->attrProhibs == NULL) {
10040 xmlFree(ret);
10041 return(NULL);
10042 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010043 return(ret);
10044}
10045
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010046/**
10047 * xmlSchemaNewParserCtxtUseDict:
10048 * @URL: the location of the schema
10049 * @dict: the dictionary to be used
10050 *
10051 * Create an XML Schemas parse context for that file/resource expected
10052 * to contain an XML Schemas file.
10053 *
10054 * Returns the parser context or NULL in case of error
10055 */
10056static xmlSchemaParserCtxtPtr
10057xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10058{
10059 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010060
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010061 ret = xmlSchemaParserCtxtCreate();
Daniel Veillarddee23482008-04-11 12:58:43 +000010062 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010063 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 ret->dict = dict;
Daniel Veillarddee23482008-04-11 12:58:43 +000010065 xmlDictReference(dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010066 if (URL != NULL)
10067 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010068 return (ret);
10069}
10070
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010071static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010072xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10073{
10074 if (vctxt->pctxt == NULL) {
10075 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010076 vctxt->pctxt =
10077 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010078 else
10079 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10080 if (vctxt->pctxt == NULL) {
10081 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10082 "failed to create a temp. parser context");
10083 return (-1);
10084 }
10085 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010086 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010087 vctxt->warning, vctxt->errCtxt);
10088 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10089 vctxt->errCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010090 }
10091 return (0);
10092}
10093
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010094/**
10095 * xmlSchemaGetSchemaBucket:
10096 * @pctxt: the schema parser context
10097 * @schemaLocation: the URI of the schema document
10098 *
10099 * Returns a schema bucket if it was already parsed.
10100 *
10101 * Returns a schema bucket if it was already parsed from
10102 * @schemaLocation, NULL otherwise.
10103 */
10104static xmlSchemaBucketPtr
10105xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10106 const xmlChar *schemaLocation)
10107{
10108 xmlSchemaBucketPtr cur;
10109 xmlSchemaItemListPtr list;
10110
10111 list = pctxt->constructor->buckets;
10112 if (list->nbItems == 0)
10113 return(NULL);
10114 else {
10115 int i;
10116 for (i = 0; i < list->nbItems; i++) {
10117 cur = (xmlSchemaBucketPtr) list->items[i];
10118 /* Pointer comparison! */
10119 if (cur->schemaLocation == schemaLocation)
10120 return(cur);
10121 }
10122 }
10123 return(NULL);
10124}
10125
10126static xmlSchemaBucketPtr
10127xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10128 const xmlChar *schemaLocation,
10129 const xmlChar *targetNamespace)
10130{
10131 xmlSchemaBucketPtr cur;
10132 xmlSchemaItemListPtr list;
10133
10134 list = pctxt->constructor->buckets;
10135 if (list->nbItems == 0)
10136 return(NULL);
10137 else {
10138 int i;
10139 for (i = 0; i < list->nbItems; i++) {
10140 cur = (xmlSchemaBucketPtr) list->items[i];
10141 /* Pointer comparison! */
10142 if ((cur->origTargetNamespace == NULL) &&
10143 (cur->schemaLocation == schemaLocation) &&
10144 (cur->targetNamespace == targetNamespace))
10145 return(cur);
10146 }
10147 }
10148 return(NULL);
10149}
10150
10151
10152#define IS_BAD_SCHEMA_DOC(b) \
10153 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10154
10155static xmlSchemaBucketPtr
10156xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10157 const xmlChar *targetNamespace,
10158 int imported)
10159{
10160 xmlSchemaBucketPtr cur;
10161 xmlSchemaItemListPtr list;
10162
10163 list = pctxt->constructor->buckets;
10164 if (list->nbItems == 0)
10165 return(NULL);
10166 else {
10167 int i;
10168 for (i = 0; i < list->nbItems; i++) {
10169 cur = (xmlSchemaBucketPtr) list->items[i];
10170 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10171 (cur->origTargetNamespace == targetNamespace) &&
10172 ((imported && cur->imported) ||
10173 ((!imported) && (!cur->imported))))
10174 return(cur);
10175 }
10176 }
10177 return(NULL);
10178}
10179
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010180static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010181xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10182 xmlSchemaPtr schema,
10183 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010184{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010185 int oldFlags;
10186 xmlDocPtr oldDoc;
10187 xmlNodePtr node;
10188 int ret, oldErrs;
10189 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000010190
10191 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010192 * Save old values; reset the *main* schema.
10193 * URGENT TODO: This is not good; move the per-document information
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000010194 * to the parser. Get rid of passing the main schema to the
10195 * parsing functions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010196 */
10197 oldFlags = schema->flags;
10198 oldDoc = schema->doc;
10199 if (schema->flags != 0)
10200 xmlSchemaClearSchemaDefaults(schema);
Daniel Veillarddee23482008-04-11 12:58:43 +000010201 schema->doc = bucket->doc;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010202 pctxt->schema = schema;
Daniel Veillarddee23482008-04-11 12:58:43 +000010203 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010204 * Keep the current target namespace on the parser *not* on the
10205 * main schema.
10206 */
10207 pctxt->targetNamespace = bucket->targetNamespace;
10208 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010209
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010210 if ((bucket->targetNamespace != NULL) &&
10211 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010212 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010213 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010214 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010215 pctxt->isS4S = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000010216 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010217 /* Mark it as parsed, even if parsing fails. */
10218 bucket->parsed++;
10219 /* Compile the schema doc. */
10220 node = xmlDocGetRootElement(bucket->doc);
10221 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10222 if (ret != 0)
10223 goto exit;
10224 /* An empty schema; just get out. */
10225 if (node->children == NULL)
10226 goto exit;
10227 oldErrs = pctxt->nberrors;
10228 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10229 if (ret != 0)
10230 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010231 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010232 * TODO: Not nice, but I'm not 100% sure we will get always an error
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010233 * as a result of the above functions; so better rely on pctxt->err
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010234 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010235 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010236 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10237 ret = pctxt->err;
10238 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010239 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010240
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010241exit:
10242 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10243 /* Restore schema values. */
10244 schema->doc = oldDoc;
10245 schema->flags = oldFlags;
10246 return(ret);
10247}
10248
10249static int
10250xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10251 xmlSchemaPtr schema,
10252 xmlSchemaBucketPtr bucket)
10253{
10254 xmlSchemaParserCtxtPtr newpctxt;
10255 int res = 0;
10256
10257 if (bucket == NULL)
10258 return(0);
10259 if (bucket->parsed) {
10260 PERROR_INT("xmlSchemaParseNewDoc",
10261 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010262 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010263 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010264 if (bucket->doc == NULL) {
10265 PERROR_INT("xmlSchemaParseNewDoc",
10266 "parsing a schema doc, but there's no doc");
10267 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000010268 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010269 if (pctxt->constructor == NULL) {
10270 PERROR_INT("xmlSchemaParseNewDoc",
10271 "no constructor");
10272 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000010273 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010274 /* Create and init the temporary parser context. */
10275 newpctxt = xmlSchemaNewParserCtxtUseDict(
10276 (const char *) bucket->schemaLocation, pctxt->dict);
10277 if (newpctxt == NULL)
10278 return(-1);
10279 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010280 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000010281 * TODO: Can we avoid that the parser knows about the main schema?
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010282 * It would be better if he knows about the current schema bucket
10283 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010284 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010285 newpctxt->schema = schema;
10286 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000010287 pctxt->errCtxt);
10288 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10289 pctxt->errCtxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010290 newpctxt->counter = pctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010291
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010292
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010293 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
Daniel Veillarddee23482008-04-11 12:58:43 +000010294
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010295 /* Channel back errors and cleanup the temporary parser context. */
10296 if (res != 0)
10297 pctxt->err = res;
10298 pctxt->nberrors += newpctxt->nberrors;
10299 pctxt->counter = newpctxt->counter;
Daniel Veillarddee23482008-04-11 12:58:43 +000010300 newpctxt->constructor = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010301 /* Free the parser context. */
10302 xmlSchemaFreeParserCtxt(newpctxt);
10303 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010304}
William M. Brack2f2a6632004-08-20 23:09:47 +000010305
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010306static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010307xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10308 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010309{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010310 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010311
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010312 if (cur == NULL) {
10313 bucket->relations = rel;
10314 return;
10315 }
10316 while (cur->next != NULL)
10317 cur = cur->next;
10318 cur->next = rel;
10319}
10320
10321
10322static const xmlChar *
10323xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10324 xmlNodePtr ctxtNode)
Daniel Veillarddee23482008-04-11 12:58:43 +000010325{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010326 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010327 * Build an absolute location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010328 */
Daniel Veillarddee23482008-04-11 12:58:43 +000010329 if (location != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010330 if (ctxtNode == NULL)
10331 return(location);
10332 else {
10333 xmlChar *base, *URI;
10334 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010335
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010336 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10337 if (base == NULL) {
10338 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10339 } else {
10340 URI = xmlBuildURI(location, base);
10341 xmlFree(base);
10342 }
10343 if (URI != NULL) {
10344 ret = xmlDictLookup(dict, URI, -1);
10345 xmlFree(URI);
10346 return(ret);
10347 }
10348 }
10349 }
10350 return(NULL);
10351}
Daniel Veillarddee23482008-04-11 12:58:43 +000010352
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010353
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010354
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010355/**
10356 * xmlSchemaAddSchemaDoc:
10357 * @pctxt: a schema validation context
10358 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010359 * @node: a subtree containing XML Schema information
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010360 *
10361 * Parse an included (and to-be-redefined) XML schema document.
10362 *
10363 * Returns 0 on success, a positive error code on errors and
10364 * -1 in case of an internal or API error.
10365 */
10366
10367static int
10368xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10369 int type, /* import or include or redefine */
10370 const xmlChar *schemaLocation,
10371 xmlDocPtr schemaDoc,
10372 const char *schemaBuffer,
10373 int schemaBufferLen,
10374 xmlNodePtr invokingNode,
Daniel Veillarddee23482008-04-11 12:58:43 +000010375 const xmlChar *sourceTargetNamespace,
10376 const xmlChar *importNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010377 xmlSchemaBucketPtr *bucket)
10378{
10379 const xmlChar *targetNamespace = NULL;
10380 xmlSchemaSchemaRelationPtr relation = NULL;
10381 xmlDocPtr doc = NULL;
10382 int res = 0, err = 0, located = 0, preserveDoc = 0;
10383 xmlSchemaBucketPtr bkt = NULL;
10384
10385 if (bucket != NULL)
10386 *bucket = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010387
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010388 switch (type) {
10389 case XML_SCHEMA_SCHEMA_IMPORT:
10390 case XML_SCHEMA_SCHEMA_MAIN:
10391 err = XML_SCHEMAP_SRC_IMPORT;
10392 break;
10393 case XML_SCHEMA_SCHEMA_INCLUDE:
10394 err = XML_SCHEMAP_SRC_INCLUDE;
10395 break;
10396 case XML_SCHEMA_SCHEMA_REDEFINE:
10397 err = XML_SCHEMAP_SRC_REDEFINE;
10398 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000010399 }
10400
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010401
10402 /* Special handling for the main schema:
10403 * skip the location and relation logic and just parse the doc.
10404 * We need just a bucket to be returned in this case.
Daniel Veillarddee23482008-04-11 12:58:43 +000010405 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010406 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
Daniel Veillarddee23482008-04-11 12:58:43 +000010407 goto doc_load;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010408
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010409 /* Note that we expect the location to be an absolute URI. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010410 if (schemaLocation != NULL) {
10411 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10412 if ((bkt != NULL) &&
10413 (pctxt->constructor->bucket == bkt)) {
10414 /* Report self-imports/inclusions/redefinitions. */
Daniel Veillarddee23482008-04-11 12:58:43 +000010415
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010416 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10417 invokingNode, NULL,
10418 "The schema must not import/include/redefine itself",
10419 NULL, NULL);
10420 goto exit;
10421 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010422 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010423 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010424 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010425 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010426 relation = xmlSchemaSchemaRelationCreate();
10427 if (relation == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010428 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010429 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10430 relation);
10431 relation->type = type;
10432
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010433 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010434 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010435 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010436 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010437 relation->importNamespace = importNamespace;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010438 if (schemaLocation == NULL) {
10439 /*
10440 * No location; this is just an import of the namespace.
10441 * Note that we don't assign a bucket to the relation
10442 * in this case.
10443 */
10444 goto exit;
10445 }
10446 targetNamespace = importNamespace;
10447 }
10448
10449 /* Did we already fetch the doc? */
Daniel Veillarddee23482008-04-11 12:58:43 +000010450 if (bkt != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010451 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010452 /*
10453 * We included/redefined and then try to import a schema,
10454 * but the new location provided for import was different.
10455 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010456 if (schemaLocation == NULL)
10457 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010458 if (!xmlStrEqual(schemaLocation,
10459 bkt->schemaLocation)) {
10460 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10461 invokingNode, NULL,
10462 "The schema document '%s' cannot be imported, since "
10463 "it was already included or redefined",
10464 schemaLocation, NULL);
10465 goto exit;
10466 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010467 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
Jason Childsd9960722009-08-07 19:01:32 +020010468 /*
10469 * We imported and then try to include/redefine a schema,
10470 * but the new location provided for the include/redefine
10471 * was different.
10472 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010473 if (schemaLocation == NULL)
10474 schemaLocation = BAD_CAST "in_memory_buffer";
Jason Childsd9960722009-08-07 19:01:32 +020010475 if (!xmlStrEqual(schemaLocation,
10476 bkt->schemaLocation)) {
10477 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10478 invokingNode, NULL,
10479 "The schema document '%s' cannot be included or "
10480 "redefined, since it was already imported",
10481 schemaLocation, NULL);
10482 goto exit;
10483 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010484 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010485 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010486
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010487 if (WXS_IS_BUCKET_IMPMAIN(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010488 /*
10489 * Given that the schemaLocation [attribute] is only a hint, it is open
10490 * to applications to ignore all but the first <import> for a given
Jan Pokorný761c9e92013-11-29 23:26:27 +010010491 * namespace, regardless of the `actual value` of schemaLocation, but
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010492 * such a strategy risks missing useful information when new
10493 * schemaLocations are offered.
10494 *
10495 * We will use the first <import> that comes with a location.
10496 * Further <import>s *with* a location, will result in an error.
10497 * TODO: Better would be to just report a warning here, but
10498 * we'll try it this way until someone complains.
10499 *
10500 * Schema Document Location Strategy:
10501 * 3 Based on the namespace name, identify an existing schema document,
10502 * either as a resource which is an XML document or a <schema> element
10503 * information item, in some local schema repository;
10504 * 5 Attempt to resolve the namespace name to locate such a resource.
10505 *
10506 * NOTE: (3) and (5) are not supported.
Daniel Veillarddee23482008-04-11 12:58:43 +000010507 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010508 if (bkt != NULL) {
10509 relation->bucket = bkt;
10510 goto exit;
10511 }
10512 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10513 importNamespace, 1);
10514
Daniel Veillarddee23482008-04-11 12:58:43 +000010515 if (bkt != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010516 relation->bucket = bkt;
10517 if (bkt->schemaLocation == NULL) {
10518 /* First given location of the schema; load the doc. */
10519 bkt->schemaLocation = schemaLocation;
10520 } else {
10521 if (!xmlStrEqual(schemaLocation,
10522 bkt->schemaLocation)) {
10523 /*
10524 * Additional location given; just skip it.
10525 * URGENT TODO: We should report a warning here.
10526 * res = XML_SCHEMAP_SRC_IMPORT;
10527 */
Daniel Veillard734e7662007-06-26 11:30:31 +000010528 if (schemaLocation == NULL)
10529 schemaLocation = BAD_CAST "in_memory_buffer";
10530
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010531 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10532 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10533 invokingNode, NULL,
10534 "Skipping import of schema located at '%s' for the "
10535 "namespace '%s', since this namespace was already "
10536 "imported with the schema located at '%s'",
10537 schemaLocation, importNamespace, bkt->schemaLocation);
10538 }
10539 goto exit;
10540 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010541 }
10542 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010543 * No bucket + first location: load the doc and create a
10544 * bucket.
10545 */
10546 } else {
10547 /* <include> and <redefine> */
10548 if (bkt != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000010549
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010550 if ((bkt->origTargetNamespace == NULL) &&
10551 (bkt->targetNamespace != sourceTargetNamespace)) {
10552 xmlSchemaBucketPtr chamel;
Daniel Veillarddee23482008-04-11 12:58:43 +000010553
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010554 /*
10555 * Chameleon include/redefine: skip loading only if it was
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010556 * already build for the targetNamespace of the including
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010557 * schema.
10558 */
10559 /*
10560 * URGENT TODO: If the schema is a chameleon-include then copy
10561 * the components into the including schema and modify the
10562 * targetNamespace of those components, do nothing otherwise.
10563 * NOTE: This is currently worked-around by compiling the
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010564 * chameleon for every distinct including targetNamespace; thus
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010565 * not performant at the moment.
10566 * TODO: Check when the namespace in wildcards for chameleons
10567 * needs to be converted: before we built wildcard intersections
10568 * or after.
10569 * Answer: after!
10570 */
10571 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10572 schemaLocation, sourceTargetNamespace);
10573 if (chamel != NULL) {
10574 /* A fitting chameleon was already parsed; NOP. */
10575 relation->bucket = chamel;
10576 goto exit;
10577 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010578 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010579 * We need to parse the chameleon again for a different
10580 * targetNamespace.
10581 * CHAMELEON TODO: Optimize this by only parsing the
10582 * chameleon once, and then copying the components to
10583 * the new targetNamespace.
10584 */
10585 bkt = NULL;
10586 } else {
10587 relation->bucket = bkt;
10588 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000010589 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010590 }
10591 }
10592 if ((bkt != NULL) && (bkt->doc != NULL)) {
10593 PERROR_INT("xmlSchemaAddSchemaDoc",
10594 "trying to load a schema doc, but a doc is already "
10595 "assigned to the schema bucket");
10596 goto exit_failure;
10597 }
10598
10599doc_load:
10600 /*
10601 * Load the document.
10602 */
10603 if (schemaDoc != NULL) {
10604 doc = schemaDoc;
10605 /* Don' free this one, since it was provided by the caller. */
10606 preserveDoc = 1;
10607 /* TODO: Does the context or the doc hold the location? */
10608 if (schemaDoc->URL != NULL)
10609 schemaLocation = xmlDictLookup(pctxt->dict,
10610 schemaDoc->URL, -1);
Daniel Veillard734e7662007-06-26 11:30:31 +000010611 else
10612 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010613 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10614 xmlParserCtxtPtr parserCtxt;
10615
10616 parserCtxt = xmlNewParserCtxt();
10617 if (parserCtxt == NULL) {
10618 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10619 "allocating a parser context", NULL);
10620 goto exit_failure;
10621 }
10622 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10623 /*
10624 * TODO: Do we have to burden the schema parser dict with all
10625 * the content of the schema doc?
10626 */
10627 xmlDictFree(parserCtxt->dict);
10628 parserCtxt->dict = pctxt->dict;
10629 xmlDictReference(parserCtxt->dict);
10630 }
10631 if (schemaLocation != NULL) {
10632 /* Parse from file. */
10633 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10634 NULL, SCHEMAS_PARSE_OPTIONS);
10635 } else if (schemaBuffer != NULL) {
10636 /* Parse from memory buffer. */
10637 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10638 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
Rob Richards410d2c42009-09-24 11:00:16 -040010639 schemaLocation = BAD_CAST "in_memory_buffer";
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010640 if (doc != NULL)
Rob Richards410d2c42009-09-24 11:00:16 -040010641 doc->URL = xmlStrdup(schemaLocation);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010642 }
10643 /*
10644 * For <import>:
10645 * 2.1 The referent is (a fragment of) a resource which is an
10646 * XML document (see clause 1.1), which in turn corresponds to
10647 * a <schema> element information item in a well-formed information
10648 * set, which in turn corresponds to a valid schema.
10649 * TODO: (2.1) fragments of XML documents are not supported.
10650 *
10651 * 2.2 The referent is a <schema> element information item in
10652 * a well-formed information set, which in turn corresponds
10653 * to a valid schema.
10654 * TODO: (2.2) is not supported.
10655 */
10656 if (doc == NULL) {
10657 xmlErrorPtr lerr;
10658 lerr = xmlGetLastError();
10659 /*
10660 * Check if this a parser error, or if the document could
10661 * just not be located.
10662 * TODO: Try to find specific error codes to react only on
10663 * localisation failures.
10664 */
10665 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10666 /*
10667 * We assume a parser error here.
10668 */
10669 located = 1;
10670 /* TODO: Error code ?? */
10671 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10672 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10673 invokingNode, NULL,
10674 "Failed to parse the XML resource '%s'",
Daniel Veillard734e7662007-06-26 11:30:31 +000010675 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010676 }
10677 }
10678 xmlFreeParserCtxt(parserCtxt);
10679 if ((doc == NULL) && located)
10680 goto exit_error;
10681 } else {
10682 xmlSchemaPErr(pctxt, NULL,
10683 XML_SCHEMAP_NOTHING_TO_PARSE,
10684 "No information for parsing was provided with the "
10685 "given schema parser context.\n",
10686 NULL, NULL);
10687 goto exit_failure;
10688 }
10689 /*
10690 * Preprocess the document.
10691 */
10692 if (doc != NULL) {
10693 xmlNodePtr docElem = NULL;
10694
Daniel Veillarddee23482008-04-11 12:58:43 +000010695 located = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010696 docElem = xmlDocGetRootElement(doc);
10697 if (docElem == NULL) {
10698 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
Daniel Veillarddee23482008-04-11 12:58:43 +000010699 invokingNode, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010700 "The document '%s' has no document element",
10701 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010702 goto exit_error;
10703 }
10704 /*
10705 * Remove all the blank text nodes.
10706 */
10707 xmlSchemaCleanupDoc(pctxt, docElem);
10708 /*
10709 * Check the schema's top level element.
10710 */
10711 if (!IS_SCHEMA(docElem, "schema")) {
10712 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10713 invokingNode, NULL,
10714 "The XML document '%s' is not a schema document",
10715 schemaLocation, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010716 goto exit_error;
10717 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010718 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010719 * Note that we don't apply a type check for the
10720 * targetNamespace value here.
10721 */
10722 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10723 "targetNamespace");
10724 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010725
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010726/* after_doc_loading: */
10727 if ((bkt == NULL) && located) {
10728 /* Only create a bucket if the schema was located. */
10729 bkt = xmlSchemaBucketCreate(pctxt, type,
10730 targetNamespace);
10731 if (bkt == NULL)
10732 goto exit_failure;
10733 }
10734 if (bkt != NULL) {
10735 bkt->schemaLocation = schemaLocation;
10736 bkt->located = located;
10737 if (doc != NULL) {
10738 bkt->doc = doc;
10739 bkt->targetNamespace = targetNamespace;
10740 bkt->origTargetNamespace = targetNamespace;
10741 if (preserveDoc)
10742 bkt->preserveDoc = 1;
10743 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010744 if (WXS_IS_BUCKET_IMPMAIN(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010745 bkt->imported++;
10746 /*
10747 * Add it to the graph of schemas.
10748 */
10749 if (relation != NULL)
10750 relation->bucket = bkt;
10751 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010752
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010753exit:
10754 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010755 * Return the bucket explicitly; this is needed for the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010756 * main schema.
10757 */
10758 if (bucket != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000010759 *bucket = bkt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010760 return (0);
10761
10762exit_error:
10763 if ((doc != NULL) && (! preserveDoc)) {
10764 xmlFreeDoc(doc);
10765 if (bkt != NULL)
10766 bkt->doc = NULL;
10767 }
10768 return(pctxt->err);
10769
10770exit_failure:
10771 if ((doc != NULL) && (! preserveDoc)) {
10772 xmlFreeDoc(doc);
10773 if (bkt != NULL)
10774 bkt->doc = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000010775 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010776 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010777}
10778
William M. Brack2f2a6632004-08-20 23:09:47 +000010779/**
10780 * xmlSchemaParseImport:
10781 * @ctxt: a schema validation context
10782 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070010783 * @node: a subtree containing XML Schema information
William M. Brack2f2a6632004-08-20 23:09:47 +000010784 *
10785 * parse a XML schema Import definition
10786 * *WARNING* this interface is highly subject to change
10787 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010788 * Returns 0 in case of success, a positive error code if
10789 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +000010790 */
10791static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010792xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +000010793 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010794{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010795 xmlNodePtr child;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010796 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10797 const xmlChar *thisTargetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +000010798 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010799 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010800 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010801
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010802 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +000010803 return (-1);
10804
10805 /*
10806 * Check for illegal attributes.
10807 */
10808 attr = node->properties;
10809 while (attr != NULL) {
10810 if (attr->ns == NULL) {
10811 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10812 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10813 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010814 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010815 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010816 }
10817 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010818 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010819 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010820 }
10821 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010822 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010823 /*
10824 * Extract and validate attributes.
10825 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010826 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010827 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010828 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010829 xmlSchemaPSimpleTypeErr(pctxt,
10830 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010831 NULL, node,
10832 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010833 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010834 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010835 }
10836
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010837 if (xmlSchemaPValAttr(pctxt, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010838 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +000010839 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010840 xmlSchemaPSimpleTypeErr(pctxt,
10841 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010842 NULL, node,
10843 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Gauravf3d79412013-11-28 22:53:54 +080010844 NULL, schemaLocation, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010845 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010846 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010847 /*
10848 * And now for the children...
10849 */
10850 child = node->children;
10851 if (IS_SCHEMA(child, "annotation")) {
10852 /*
10853 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010854 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +000010855 */
10856 child = child->next;
10857 }
10858 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010859 xmlSchemaPContentErr(pctxt,
10860 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010861 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010862 "(annotation?)");
10863 }
10864 /*
10865 * Apply additional constraints.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010866 *
10867 * Note that it is important to use the original @targetNamespace
10868 * (or none at all), to rule out imports of schemas _with_ a
10869 * @targetNamespace if the importing schema is a chameleon schema
10870 * (with no @targetNamespace).
William M. Brack2f2a6632004-08-20 23:09:47 +000010871 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010872 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010873 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010874 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010010875 * 1.1 If the namespace [attribute] is present, then its `actual value`
10876 * must not match the `actual value` of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +000010877 * targetNamespace [attribute].
10878 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010879 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010880 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010881 XML_SCHEMAP_SRC_IMPORT_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010882 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010883 "The value of the attribute 'namespace' must not match "
10884 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010885 thisTargetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010886 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010887 }
10888 } else {
10889 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010890 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +000010891 * <schema> must have a targetNamespace [attribute].
10892 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010893 if (thisTargetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010894 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010895 XML_SCHEMAP_SRC_IMPORT_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010896 NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +000010897 "The attribute 'namespace' must be existent if "
10898 "the importing schema has no target namespace",
10899 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010900 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +000010901 }
10902 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010903 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000010904 * Locate and acquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +000010905 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010906 if (schemaLocation != NULL)
10907 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10908 schemaLocation, node);
10909 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010910 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010911 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010912
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010913 if (ret != 0)
10914 return(ret);
10915
10916 /*
10917 * For <import>: "It is *not* an error for the application
10918 * schema reference strategy to fail."
10919 * So just don't parse if no schema document was found.
10920 * Note that we will get no bucket if the schema could not be
10921 * located or if there was no schemaLocation.
10922 */
10923 if ((bucket == NULL) && (schemaLocation != NULL)) {
10924 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10925 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10926 node, NULL,
10927 "Failed to locate a schema at location '%s'. "
10928 "Skipping the import", schemaLocation, NULL, NULL);
10929 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010930
10931 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010932 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10933 }
Daniel Veillarddee23482008-04-11 12:58:43 +000010934
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010935 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000010936}
10937
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010938static int
10939xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10940 xmlSchemaPtr schema,
10941 xmlNodePtr node,
10942 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010943 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010944{
10945 xmlAttrPtr attr;
10946
10947 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10948 (schemaLocation == NULL))
10949 return (-1);
10950
10951 *schemaLocation = NULL;
10952 /*
10953 * Check for illegal attributes.
10954 * Applies for both <include> and <redefine>.
10955 */
10956 attr = node->properties;
10957 while (attr != NULL) {
10958 if (attr->ns == NULL) {
10959 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10960 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10961 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010963 }
10964 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10965 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010966 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010967 }
10968 attr = attr->next;
10969 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010970 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010971 /*
10972 * Preliminary step, extract the URI-Reference and make an URI
10973 * from the base.
10974 */
10975 /*
10976 * Attribute "schemaLocation" is mandatory.
10977 */
10978 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10979 if (attr != NULL) {
10980 xmlChar *base = NULL;
10981 xmlChar *uri = NULL;
10982
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000010983 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010984 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10985 (const xmlChar **) schemaLocation) != 0)
10986 goto exit_error;
10987 base = xmlNodeGetBase(node->doc, node);
10988 if (base == NULL) {
10989 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10990 } else {
10991 uri = xmlBuildURI(*schemaLocation, base);
10992 xmlFree(base);
10993 }
10994 if (uri == NULL) {
10995 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10996 "could not build an URI from the schemaLocation")
10997 goto exit_failure;
10998 }
10999 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11000 xmlFree(uri);
11001 } else {
11002 xmlSchemaPMissingAttrErr(pctxt,
11003 XML_SCHEMAP_S4S_ATTR_MISSING,
11004 NULL, node, "schemaLocation", NULL);
11005 goto exit_error;
11006 }
11007 /*
11008 * Report self-inclusion and self-redefinition.
11009 */
11010 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011011 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011012 xmlSchemaPCustomErr(pctxt,
11013 XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011014 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011015 "The schema document '%s' cannot redefine itself.",
Daniel Veillarddee23482008-04-11 12:58:43 +000011016 *schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011017 } else {
11018 xmlSchemaPCustomErr(pctxt,
11019 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011020 NULL, node,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011021 "The schema document '%s' cannot include itself.",
11022 *schemaLocation);
11023 }
11024 goto exit_error;
11025 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011026
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011027 return(0);
11028exit_error:
11029 return(pctxt->err);
11030exit_failure:
11031 return(-1);
11032}
11033
11034static int
11035xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11036 xmlSchemaPtr schema,
11037 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011038 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011039{
11040 xmlNodePtr child = NULL;
11041 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011042 int res = 0; /* hasRedefinitions = 0 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011043 int isChameleon = 0, wasChameleon = 0;
11044 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011045
11046 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11047 return (-1);
11048
11049 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011050 * Parse attributes. Note that the returned schemaLocation will
11051 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011052 */
11053 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011054 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011055 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000011056 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011057 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011058 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011059 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011060 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11061 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011062 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000011063 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011064 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011065 * If we get no schema bucket back, then this means that the schema
11066 * document could not be located or was broken XML or was not
11067 * a schema document.
Daniel Veillarddee23482008-04-11 12:58:43 +000011068 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011069 if ((bucket == NULL) || (bucket->doc == NULL)) {
11070 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11071 /*
11072 * WARNING for <include>:
11073 * We will raise an error if the schema cannot be located
11074 * for inclusions, since the that was the feedback from the
11075 * schema people. I.e. the following spec piece will *not* be
11076 * satisfied:
Jan Pokorný761c9e92013-11-29 23:26:27 +010011077 * SPEC src-include: "It is not an error for the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011078 * schemaLocation [attribute] to fail to resolve it all, in which
11079 * case no corresponding inclusion is performed.
11080 * So do we need a warning report here?"
11081 */
11082 res = XML_SCHEMAP_SRC_INCLUDE;
11083 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11084 node, NULL,
11085 "Failed to load the document '%s' for inclusion",
11086 schemaLocation, NULL);
11087 } else {
11088 /*
11089 * NOTE: This was changed to raise an error even if no redefinitions
11090 * are specified.
11091 *
11092 * SPEC src-redefine (1)
11093 * "If there are any element information items among the [children]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011094 * other than <annotation> then the `actual value` of the
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011095 * schemaLocation [attribute] must successfully resolve."
11096 * TODO: Ask the WG if a the location has always to resolve
11097 * here as well!
11098 */
11099 res = XML_SCHEMAP_SRC_REDEFINE;
11100 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11101 node, NULL,
11102 "Failed to load the document '%s' for redefinition",
11103 schemaLocation, NULL);
11104 }
11105 } else {
11106 /*
11107 * Check targetNamespace sanity before parsing the new schema.
11108 * TODO: Note that we won't check further content if the
11109 * targetNamespace was bad.
Daniel Veillarddee23482008-04-11 12:58:43 +000011110 */
11111 if (bucket->origTargetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011112 /*
11113 * SPEC src-include (2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010011114 * "SII has a targetNamespace [attribute], and its `actual
11115 * value` is identical to the `actual value` of the targetNamespace
11116 * [attribute] of SII' (which must have such an [attribute])."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011117 */
11118 if (pctxt->targetNamespace == NULL) {
11119 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11120 XML_SCHEMAP_SRC_INCLUDE,
11121 node, NULL,
11122 "The target namespace of the included/redefined schema "
11123 "'%s' has to be absent, since the including/redefining "
11124 "schema has no target namespace",
11125 schemaLocation, NULL);
11126 goto exit_error;
11127 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11128 pctxt->targetNamespace)) {
11129 /* TODO: Change error function. */
11130 xmlSchemaPCustomErrExt(pctxt,
11131 XML_SCHEMAP_SRC_INCLUDE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011132 NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011133 "The target namespace '%s' of the included/redefined "
11134 "schema '%s' differs from '%s' of the "
11135 "including/redefining schema",
11136 bucket->origTargetNamespace, schemaLocation,
11137 pctxt->targetNamespace);
11138 goto exit_error;
11139 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011140 } else if (pctxt->targetNamespace != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011141 /*
11142 * Chameleons: the original target namespace will
11143 * differ from the resulting namespace.
11144 */
11145 isChameleon = 1;
11146 if (bucket->parsed &&
Jason Childsedc68aa2009-08-07 20:29:33 +020011147 bucket->origTargetNamespace != NULL) {
11148 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11149 XML_SCHEMAP_SRC_INCLUDE,
11150 node, NULL,
11151 "The target namespace of the included/redefined schema "
11152 "'%s' has to be absent or the same as the "
11153 "including/redefining schema's target namespace",
11154 schemaLocation, NULL);
11155 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011156 }
11157 bucket->targetNamespace = pctxt->targetNamespace;
11158 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011159 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011160 /*
11161 * Parse the schema.
Daniel Veillarddee23482008-04-11 12:58:43 +000011162 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011163 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11164 if (isChameleon) {
11165 /* TODO: Get rid of this flag on the schema itself. */
11166 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11167 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11168 } else
11169 wasChameleon = 1;
11170 }
11171 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11172 /* Restore chameleon flag. */
11173 if (isChameleon && (!wasChameleon))
11174 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11175 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011176 /*
11177 * And now for the children...
11178 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011179 child = node->children;
11180 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011181 /*
11182 * Parse (simpleType | complexType | group | attributeGroup))*
11183 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011184 pctxt->redefined = bucket;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011185 /*
11186 * How to proceed if the redefined schema was not located?
11187 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011188 pctxt->isRedefine = 1;
11189 while (IS_SCHEMA(child, "annotation") ||
11190 IS_SCHEMA(child, "simpleType") ||
11191 IS_SCHEMA(child, "complexType") ||
11192 IS_SCHEMA(child, "group") ||
11193 IS_SCHEMA(child, "attributeGroup")) {
11194 if (IS_SCHEMA(child, "annotation")) {
11195 /*
11196 * TODO: discard or not?
11197 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011198 } else if (IS_SCHEMA(child, "simpleType")) {
11199 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11200 } else if (IS_SCHEMA(child, "complexType")) {
11201 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011202 /* hasRedefinitions = 1; */
Daniel Veillarddee23482008-04-11 12:58:43 +000011203 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011204 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011205 xmlSchemaParseModelGroupDefinition(pctxt,
11206 schema, child);
11207 } else if (IS_SCHEMA(child, "attributeGroup")) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000011208 /* hasRedefinitions = 1; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011209 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11210 child);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011211 }
11212 child = child->next;
11213 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011214 pctxt->redefined = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011215 pctxt->isRedefine = 0;
11216 } else {
11217 if (IS_SCHEMA(child, "annotation")) {
11218 /*
11219 * TODO: discard or not?
11220 */
11221 child = child->next;
11222 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011223 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011224 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011225 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011226 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11227 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011228 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011229 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11230 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011231 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011232 NULL, node, child, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011233 "(annotation?)");
Daniel Veillarddee23482008-04-11 12:58:43 +000011234 }
11235 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011236 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011237
11238exit_error:
11239 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011240}
11241
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011242static int
11243xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11244 xmlNodePtr node)
11245{
11246 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011247#ifndef ENABLE_REDEFINE
11248 TODO
11249 return(0);
11250#endif
11251 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11252 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011253 if (res != 0)
11254 return(res);
11255 return(0);
11256}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011257
11258static int
11259xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11260 xmlNodePtr node)
11261{
11262 int res;
11263
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011264 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11265 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011266 if (res != 0)
11267 return(res);
11268 return(0);
11269}
11270
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011271/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011272 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011273 * @ctxt: a schema validation context
11274 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070011275 * @node: a subtree containing XML Schema information
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011276 * @type: the "compositor" type
11277 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000011278 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011279 * parse a XML schema Sequence definition.
11280 * Applies parts of:
11281 * Schema Representation Constraint:
11282 * Redefinition Constraints and Semantics (src-redefine)
11283 * (6.1), (6.1.1), (6.1.2)
11284 *
Daniel Veillarddee23482008-04-11 12:58:43 +000011285 * Schema Component Constraint:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011286 * All Group Limited (cos-all-limited) (2)
11287 * TODO: Actually this should go to component-level checks,
11288 * but is done here due to performance. Move it to an other layer
11289 * is schema construction via an API is implemented.
11290 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011291 * *WARNING* this interface is highly subject to change
11292 *
William M. Bracke7091952004-05-11 15:09:58 +000011293 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000011294 * 1 in case of success.
11295 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011296static xmlSchemaTreeItemPtr
11297xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11298 xmlNodePtr node, xmlSchemaTypeType type,
11299 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000011300{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011301 xmlSchemaModelGroupPtr item;
11302 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011303 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011304 xmlAttrPtr attr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011305 int min = 1, max = 1, isElemRef, hasRefs = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011306
11307 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011308 return (NULL);
11309 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000011311 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011312 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 if (item == NULL)
11314 return (NULL);
11315
11316 if (withParticle) {
11317 if (type == XML_SCHEMA_TYPE_ALL) {
11318 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011319 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011320 } else {
11321 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011322 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11323 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11324 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011325 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011326 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11327 /*
11328 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011329 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000011330 particle = xmlSchemaAddParticle(ctxt, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011331 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011332 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 particle->children = (xmlSchemaTreeItemPtr) item;
11334 /*
11335 * Check for illegal attributes.
11336 */
11337 attr = node->properties;
11338 while (attr != NULL) {
11339 if (attr->ns == NULL) {
11340 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11341 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11342 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011343 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011344 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011345 }
11346 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011347 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011348 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011349 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011350 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000011351 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 } else {
11353 /*
11354 * Check for illegal attributes.
11355 */
11356 attr = node->properties;
11357 while (attr != NULL) {
11358 if (attr->ns == NULL) {
11359 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011360 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 }
11363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011364 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011366 }
11367 attr = attr->next;
11368 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011370
William M. Brack2f2a6632004-08-20 23:09:47 +000011371 /*
11372 * Extract and validate attributes.
11373 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011374 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011375 /*
11376 * And now for the children...
11377 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011378 child = node->children;
11379 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011380 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011381 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011382 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011383 if (type == XML_SCHEMA_TYPE_ALL) {
11384 xmlSchemaParticlePtr part, last = NULL;
11385
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011386 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011387 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011388 schema, child, &isElemRef, 0);
11389 /*
11390 * SPEC cos-all-limited (2)
11391 * "The {max occurs} of all the particles in the {particles}
11392 * of the ('all') group must be 0 or 1.
11393 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 if (part != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011395 if (isElemRef)
11396 hasRefs++;
11397 if (part->minOccurs > 1) {
11398 xmlSchemaPCustomErr(ctxt,
11399 XML_SCHEMAP_COS_ALL_LIMITED,
11400 NULL, child,
11401 "Invalid value for minOccurs (must be 0 or 1)",
11402 NULL);
11403 /* Reset to 1. */
11404 part->minOccurs = 1;
11405 }
11406 if (part->maxOccurs > 1) {
11407 xmlSchemaPCustomErr(ctxt,
11408 XML_SCHEMAP_COS_ALL_LIMITED,
11409 NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 "Invalid value for maxOccurs (must be 0 or 1)",
11411 NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011412 /* Reset to 1. */
11413 part->maxOccurs = 1;
11414 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011415 if (last == NULL)
11416 item->children = (xmlSchemaTreeItemPtr) part;
11417 else
11418 last->next = (xmlSchemaTreeItemPtr) part;
11419 last = part;
11420 }
11421 child = child->next;
11422 }
11423 if (child != NULL) {
11424 xmlSchemaPContentErr(ctxt,
11425 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011426 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011427 "(annotation?, (annotation?, element*)");
11428 }
11429 } else {
11430 /* choice + sequence */
11431 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11432
11433 while ((IS_SCHEMA(child, "element")) ||
11434 (IS_SCHEMA(child, "group")) ||
11435 (IS_SCHEMA(child, "any")) ||
11436 (IS_SCHEMA(child, "choice")) ||
11437 (IS_SCHEMA(child, "sequence"))) {
11438
11439 if (IS_SCHEMA(child, "element")) {
11440 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011441 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11442 if (part && isElemRef)
11443 hasRefs++;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011444 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011445 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011446 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011447 if (part != NULL)
11448 hasRefs++;
11449 /*
11450 * Handle redefinitions.
11451 */
11452 if (ctxt->isRedefine && ctxt->redef &&
11453 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11454 part && part->children)
11455 {
11456 if ((xmlSchemaGetQNameRefName(part->children) ==
11457 ctxt->redef->refName) &&
11458 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11459 ctxt->redef->refTargetNs))
11460 {
11461 /*
11462 * SPEC src-redefine:
11463 * (6.1) "If it has a <group> among its contents at
Jan Pokorný761c9e92013-11-29 23:26:27 +010011464 * some level the `actual value` of whose ref
11465 * [attribute] is the same as the `actual value` of
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011466 * its own name attribute plus target namespace, then
11467 * all of the following must be true:"
11468 * (6.1.1) "It must have exactly one such group."
11469 */
11470 if (ctxt->redefCounter != 0) {
11471 xmlChar *str = NULL;
11472
11473 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11474 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11475 "The redefining model group definition "
11476 "'%s' must not contain more than one "
11477 "reference to the redefined definition",
11478 xmlSchemaFormatQName(&str,
11479 ctxt->redef->refTargetNs,
11480 ctxt->redef->refName),
11481 NULL);
11482 FREE_AND_NULL(str)
11483 part = NULL;
11484 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11485 ((WXS_PARTICLE(part))->maxOccurs != 1))
11486 {
11487 xmlChar *str = NULL;
11488 /*
11489 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010011490 * (6.1.2) "The `actual value` of both that
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011491 * group's minOccurs and maxOccurs [attribute]
Jan Pokorný761c9e92013-11-29 23:26:27 +010011492 * must be 1 (or `absent`).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011493 */
11494 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11495 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11496 "The redefining model group definition "
11497 "'%s' must not contain a reference to the "
11498 "redefined definition with a "
11499 "maxOccurs/minOccurs other than 1",
11500 xmlSchemaFormatQName(&str,
11501 ctxt->redef->refTargetNs,
11502 ctxt->redef->refName),
11503 NULL);
11504 FREE_AND_NULL(str)
11505 part = NULL;
11506 }
11507 ctxt->redef->reference = WXS_BASIC_CAST part;
11508 ctxt->redefCounter++;
Daniel Veillarddee23482008-04-11 12:58:43 +000011509 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011510 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011512 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 xmlSchemaParseAny(ctxt, schema, child);
11514 } else if (IS_SCHEMA(child, "choice")) {
11515 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11516 XML_SCHEMA_TYPE_CHOICE, 1);
11517 } else if (IS_SCHEMA(child, "sequence")) {
11518 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11519 XML_SCHEMA_TYPE_SEQUENCE, 1);
11520 }
11521 if (part != NULL) {
11522 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011524 else
11525 last->next = part;
11526 last = part;
11527 }
11528 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 if (child != NULL) {
11531 xmlSchemaPContentErr(ctxt,
11532 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011533 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011534 "(annotation?, (element | group | choice | sequence | any)*)");
11535 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011536 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011537 if ((max == 0) && (min == 0))
11538 return (NULL);
11539 if (hasRefs) {
11540 /*
11541 * We need to resolve references.
11542 */
11543 WXS_ADD_PENDING(ctxt, item);
11544 }
11545 if (withParticle)
Daniel Veillarddee23482008-04-11 12:58:43 +000011546 return ((xmlSchemaTreeItemPtr) particle);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011547 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011548 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000011549}
11550
11551/**
11552 * xmlSchemaParseRestriction:
11553 * @ctxt: a schema validation context
11554 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070011555 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +000011556 *
11557 * parse a XML schema Restriction definition
11558 * *WARNING* this interface is highly subject to change
11559 *
11560 * Returns the type definition or NULL in case of error
11561 */
11562static xmlSchemaTypePtr
11563xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011564 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011565{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011566 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011567 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000011568 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011569
11570 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11571 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011572 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573 type = ctxt->ctxtType;
11574 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011575
11576 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011577 * Check for illegal attributes.
11578 */
11579 attr = node->properties;
11580 while (attr != NULL) {
11581 if (attr->ns == NULL) {
11582 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11583 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011584 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011585 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011586 }
11587 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011588 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000011590 }
11591 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011592 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011593 /*
11594 * Extract and validate attributes.
11595 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011596 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000011597 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000011598 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000011599 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011600 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011601 * Extract the base type. The "base" attribute is mandatory if inside
11602 * a complex type or if redefining.
11603 *
11604 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011605 * among its [children]), the simple type definition which is
Jan Pokorný761c9e92013-11-29 23:26:27 +010011606 * the {content type} of the type definition `resolved` to by
11607 * the `actual value` of the base [attribute]"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011608 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011609 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011610 &(type->baseNs), &(type->base)) == 0)
11611 {
11612 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11613 xmlSchemaPMissingAttrErr(ctxt,
11614 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011615 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011616 } else if ((ctxt->isRedefine) &&
11617 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11618 {
11619 if (type->base == NULL) {
11620 xmlSchemaPMissingAttrErr(ctxt,
11621 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011622 NULL, node, "base", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011623 } else if ((! xmlStrEqual(type->base, type->name)) ||
11624 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11625 {
11626 xmlChar *str1 = NULL, *str2 = NULL;
11627 /*
11628 * REDEFINE: SPEC src-redefine (5)
11629 * "Within the [children], each <simpleType> must have a
Jan Pokorný761c9e92013-11-29 23:26:27 +010011630 * <restriction> among its [children] ... the `actual value` of
11631 * whose base [attribute] must be the same as the `actual value`
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011632 * of its own name attribute plus target namespace;"
11633 */
11634 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011635 NULL, node, "This is a redefinition, but the QName "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011636 "value '%s' of the 'base' attribute does not match the "
11637 "type's designation '%s'",
11638 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
Daniel Veillardfef73a52006-03-27 09:38:57 +000011639 xmlSchemaFormatQName(&str2, type->targetNamespace,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011640 type->name), NULL);
11641 FREE_AND_NULL(str1);
11642 FREE_AND_NULL(str2);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011643 /* Avoid confusion and erase the values. */
11644 type->base = NULL;
11645 type->baseNs = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011646 }
Daniel Veillarddee23482008-04-11 12:58:43 +000011647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011648 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011649 /*
11650 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011651 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011652 child = node->children;
11653 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011654 /*
11655 * Add the annotation to the simple type ancestor.
11656 */
11657 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011658 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011659 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011661 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11662 /*
11663 * Corresponds to <simpleType><restriction><simpleType>.
11664 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011665 if (IS_SCHEMA(child, "simpleType")) {
11666 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011667 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000011668 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011669 * Either the base [attribute] or the simpleType [child] of the
11670 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000011671 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011672 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000011673 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011674 NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000011675 "The attribute 'base' and the <simpleType> child are "
11676 "mutually exclusive", NULL);
11677 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011678 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000011679 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011680 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011681 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011682 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011683 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011684 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011685 NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011686 "Either the attribute 'base' or a <simpleType> child "
11687 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000011688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011689 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11690 /*
11691 * Corresponds to <complexType><complexContent><restriction>...
11692 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011693 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011694 * Model groups <all>, <choice> and <sequence>.
11695 */
11696 if (IS_SCHEMA(child, "all")) {
11697 type->subtypes = (xmlSchemaTypePtr)
11698 xmlSchemaParseModelGroup(ctxt, schema, child,
11699 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011700 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011701 } else if (IS_SCHEMA(child, "choice")) {
11702 type->subtypes = (xmlSchemaTypePtr)
11703 xmlSchemaParseModelGroup(ctxt,
11704 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11705 child = child->next;
11706 } else if (IS_SCHEMA(child, "sequence")) {
11707 type->subtypes = (xmlSchemaTypePtr)
11708 xmlSchemaParseModelGroup(ctxt, schema, child,
11709 XML_SCHEMA_TYPE_SEQUENCE, 1);
11710 child = child->next;
11711 /*
11712 * Model group reference <group>.
11713 */
Daniel Veillarddee23482008-04-11 12:58:43 +000011714 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011715 type->subtypes = (xmlSchemaTypePtr)
11716 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011717 /*
11718 * Note that the reference will be resolved in
11719 * xmlSchemaResolveTypeReferences();
11720 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 child = child->next;
11722 }
11723 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 /*
11725 * Corresponds to <complexType><simpleContent><restriction>...
11726 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011727 * "1.1 the simple type definition corresponding to the <simpleType>
11728 * among the [children] of <restriction> if there is one;"
11729 */
11730 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011731 /*
11732 * We will store the to-be-restricted simple type in
11733 * type->contentTypeDef *temporarily*.
11734 */
11735 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011736 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011737 if ( type->contentTypeDef == NULL)
11738 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011739 child = child->next;
11740 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011742
11743 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011744 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011745 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011746 /*
11747 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011748 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011749 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011750
Daniel Veillard01fa6152004-06-29 17:04:39 +000011751 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011752 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011753 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011754 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011755 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11756 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000011757 * *Single Facet Value*
11758 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011759 while ((IS_SCHEMA(child, "minInclusive")) ||
11760 (IS_SCHEMA(child, "minExclusive")) ||
11761 (IS_SCHEMA(child, "maxInclusive")) ||
11762 (IS_SCHEMA(child, "maxExclusive")) ||
11763 (IS_SCHEMA(child, "totalDigits")) ||
11764 (IS_SCHEMA(child, "fractionDigits")) ||
11765 (IS_SCHEMA(child, "pattern")) ||
11766 (IS_SCHEMA(child, "enumeration")) ||
11767 (IS_SCHEMA(child, "whiteSpace")) ||
11768 (IS_SCHEMA(child, "length")) ||
11769 (IS_SCHEMA(child, "maxLength")) ||
11770 (IS_SCHEMA(child, "minLength"))) {
11771 facet = xmlSchemaParseFacet(ctxt, schema, child);
11772 if (facet != NULL) {
11773 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011774 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011775 else
11776 lastfacet->next = facet;
11777 lastfacet = facet;
11778 lastfacet->next = NULL;
11779 }
11780 child = child->next;
11781 }
11782 /*
11783 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011784 */
11785 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011786 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11787
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788 facet = type->facets;
11789 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011790 facetLink = (xmlSchemaFacetLinkPtr)
11791 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000011792 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011793 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011794 xmlFree(facetLink);
11795 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011796 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011797 facetLink->facet = facet;
11798 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 if (lastFacetLink == NULL)
11800 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011801 else
11802 lastFacetLink->next = facetLink;
11803 lastFacetLink = facetLink;
11804 facet = facet->next;
11805 } while (facet != NULL);
11806 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011808 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11809 /*
11810 * Attribute uses/declarations.
11811 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011812 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11813 (xmlSchemaItemListPtr *) &(type->attrUses),
11814 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11815 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011816 /*
11817 * Attribute wildcard.
11818 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011819 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011820 type->attributeWildcard =
11821 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011822 child = child->next;
11823 }
11824 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011825 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011826 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11827 xmlSchemaPContentErr(ctxt,
11828 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011829 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011830 "annotation?, (group | all | choice | sequence)?, "
11831 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011832 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011833 xmlSchemaPContentErr(ctxt,
11834 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011835 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011836 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11837 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11838 "length | minLength | maxLength | enumeration | whiteSpace | "
11839 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11840 } else {
11841 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011842 xmlSchemaPContentErr(ctxt,
11843 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011844 NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011845 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11846 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11847 "length | minLength | maxLength | enumeration | whiteSpace | "
11848 "pattern)*))");
11849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011850 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011851 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011852}
11853
11854/**
11855 * xmlSchemaParseExtension:
11856 * @ctxt: a schema validation context
11857 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070011858 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +000011859 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011860 * Parses an <extension>, which is found inside a
11861 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000011863 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011864 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000011865 */
11866static xmlSchemaTypePtr
11867xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011868 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000011869{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011870 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011871 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011872 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011873
11874 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11875 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011876 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011877 type = ctxt->ctxtType;
11878 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000011879
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011880 /*
11881 * Check for illegal attributes.
11882 */
11883 attr = node->properties;
11884 while (attr != NULL) {
11885 if (attr->ns == NULL) {
11886 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11887 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011888 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011890 }
11891 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011893 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011894 }
11895 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011896 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011897
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011898 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011899
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011900 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011901 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011902 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011903 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11904 "base", &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011905 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000011906 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011907 XML_SCHEMAP_S4S_ATTR_MISSING,
11908 NULL, node, "base", NULL);
11909 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011910 /*
11911 * And now for the children...
11912 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011913 child = node->children;
11914 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011915 /*
11916 * Add the annotation to the type ancestor.
11917 */
11918 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000011919 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011920 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011921 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011922 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11923 /*
11924 * Corresponds to <complexType><complexContent><extension>... and:
11925 *
11926 * Model groups <all>, <choice>, <sequence> and <group>.
11927 */
11928 if (IS_SCHEMA(child, "all")) {
11929 type->subtypes = (xmlSchemaTypePtr)
11930 xmlSchemaParseModelGroup(ctxt, schema,
11931 child, XML_SCHEMA_TYPE_ALL, 1);
11932 child = child->next;
11933 } else if (IS_SCHEMA(child, "choice")) {
11934 type->subtypes = (xmlSchemaTypePtr)
11935 xmlSchemaParseModelGroup(ctxt, schema,
11936 child, XML_SCHEMA_TYPE_CHOICE, 1);
11937 child = child->next;
11938 } else if (IS_SCHEMA(child, "sequence")) {
11939 type->subtypes = (xmlSchemaTypePtr)
11940 xmlSchemaParseModelGroup(ctxt, schema,
11941 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11942 child = child->next;
11943 } else if (IS_SCHEMA(child, "group")) {
11944 type->subtypes = (xmlSchemaTypePtr)
11945 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011946 /*
11947 * Note that the reference will be resolved in
11948 * xmlSchemaResolveTypeReferences();
11949 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011950 child = child->next;
11951 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011952 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011953 if (child != NULL) {
11954 /*
11955 * Attribute uses/declarations.
11956 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011957 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11958 (xmlSchemaItemListPtr *) &(type->attrUses),
11959 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11960 return(NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011961 /*
11962 * Attribute wildcard.
11963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964 if (IS_SCHEMA(child, "anyAttribute")) {
11965 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011966 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11967 child = child->next;
11968 }
11969 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011970 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011971 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11972 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011973 xmlSchemaPContentErr(ctxt,
11974 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011975 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011976 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011978 } else {
11979 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011980 xmlSchemaPContentErr(ctxt,
11981 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000011982 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011983 "(annotation?, ((attribute | attributeGroup)*, "
11984 "anyAttribute?))");
11985 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011986 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011987 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011988}
11989
11990/**
11991 * xmlSchemaParseSimpleContent:
11992 * @ctxt: a schema validation context
11993 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070011994 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +000011995 *
11996 * parse a XML schema SimpleContent definition
11997 * *WARNING* this interface is highly subject to change
11998 *
11999 * Returns the type definition or NULL in case of error
12000 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012001static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012002xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012003 xmlSchemaPtr schema, xmlNodePtr node,
12004 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000012005{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012006 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012007 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012008 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000012009
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012010 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12011 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012012 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012013 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012014 /* Not a component, don't create it. */
12015 type = ctxt->ctxtType;
12016 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12017 /*
12018 * Check for illegal attributes.
12019 */
12020 attr = node->properties;
12021 while (attr != NULL) {
12022 if (attr->ns == NULL) {
12023 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012024 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012025 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012026 }
12027 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012028 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012029 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012030 }
12031 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012032 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012033
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012034 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000012035
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012036 /*
12037 * And now for the children...
12038 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012039 child = node->children;
12040 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012041 /*
12042 * Add the annotation to the complex type ancestor.
12043 */
12044 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012045 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012046 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012047 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012048 if (child == NULL) {
12049 xmlSchemaPContentErr(ctxt,
12050 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012051 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012052 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012053 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012054 if (child == NULL) {
12055 xmlSchemaPContentErr(ctxt,
12056 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012057 NULL, node, NULL, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012058 "(annotation?, (restriction | extension))");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012059 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012060 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012061 xmlSchemaParseRestriction(ctxt, schema, child,
12062 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012063 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012064 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012065 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012066 xmlSchemaParseExtension(ctxt, schema, child,
12067 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012068 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012069 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012071 if (child != NULL) {
12072 xmlSchemaPContentErr(ctxt,
12073 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012074 NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012075 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012076 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012077 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012078}
12079
12080/**
12081 * xmlSchemaParseComplexContent:
12082 * @ctxt: a schema validation context
12083 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070012084 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +000012085 *
12086 * parse a XML schema ComplexContent definition
12087 * *WARNING* this interface is highly subject to change
12088 *
12089 * Returns the type definition or NULL in case of error
12090 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012091static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012092xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012093 xmlSchemaPtr schema, xmlNodePtr node,
12094 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000012095{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012096 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012097 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012098 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000012099
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012100 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12101 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012102 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012103 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012104 /* Not a component, don't create it. */
12105 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012106 /*
12107 * Check for illegal attributes.
12108 */
12109 attr = node->properties;
12110 while (attr != NULL) {
12111 if (attr->ns == NULL) {
12112 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012113 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012114 {
12115 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012116 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012117 }
12118 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12119 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012120 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012121 }
12122 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012124
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012125 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000012126
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012127 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012128 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012129 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012130 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012131 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12132 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012133 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012134 child = node->children;
12135 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012136 /*
12137 * Add the annotation to the complex type ancestor.
12138 */
12139 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012140 xmlSchemaParseAnnotation(ctxt, child, 1));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012141 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012142 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012143 if (child == NULL) {
12144 xmlSchemaPContentErr(ctxt,
12145 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012146 NULL, node, NULL,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012147 NULL, "(annotation?, (restriction | extension))");
12148 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012149 if (child == NULL) {
12150 xmlSchemaPContentErr(ctxt,
12151 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012152 NULL, node, NULL,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012153 NULL, "(annotation?, (restriction | extension))");
12154 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012156 xmlSchemaParseRestriction(ctxt, schema, child,
12157 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012158 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012159 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012160 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012161 xmlSchemaParseExtension(ctxt, schema, child,
12162 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012163 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012164 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012165 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012166 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012167 xmlSchemaPContentErr(ctxt,
12168 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012169 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012170 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012172 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012173}
12174
12175/**
12176 * xmlSchemaParseComplexType:
12177 * @ctxt: a schema validation context
12178 * @schema: the schema being built
Haibo Huangcfd91dc2020-07-30 23:01:33 -070012179 * @node: a subtree containing XML Schema information
Daniel Veillard4255d502002-04-16 15:50:10 +000012180 *
12181 * parse a XML schema Complex Type definition
12182 * *WARNING* this interface is highly subject to change
12183 *
12184 * Returns the type definition or NULL in case of error
12185 */
12186static xmlSchemaTypePtr
12187xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000012188 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000012189{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012190 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012191 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012192 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012193 xmlAttrPtr attr;
12194 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012195#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000012196 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012197#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012198 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000012199
Daniel Veillard4255d502002-04-16 15:50:10 +000012200
12201 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12202 return (NULL);
12203
Daniel Veillard01fa6152004-06-29 17:04:39 +000012204 ctxtType = ctxt->ctxtType;
12205
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012206 if (topLevel) {
12207 attr = xmlSchemaGetPropNode(node, "name");
12208 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209 xmlSchemaPMissingAttrErr(ctxt,
12210 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012211 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012212 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012213 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12214 return (NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012215 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012216 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012218 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012219 /*
12220 * Parse as local complex type definition.
12221 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012222#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000012223 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012224 type = xmlSchemaAddType(ctxt, schema,
12225 XML_SCHEMA_TYPE_COMPLEX,
12226 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012227 ctxt->targetNamespace, node, 0);
12228#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012229 type = xmlSchemaAddType(ctxt, schema,
12230 XML_SCHEMA_TYPE_COMPLEX,
12231 NULL, ctxt->targetNamespace, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012232#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012233 if (type == NULL)
12234 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012235 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012236 type->node = node;
12237 type->type = XML_SCHEMA_TYPE_COMPLEX;
12238 /*
12239 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012240 */
12241 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012242 /*
12243 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012244 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012245 type = xmlSchemaAddType(ctxt, schema,
12246 XML_SCHEMA_TYPE_COMPLEX,
12247 name, ctxt->targetNamespace, node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012248 if (type == NULL)
12249 return (NULL);
12250 type->node = node;
12251 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000012253 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012254 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012255 /*
12256 * Handle attributes.
12257 */
12258 attr = node->properties;
12259 while (attr != NULL) {
12260 if (attr->ns == NULL) {
12261 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12262 /*
12263 * Attribute "id".
12264 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012265 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012266 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12267 /*
12268 * Attribute "mixed".
12269 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012270 if (xmlSchemaPGetBoolNodeValue(ctxt,
12271 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012272 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12273 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012274 /*
12275 * Attributes of global complex type definitions.
12276 */
12277 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12278 /* Pass. */
12279 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12280 /*
12281 * Attribute "abstract".
12282 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012283 if (xmlSchemaPGetBoolNodeValue(ctxt,
12284 NULL, (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012285 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12286 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12287 /*
12288 * Attribute "final".
12289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012290 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012291 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292 if (xmlSchemaPValAttrBlockFinal(attrValue,
12293 &(type->flags),
12294 -1,
12295 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12296 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12297 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012298 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012299 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012300 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012301 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012302 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012303 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012304 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012306 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12307 /*
12308 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012309 */
12310 attrValue = xmlSchemaGetNodeContent(ctxt,
12311 (xmlNodePtr) attr);
12312 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012313 -1,
12314 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012315 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012316 -1, -1, -1) != 0) {
12317 xmlSchemaPSimpleTypeErr(ctxt,
12318 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012319 NULL, (xmlNodePtr) attr, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012320 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012321 attrValue, NULL, NULL, NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000012322 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012323 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012324 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012325 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012327 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012328 } else {
12329 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012331 }
12332 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012333 xmlSchemaPIllegalAttrErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012334 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012335 }
12336 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012337 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012338 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012339 /*
12340 * Apply default "block" values.
12341 */
12342 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12343 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12344 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12345 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12346 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012347 if (! final) {
12348 /*
12349 * Apply default "block" values.
12350 */
12351 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12352 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12353 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12354 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12355 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012356 /*
12357 * And now for the children...
12358 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012359 child = node->children;
12360 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000012361 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012362 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012363 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012365 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012366 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012367 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012368 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012369 * Specifying mixed='true' when the <simpleContent>
12370 * alternative is chosen has no effect
12371 */
William M. Bracke7091952004-05-11 15:09:58 +000012372 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12373 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012374 xmlSchemaParseSimpleContent(ctxt, schema, child,
12375 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012376 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012377 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012378 /*
12379 * <complexType><complexContent>...
12380 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012381 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012382 xmlSchemaParseComplexContent(ctxt, schema, child,
12383 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012384 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012385 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012386 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012387 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12388 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012389 * SPEC
12390 * "...the third alternative (neither <simpleContent> nor
12391 * <complexContent>) is chosen. This case is understood as shorthand
Jan Pokorný761c9e92013-11-29 23:26:27 +010012392 * for complex content restricting the `ur-type definition`, and the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012393 * details of the mappings should be modified as necessary.
12394 */
12395 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12396 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012397 /*
12398 * Parse model groups.
12399 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012400 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012401 type->subtypes = (xmlSchemaTypePtr)
12402 xmlSchemaParseModelGroup(ctxt, schema, child,
12403 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012404 child = child->next;
12405 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012406 type->subtypes = (xmlSchemaTypePtr)
12407 xmlSchemaParseModelGroup(ctxt, schema, child,
12408 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012409 child = child->next;
12410 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012411 type->subtypes = (xmlSchemaTypePtr)
12412 xmlSchemaParseModelGroup(ctxt, schema, child,
12413 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012414 child = child->next;
12415 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012416 type->subtypes = (xmlSchemaTypePtr)
12417 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012418 /*
12419 * Note that the reference will be resolved in
12420 * xmlSchemaResolveTypeReferences();
12421 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012422 child = child->next;
12423 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012424 /*
12425 * Parse attribute decls/refs.
12426 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012427 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12428 (xmlSchemaItemListPtr *) &(type->attrUses),
12429 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12430 return(NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012431 /*
12432 * Parse attribute wildcard.
12433 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012434 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12436 child = child->next;
12437 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012438 }
12439 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012440 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012442 NULL, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012443 NULL, "(annotation?, (simpleContent | complexContent | "
12444 "((group | all | choice | sequence)?, ((attribute | "
12445 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000012446 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012447 /*
12448 * REDEFINE: SPEC src-redefine (5)
12449 */
12450 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12451 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012452 NULL, node, "This is a redefinition, thus the "
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000012453 "<complexType> must have a <restriction> or <extension> "
12454 "grand-child", NULL);
12455 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012456 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000012457 return (type);
12458}
12459
Daniel Veillard4255d502002-04-16 15:50:10 +000012460/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012461 * *
12462 * Validating using Schemas *
12463 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012464 ************************************************************************/
12465
12466/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080012467 * *
12468 * Reading/Writing Schemas *
12469 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000012470 ************************************************************************/
12471
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012472#if 0 /* Will be enabled if it is clear what options are needed. */
12473/**
12474 * xmlSchemaParserCtxtSetOptions:
12475 * @ctxt: a schema parser context
12476 * @options: a combination of xmlSchemaParserOption
12477 *
12478 * Sets the options to be used during the parse.
12479 *
12480 * Returns 0 in case of success, -1 in case of an
12481 * API error.
12482 */
12483static int
12484xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12485 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012487{
12488 int i;
12489
12490 if (ctxt == NULL)
12491 return (-1);
12492 /*
12493 * WARNING: Change the start value if adding to the
12494 * xmlSchemaParseOption.
12495 */
12496 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12497 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012498 return (-1);
12499 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012500 }
12501 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012502 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012503}
12504
12505/**
12506 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012507 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012508 *
12509 * Returns the option combination of the parser context.
12510 */
12511static int
12512xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513
12514{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012515 if (ctxt == NULL)
12516 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012517 else
12518 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012519}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012520#endif
12521
Daniel Veillard4255d502002-04-16 15:50:10 +000012522/**
12523 * xmlSchemaNewParserCtxt:
12524 * @URL: the location of the schema
12525 *
12526 * Create an XML Schemas parse context for that file/resource expected
12527 * to contain an XML Schemas file.
12528 *
12529 * Returns the parser context or NULL in case of error
12530 */
12531xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012532xmlSchemaNewParserCtxt(const char *URL)
12533{
Daniel Veillard4255d502002-04-16 15:50:10 +000012534 xmlSchemaParserCtxtPtr ret;
12535
12536 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012537 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012538
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012539 ret = xmlSchemaParserCtxtCreate();
12540 if (ret == NULL)
12541 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012542 ret->dict = xmlDictCreate();
12543 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012544 return (ret);
12545}
12546
12547/**
Daniel Veillard6045c902002-10-09 21:13:59 +000012548 * xmlSchemaNewMemParserCtxt:
12549 * @buffer: a pointer to a char array containing the schemas
12550 * @size: the size of the array
12551 *
12552 * Create an XML Schemas parse context for that memory buffer expected
12553 * to contain an XML Schemas file.
12554 *
12555 * Returns the parser context or NULL in case of error
12556 */
12557xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012558xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12559{
Daniel Veillard6045c902002-10-09 21:13:59 +000012560 xmlSchemaParserCtxtPtr ret;
12561
12562 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012563 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012564 ret = xmlSchemaParserCtxtCreate();
12565 if (ret == NULL)
12566 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000012567 ret->buffer = buffer;
12568 ret->size = size;
Daniel Veillarddee23482008-04-11 12:58:43 +000012569 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000012570 return (ret);
12571}
12572
12573/**
Daniel Veillard9d751502003-10-29 13:21:47 +000012574 * xmlSchemaNewDocParserCtxt:
12575 * @doc: a preparsed document tree
12576 *
12577 * Create an XML Schemas parse context for that document.
12578 * NB. The document may be modified during the parsing process.
12579 *
12580 * Returns the parser context or NULL in case of error
12581 */
12582xmlSchemaParserCtxtPtr
12583xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12584{
12585 xmlSchemaParserCtxtPtr ret;
12586
12587 if (doc == NULL)
12588 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000012589 ret = xmlSchemaParserCtxtCreate();
12590 if (ret == NULL)
12591 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000012592 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000012593 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000012594 /* The application has responsibility for the document */
12595 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000012596
12597 return (ret);
12598}
12599
12600/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012601 * xmlSchemaFreeParserCtxt:
12602 * @ctxt: the schema parser context
12603 *
12604 * Free the resources associated to the schema parser context
12605 */
12606void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012607xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12608{
Daniel Veillard4255d502002-04-16 15:50:10 +000012609 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012610 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012611 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillarddee23482008-04-11 12:58:43 +000012612 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012613 if (ctxt->vctxt != NULL) {
12614 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12615 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012616 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12617 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12618 ctxt->constructor = NULL;
12619 ctxt->ownsConstructor = 0;
12620 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012621 if (ctxt->attrProhibs != NULL)
12622 xmlSchemaItemListFree(ctxt->attrProhibs);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012623 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000012624 xmlFree(ctxt);
12625}
12626
12627/************************************************************************
12628 * *
12629 * Building the content models *
12630 * *
12631 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012632
Daniel Veillard4013e832009-08-26 17:24:31 +020012633/**
12634 * xmlSchemaBuildContentModelForSubstGroup:
12635 *
12636 * Returns 1 if nillable, 0 otherwise
12637 */
12638static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012639xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012640 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012641{
Daniel Veillarda980bef2005-07-18 21:34:03 +000012642 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012643 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012644 xmlSchemaSubstGroupPtr substGroup;
12645 int i;
Daniel Veillard4013e832009-08-26 17:24:31 +020012646 int ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012647
12648 elemDecl = (xmlSchemaElementPtr) particle->children;
12649 /*
12650 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012652 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000012653 if (end == NULL)
12654 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012655 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012656 if (substGroup == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012657 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012658 XML_SCHEMAP_INTERNAL,
12659 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12660 "declaration is marked having a subst. group but none "
12661 "available.\n", elemDecl->name, NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020012662 return(0);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012663 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000012664 if (counter >= 0) {
12665 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012666 * NOTE that we put the declaration in, even if it's abstract.
12667 * However, an error will be raised during *validation* if an element
12668 * information item shall be validated against an abstract element
12669 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000012670 */
12671 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12672 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12673 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674 /*
12675 * Add subst. group members.
12676 */
12677 for (i = 0; i < substGroup->members->nbItems; i++) {
12678 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12679 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12680 member->name, member->targetNamespace, member);
12681 }
12682 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012683 /*
12684 * NOTE that we put the declaration in, even if it's abstract,
12685 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012686 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012687 xmlAutomataNewTransition2(pctxt->am,
12688 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012689 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12690 /*
12691 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012692 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012693 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012694 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012695 /*
12696 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12697 * was incorrectly used instead of xmlAutomataNewTransition2()
12698 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12699 * section in xmlSchemaBuildAContentModel() ).
Daniel Veillarddee23482008-04-11 12:58:43 +000012700 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
Kasimier T. Buchcik92b394f2006-05-09 19:59:54 +000012701 * intended for the above "counter" section originally. I.e.,
12702 * check xs:all with subst-groups.
12703 *
12704 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12705 * member->name, member->targetNamespace,
12706 * 1, 1, member);
12707 */
12708 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012709 member->name, member->targetNamespace, member);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012710 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012711 }
12712 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012713 xmlAutomataStatePtr hop;
12714 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12715 UNBOUNDED : particle->maxOccurs - 1;
12716 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12717
12718 counter =
12719 xmlAutomataNewCounter(pctxt->am, minOccurs,
12720 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012721 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012722
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012723 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012724 xmlAutomataNewTransition2(pctxt->am,
12725 start, NULL,
12726 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012727 hop);
12728 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000012729 * Add subst. group members.
12730 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012731 for (i = 0; i < substGroup->members->nbItems; i++) {
12732 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12733 xmlAutomataNewEpsilon(pctxt->am,
12734 xmlAutomataNewTransition2(pctxt->am,
12735 start, NULL,
12736 member->name, member->targetNamespace, member),
12737 hop);
12738 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012739 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12740 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12741 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012742 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012743 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012744 ret = 1;
12745 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012746 pctxt->state = end;
Daniel Veillard4013e832009-08-26 17:24:31 +020012747 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012748}
12749
Daniel Veillard4013e832009-08-26 17:24:31 +020012750/**
12751 * xmlSchemaBuildContentModelForElement:
12752 *
12753 * Returns 1 if nillable, 0 otherwise
12754 */
12755static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012756xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12757 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012758{
Daniel Veillard4013e832009-08-26 17:24:31 +020012759 int ret = 0;
12760
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000012761 if (((xmlSchemaElementPtr) particle->children)->flags &
12762 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012763 /*
12764 * Substitution groups.
12765 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012766 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012767 } else {
12768 xmlSchemaElementPtr elemDecl;
12769 xmlAutomataStatePtr start;
12770
12771 elemDecl = (xmlSchemaElementPtr) particle->children;
12772
12773 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillard4013e832009-08-26 17:24:31 +020012774 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012775 if (particle->maxOccurs == 1) {
12776 start = ctxt->state;
12777 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012778 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12779 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12780 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012781 /* Special case. */
Daniel Veillarddee23482008-04-11 12:58:43 +000012782 start = ctxt->state;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012783 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000012784 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik7ca5aed2005-12-12 15:13:40 +000012785 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
Daniel Veillarddee23482008-04-11 12:58:43 +000012786 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012787 } else {
12788 int counter;
12789 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12790 UNBOUNDED : particle->maxOccurs - 1;
12791 int minOccurs = particle->minOccurs < 1 ?
12792 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012793
12794 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012795 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12796 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12797 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12798 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12799 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12800 NULL, counter);
12801 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012802 if (particle->minOccurs == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012803 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
Daniel Veillard4013e832009-08-26 17:24:31 +020012804 ret = 1;
12805 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012806 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012807 return(ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012808}
12809
Daniel Veillard4255d502002-04-16 15:50:10 +000012810/**
12811 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012812 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012813 * @particle: the particle component
12814 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000012815 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012816 * Create the automaton for the {content type} of a complex type.
12817 *
Daniel Veillard4013e832009-08-26 17:24:31 +020012818 * Returns 1 if the content is nillable, 0 otherwise
Daniel Veillard4255d502002-04-16 15:50:10 +000012819 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012820static int
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012821xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012822 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012823{
Daniel Veillard4013e832009-08-26 17:24:31 +020012824 int ret = 0, tmp2;
12825
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012826 if (particle == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000012827 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Daniel Veillard4013e832009-08-26 17:24:31 +020012828 return(1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012829 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012830 if (particle->children == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000012831 /*
12832 * Just return in this case. A missing "term" of the particle
12833 * might arise due to an invalid "term" component.
12834 */
Daniel Veillard4013e832009-08-26 17:24:31 +020012835 return(1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012836 }
12837
12838 switch (particle->children->type) {
12839 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012840 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012841 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012842 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000012843
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012844 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012845
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012846 start = pctxt->state;
12847 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012848
12849 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012850 if (wild->any == 1) {
12851 /*
12852 * We need to add both transitions:
12853 *
12854 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012855 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012856 pctxt->state =
12857 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012858 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012859 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012860 /*
12861 * 2. the {"*"} for elements in no namespace.
12862 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012863 pctxt->state =
12864 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012865 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012866 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012867
12868 } else if (wild->nsSet != NULL) {
12869 ns = wild->nsSet;
12870 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012871 pctxt->state = start;
12872 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12873 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12874 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012875 ns = ns->next;
12876 } while (ns != NULL);
12877
12878 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000012879 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12880 start, end, BAD_CAST "*", wild->negNsSet->value,
12881 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012882 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012883 } else {
12884 int counter;
12885 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012886 int maxOccurs =
Daniel Veillard4013e832009-08-26 17:24:31 +020012887 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12888 particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012889 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012890 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012891
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012892 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12893 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012894 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012895 pctxt->state =
12896 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012897 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012898 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12899 pctxt->state =
12900 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012901 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012902 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012903 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012904 ns = wild->nsSet;
12905 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012906 pctxt->state =
12907 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012908 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012909 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012910 ns = ns->next;
12911 } while (ns != NULL);
12912
12913 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012914 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000012915 start, hop, BAD_CAST "*", wild->negNsSet->value,
12916 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012917 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012918 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12919 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012920 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012922 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillard4013e832009-08-26 17:24:31 +020012923 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012924 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012925 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012926 break;
12927 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012928 case XML_SCHEMA_TYPE_ELEMENT:
Daniel Veillard4013e832009-08-26 17:24:31 +020012929 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012930 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012931 case XML_SCHEMA_TYPE_SEQUENCE:{
Daniel Veillard4013e832009-08-26 17:24:31 +020012932 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012933
Daniel Veillard4013e832009-08-26 17:24:31 +020012934 ret = 1;
12935 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070012936 * If max and min occurrences are default (1) then
Daniel Veillard4013e832009-08-26 17:24:31 +020012937 * simply iterate over the particles of the <sequence>.
12938 */
12939 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12940 sub = particle->children->children;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012941
Daniel Veillard4013e832009-08-26 17:24:31 +020012942 while (sub != NULL) {
12943 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12944 (xmlSchemaParticlePtr) sub);
12945 if (tmp2 != 1) ret = 0;
12946 sub = sub->next;
12947 }
12948 } else {
12949 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012950
Daniel Veillard4013e832009-08-26 17:24:31 +020012951 if (particle->maxOccurs >= UNBOUNDED) {
12952 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012953 xmlAutomataStatePtr tmp;
12954 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000012955
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012956 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012957 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012958 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000012959
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012960 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012961 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillard4255d502002-04-16 15:50:10 +000012962
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012963 sub = particle->children->children;
12964 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012965 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12966 (xmlSchemaParticlePtr) sub);
12967 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012968 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012969 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012970 tmp = pctxt->state;
Daniel Veillard4013e832009-08-26 17:24:31 +020012971 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12972 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012973 pctxt->state =
Daniel Veillard4013e832009-08-26 17:24:31 +020012974 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12975 NULL, counter);
12976 if (ret == 1)
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012977 xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillard4013e832009-08-26 17:24:31 +020012978 oldstate, pctxt->state);
12979
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012980 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020012981 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12982 oldstate, NULL);
12983 oldstate = pctxt->state;
12984
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012985 sub = particle->children->children;
12986 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020012987 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12988 (xmlSchemaParticlePtr) sub);
12989 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012990 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012991 }
Daniel Veillard4013e832009-08-26 17:24:31 +020012992 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12993 oldstate);
12994 /*
12995 * epsilon needed to block previous trans from
12996 * being allowed to enter back from another
12997 * construct
12998 */
12999 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13000 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013001 if (particle->minOccurs == 0) {
Daniel Veillard4013e832009-08-26 17:24:31 +020013002 xmlAutomataNewEpsilon(pctxt->am,
13003 oldstate, pctxt->state);
13004 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013005 }
13006 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013007 } else if ((particle->maxOccurs > 1)
13008 || (particle->minOccurs > 1)) {
13009 xmlAutomataStatePtr tmp;
13010 int counter;
Daniel Veillardb509f152002-04-17 16:28:10 +000013011
Daniel Veillard4013e832009-08-26 17:24:31 +020013012 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13013 oldstate, NULL);
13014 oldstate = pctxt->state;
Daniel Veillard7646b182002-04-20 06:41:40 +000013015
Daniel Veillard4013e832009-08-26 17:24:31 +020013016 counter = xmlAutomataNewCounter(pctxt->am,
13017 particle->minOccurs - 1,
13018 particle->maxOccurs - 1);
13019
13020 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013021 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020013022 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13023 (xmlSchemaParticlePtr) sub);
13024 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013025 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013026 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013027 tmp = pctxt->state;
13028 xmlAutomataNewCountedTrans(pctxt->am,
13029 tmp, oldstate, counter);
13030 pctxt->state =
13031 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13032 counter);
13033 if ((particle->minOccurs == 0) || (ret == 1)) {
13034 xmlAutomataNewEpsilon(pctxt->am,
13035 oldstate, pctxt->state);
13036 ret = 1;
13037 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013038 } else {
Daniel Veillard4013e832009-08-26 17:24:31 +020013039 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013040 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020013041 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13042 (xmlSchemaParticlePtr) sub);
13043 if (tmp2 != 1) ret = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013044 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000013045 }
Daniel Veillardc70d1852012-08-23 23:28:04 +080013046
13047 /*
13048 * epsilon needed to block previous trans from
13049 * being allowed to enter back from another
13050 * construct
13051 */
13052 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13053 pctxt->state, NULL);
13054
Daniel Veillard4013e832009-08-26 17:24:31 +020013055 if (particle->minOccurs == 0) {
13056 xmlAutomataNewEpsilon(pctxt->am, oldstate,
13057 pctxt->state);
13058 ret = 1;
13059 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013060 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013061 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013062 break;
13063 }
13064 case XML_SCHEMA_TYPE_CHOICE:{
13065 xmlSchemaTreeItemPtr sub;
13066 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013067
Daniel Veillard4013e832009-08-26 17:24:31 +020013068 ret = 0;
13069 start = pctxt->state;
13070 end = xmlAutomataNewState(pctxt->am);
13071
13072 /*
13073 * iterate over the subtypes and remerge the end with an
13074 * epsilon transition
13075 */
13076 if (particle->maxOccurs == 1) {
13077 sub = particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078 while (sub != NULL) {
Daniel Veillard4013e832009-08-26 17:24:31 +020013079 pctxt->state = start;
13080 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13081 (xmlSchemaParticlePtr) sub);
13082 if (tmp2 == 1) ret = 1;
13083 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13084 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013085 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013086 } else {
13087 int counter;
13088 xmlAutomataStatePtr hop, base;
13089 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13090 UNBOUNDED : particle->maxOccurs - 1;
13091 int minOccurs =
13092 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13093
13094 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070013095 * use a counter to keep track of the number of transitions
Daniel Veillard4013e832009-08-26 17:24:31 +020013096 * which went through the choice.
13097 */
13098 counter =
13099 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13100 hop = xmlAutomataNewState(pctxt->am);
13101 base = xmlAutomataNewState(pctxt->am);
13102
13103 sub = particle->children->children;
13104 while (sub != NULL) {
13105 pctxt->state = base;
13106 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13107 (xmlSchemaParticlePtr) sub);
13108 if (tmp2 == 1) ret = 1;
13109 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13110 sub = sub->next;
Daniel Veillardbd56c442009-08-12 15:39:23 +020013111 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013112 xmlAutomataNewEpsilon(pctxt->am, start, base);
13113 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13114 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13115 if (ret == 1)
13116 xmlAutomataNewEpsilon(pctxt->am, base, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013117 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013118 if (particle->minOccurs == 0) {
13119 xmlAutomataNewEpsilon(pctxt->am, start, end);
13120 ret = 1;
13121 }
13122 pctxt->state = end;
13123 break;
13124 }
13125 case XML_SCHEMA_TYPE_ALL:{
13126 xmlAutomataStatePtr start, tmp;
13127 xmlSchemaParticlePtr sub;
13128 xmlSchemaElementPtr elemDecl;
13129
13130 ret = 1;
13131
13132 sub = (xmlSchemaParticlePtr) particle->children->children;
13133 if (sub == NULL)
13134 break;
13135
13136 ret = 0;
13137
13138 start = pctxt->state;
13139 tmp = xmlAutomataNewState(pctxt->am);
13140 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13141 pctxt->state = tmp;
13142 while (sub != NULL) {
13143 pctxt->state = tmp;
13144
13145 elemDecl = (xmlSchemaElementPtr) sub->children;
13146 if (elemDecl == NULL) {
13147 PERROR_INT("xmlSchemaBuildAContentModel",
13148 "<element> particle has no term");
13149 return(ret);
13150 };
13151 /*
13152 * NOTE: The {max occurs} of all the particles in the
13153 * {particles} of the group must be 0 or 1; this is
13154 * already ensured during the parse of the content of
13155 * <all>.
13156 */
13157 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13158 int counter;
13159
13160 /*
13161 * This is an abstract group, we need to share
13162 * the same counter for all the element transitions
13163 * derived from the group
13164 */
13165 counter = xmlAutomataNewCounter(pctxt->am,
13166 sub->minOccurs, sub->maxOccurs);
13167 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13168 sub, counter, pctxt->state);
13169 } else {
13170 if ((sub->minOccurs == 1) &&
13171 (sub->maxOccurs == 1)) {
13172 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13173 pctxt->state,
13174 elemDecl->name,
13175 elemDecl->targetNamespace,
13176 1, 1, elemDecl);
13177 } else if ((sub->minOccurs == 0) &&
13178 (sub->maxOccurs == 1)) {
13179
13180 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13181 pctxt->state,
13182 elemDecl->name,
13183 elemDecl->targetNamespace,
13184 0,
13185 1,
13186 elemDecl);
13187 }
13188 }
13189 sub = (xmlSchemaParticlePtr) sub->next;
13190 }
13191 pctxt->state =
13192 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13193 if (particle->minOccurs == 0) {
13194 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13195 ret = 1;
13196 }
13197 break;
13198 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013199 case XML_SCHEMA_TYPE_GROUP:
13200 /*
13201 * If we hit a model group definition, then this means that
13202 * it was empty, thus was not substituted for the containing
13203 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013204 * TODO: But the group should be substituted and not occur at
13205 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013206 */
Daniel Veillard4013e832009-08-26 17:24:31 +020013207 ret = 1;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000013208 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013209 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013210 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13211 "xmlSchemaBuildAContentModel",
13212 "found unexpected term of type '%s' in content model",
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013213 WXS_ITEM_TYPE_NAME(particle->children), NULL);
Daniel Veillard4013e832009-08-26 17:24:31 +020013214 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013215 }
Daniel Veillard4013e832009-08-26 17:24:31 +020013216 return(ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013217}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013218
Daniel Veillard4255d502002-04-16 15:50:10 +000013219/**
13220 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000013221 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013223 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000013224 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013225 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000013226 */
13227static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013228xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013229 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013230{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013231 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13232 (type->contModel != NULL) ||
13233 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13234 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013235 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013236
13237#ifdef DEBUG_CONTENT
13238 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013239 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013240#endif
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013241 ctxt->am = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013242 ctxt->am = xmlNewAutomata();
13243 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013244 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013245 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013246 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013247 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000013248 ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013249 /*
13250 * Build the automaton.
13251 */
13252 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
Daniel Veillard4255d502002-04-16 15:50:10 +000013253 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013254 type->contModel = xmlAutomataCompile(ctxt->am);
13255 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013256 xmlSchemaPCustomErr(ctxt,
13257 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013258 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013259 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013260 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013261 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013262 XML_SCHEMAP_NOT_DETERMINISTIC,
13263 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013264 WXS_BASIC_CAST type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013265 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000013266 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000013267#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013268 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013269 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013270 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000013271#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000013272 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000013273 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013274 xmlFreeAutomata(ctxt->am);
13275 ctxt->am = NULL;
13276}
13277
13278/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013279 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000013280 * @elem: the schema element context
13281 * @ctxt: the schema parser context
13282 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013283 * Resolves the references of an element declaration
13284 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000013286 */
13287static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013288xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13289 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000013290{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013291 if ((ctxt == NULL) || (elemDecl == NULL) ||
13292 ((elemDecl != NULL) &&
13293 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013294 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013295 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013296
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013297 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013298 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013299
Jan Pokorný761c9e92013-11-29 23:26:27 +010013300 /* (type definition) ... otherwise the type definition `resolved`
13301 * to by the `actual value` of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013302 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013303 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013304 elemDecl->namedTypeNs);
13305 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013306 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013307 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013308 WXS_BASIC_CAST elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013309 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013310 XML_SCHEMA_TYPE_BASIC, "type definition");
13311 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013312 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013313 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013314 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013315 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013316
Daniel Veillardc0826a72004-08-10 14:17:33 +000013317 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013318 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013319 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013320 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013321 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13322 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013323 if (substHead == NULL) {
13324 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013325 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013326 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013327 "substitutionGroup", elemDecl->substGroup,
13328 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013329 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013330 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013331 /*
13332 * Set the "substitution group affiliation".
13333 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013334 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013335 WXS_SUBST_HEAD(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013336 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013337 * The type definitions is set to:
13338 * SPEC "...the {type definition} of the element
Jan Pokorný761c9e92013-11-29 23:26:27 +010013339 * declaration `resolved` to by the `actual value`
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013340 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013341 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013342 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013343 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013344 }
13345 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013346 /*
13347 * SPEC "The definition of anyType serves as the default type definition
13348 * for element declarations whose XML representation does not specify one."
13349 */
13350 if ((elemDecl->subtypes == NULL) &&
13351 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013352 (elemDecl->substGroup == NULL))
13353 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000013354}
13355
13356/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013357 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000013358 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013359 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000013360 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013361 * Checks and builds the "member type definitions" property of the union
13362 * simple type. This handles part (1), part (2) is done in
13363 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13364 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013365 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000013366 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013367static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013368xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13369 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013370{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013371
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013372 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013373 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000013374
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013375 /*
13376 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Jan Pokorný761c9e92013-11-29 23:26:27 +010013377 * define the explicit members as the type definitions `resolved`
13378 * to by the items in the `actual value` of the memberTypes [attribute],
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013379 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013380 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000013381 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013382 /*
13383 * Resolve references.
13384 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013385 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013386 lastLink = NULL;
13387 while (link != NULL) {
13388 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013390 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13391 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13392
13393 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013394 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013395 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013396 WXS_BASIC_CAST type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013397 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13398 /*
13399 * Remove the member type link.
13400 */
13401 if (lastLink == NULL)
13402 type->memberTypes = link->next;
13403 else
13404 lastLink->next = link->next;
13405 newLink = link;
13406 link = link->next;
13407 xmlFree(newLink);
13408 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013409 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013410 lastLink = link;
13411 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013412 }
13413 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 /*
13415 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013416 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13420 if (link == NULL) {
13421 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13422 return (-1);
13423 }
13424 link->type = memberType;
13425 link->next = NULL;
13426 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013427 type->memberTypes = link;
13428 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429 lastLink->next = link;
13430 lastLink = link;
13431 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000013434}
13435
Daniel Veillard4255d502002-04-16 15:50:10 +000013436/**
Daniel Veillard3646d642004-06-02 19:19:14 +000013437 * xmlSchemaIsDerivedFromBuiltInType:
13438 * @ctxt: the schema parser context
13439 * @type: the type definition
13440 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013441 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013442 *
13443 * Returns 1 if the type has the given value type, or
13444 * is derived from such a type.
13445 */
William M. Brack803812b2004-06-03 02:11:24 +000013446static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000013448{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 if (type == NULL)
13450 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013451 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 return (0);
13453 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13454 if (type->builtInType == valType)
13455 return(1);
13456 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13457 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13458 return (0);
13459 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013460 }
13461 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000013462}
13463
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464#if 0
13465/**
13466 * xmlSchemaIsDerivedFromBuiltInType:
13467 * @ctxt: the schema parser context
13468 * @type: the type definition
13469 * @valType: the value type
13470 *
13471 *
13472 * Returns 1 if the type has the given value type, or
13473 * is derived from such a type.
13474 */
13475static int
13476xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13477{
13478 if (type == NULL)
13479 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013480 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 return (0);
13482 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13483 if (type->builtInType == valType)
13484 return(1);
13485 return (0);
13486 } else
13487 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13488
13489 return (0);
13490}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491
13492static xmlSchemaTypePtr
13493xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13494{
13495 if (type == NULL)
13496 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013497 if (WXS_IS_COMPLEX(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 return (NULL);
13499 if (type->type == XML_SCHEMA_TYPE_BASIC)
Daniel Veillard6a0baa02005-12-10 11:11:12 +000013500 return(type);
13501 return(xmlSchemaQueryBuiltInType(type->subtypes));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502}
Daniel Veillard15724252008-08-30 15:01:04 +000013503#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504
Daniel Veillard3646d642004-06-02 19:19:14 +000013505/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013506 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013507 * @type: the simpleType definition
13508 *
13509 * Returns the primitive type of the given type or
13510 * NULL in case of error.
13511 */
13512static xmlSchemaTypePtr
13513xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13514{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013515
Daniel Veillard01fa6152004-06-29 17:04:39 +000013516 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013517 /*
13518 * Note that anySimpleType is actually not a primitive type
13519 * but we need that here.
13520 */
13521 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13522 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 return (type);
13524 type = type->baseType;
13525 }
13526
13527 return (NULL);
13528}
13529
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013530#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013531/**
13532 * xmlSchemaGetBuiltInTypeAncestor:
13533 * @type: the simpleType definition
13534 *
13535 * Returns the primitive type of the given type or
13536 * NULL in case of error.
13537 */
13538static xmlSchemaTypePtr
13539xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13540{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013541 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013542 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013543 while (type != NULL) {
13544 if (type->type == XML_SCHEMA_TYPE_BASIC)
13545 return (type);
13546 type = type->baseType;
13547 }
13548
13549 return (NULL);
13550}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000013551#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000013552
Daniel Veillard01fa6152004-06-29 17:04:39 +000013553/**
Daniel Veillard50355f02004-06-08 17:52:16 +000013554 * xmlSchemaCloneWildcardNsConstraints:
13555 * @ctxt: the schema parser context
13556 * @dest: the destination wildcard
13557 * @source: the source wildcard
13558 *
13559 * Clones the namespace constraints of source
Haibo Huangcfd91dc2020-07-30 23:01:33 -070013560 * and assigns them to dest.
Daniel Veillard50355f02004-06-08 17:52:16 +000013561 * Returns -1 on internal error, 0 otherwise.
13562 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013563static int
13564xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013565 xmlSchemaWildcardPtr dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013566 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000013567{
13568 xmlSchemaWildcardNsPtr cur, tmp, last;
13569
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013570 if ((source == NULL) || (dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013571 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013572 dest->any = source->any;
Daniel Veillard3646d642004-06-02 19:19:14 +000013573 cur = source->nsSet;
13574 last = NULL;
13575 while (cur != NULL) {
13576 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13577 if (tmp == NULL)
13578 return(-1);
13579 tmp->value = cur->value;
13580 if (last == NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013581 dest->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013583 last->next = tmp;
13584 last = tmp;
13585 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013586 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013587 if (dest->negNsSet != NULL)
13588 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000013589 if (source->negNsSet != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013590 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13591 if (dest->negNsSet == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013593 dest->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000013594 } else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013595 dest->negNsSet = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013596 return(0);
13597}
13598
Daniel Veillard50355f02004-06-08 17:52:16 +000013599/**
13600 * xmlSchemaUnionWildcards:
13601 * @ctxt: the schema parser context
13602 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013603 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013604 *
13605 * Unions the namespace constraints of the given wildcards.
13606 * @completeWild will hold the resulting union.
13607 * Returns a positive error code on failure, -1 in case of an
13608 * internal error, 0 otherwise.
13609 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013610static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013611xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013612 xmlSchemaWildcardPtr completeWild,
13613 xmlSchemaWildcardPtr curWild)
13614{
13615 xmlSchemaWildcardNsPtr cur, curB, tmp;
13616
13617 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013618 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013619 * value.
13620 */
13621 if ((completeWild->any == curWild->any) &&
13622 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13623 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013624
Daniel Veillard3646d642004-06-02 19:19:14 +000013625 if ((completeWild->negNsSet == NULL) ||
13626 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013627
Daniel Veillard3646d642004-06-02 19:19:14 +000013628 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013629 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013630
13631 /*
13632 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013633 */
13634 cur = completeWild->nsSet;
13635 while (cur != NULL) {
13636 found = 0;
13637 curB = curWild->nsSet;
13638 while (curB != NULL) {
13639 if (cur->value == curB->value) {
13640 found = 1;
13641 break;
13642 }
13643 curB = curB->next;
13644 }
13645 if (!found)
13646 break;
13647 cur = cur->next;
13648 }
13649 if (found)
13650 return(0);
13651 } else
13652 return(0);
13653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013654 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013655 /*
13656 * 2 If either O1 or O2 is any, then any must be the value
13657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013658 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013659 if (completeWild->any == 0) {
13660 completeWild->any = 1;
13661 if (completeWild->nsSet != NULL) {
13662 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13663 completeWild->nsSet = NULL;
13664 }
13665 if (completeWild->negNsSet != NULL) {
13666 xmlFree(completeWild->negNsSet);
13667 completeWild->negNsSet = NULL;
13668 }
13669 }
Daniel Veillard50355f02004-06-08 17:52:16 +000013670 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013671 }
13672 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013673 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013674 * then the union of those sets must be the value.
13675 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013676 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013677 int found;
13678 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679
Daniel Veillard3646d642004-06-02 19:19:14 +000013680 cur = curWild->nsSet;
13681 start = completeWild->nsSet;
13682 while (cur != NULL) {
13683 found = 0;
13684 curB = start;
13685 while (curB != NULL) {
13686 if (cur->value == curB->value) {
13687 found = 1;
13688 break;
13689 }
13690 curB = curB->next;
13691 }
13692 if (!found) {
13693 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013694 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013695 return (-1);
13696 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000013698 completeWild->nsSet = tmp;
13699 }
13700 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013701 }
13702
Daniel Veillard3646d642004-06-02 19:19:14 +000013703 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013704 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013705 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013706 * 4 If the two are negations of different values (namespace names
Jan Pokorný761c9e92013-11-29 23:26:27 +010013707 * or `absent`), then a pair of not and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013708 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013709 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013710 (curWild->negNsSet != NULL) &&
13711 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13712 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000013713
13714 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013715 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013716 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013717 * 5.
13718 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013719 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013720 (completeWild->negNsSet->value != NULL) &&
13721 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 (curWild->negNsSet->value != NULL) &&
13724 (completeWild->nsSet != NULL))) {
13725
13726 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727
Daniel Veillard3646d642004-06-02 19:19:14 +000013728 if (completeWild->nsSet != NULL) {
13729 cur = completeWild->nsSet;
13730 curB = curWild->negNsSet;
13731 } else {
13732 cur = curWild->nsSet;
13733 curB = completeWild->negNsSet;
13734 }
13735 nsFound = 0;
13736 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013737 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013738 absentFound = 1;
13739 else if (cur->value == curB->value)
13740 nsFound = 1;
13741 if (nsFound && absentFound)
13742 break;
13743 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013744 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013745
13746 if (nsFound && absentFound) {
13747 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 * 5.1 If the set S includes both the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013749 * name and `absent`, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013751 completeWild->any = 1;
13752 if (completeWild->nsSet != NULL) {
13753 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13754 completeWild->nsSet = NULL;
13755 }
13756 if (completeWild->negNsSet != NULL) {
13757 xmlFree(completeWild->negNsSet);
13758 completeWild->negNsSet = NULL;
13759 }
13760 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013761 /*
13762 * 5.2 If the set S includes the negated namespace name
Jan Pokorný761c9e92013-11-29 23:26:27 +010013763 * but not `absent`, then a pair of not and `absent` must
Daniel Veillard3646d642004-06-02 19:19:14 +000013764 * be the value.
13765 */
13766 if (completeWild->nsSet != NULL) {
13767 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13768 completeWild->nsSet = NULL;
13769 }
13770 if (completeWild->negNsSet == NULL) {
13771 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13772 if (completeWild->negNsSet == NULL)
13773 return (-1);
13774 }
13775 completeWild->negNsSet->value = NULL;
13776 } else if ((!nsFound) && absentFound) {
13777 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013778 * 5.3 If the set S includes `absent` but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000013779 * namespace name, then the union is not expressible.
13780 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013781 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000013782 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Haibo Huangcfd91dc2020-07-30 23:01:33 -070013783 "The union of the wildcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013784 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013785 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000013786 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787 /*
13788 * 5.4 If the set S does not include either the negated namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013789 * name or `absent`, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000013790 * and a namespace name must be the value.
13791 */
13792 if (completeWild->negNsSet == NULL) {
13793 if (completeWild->nsSet != NULL) {
13794 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13795 completeWild->nsSet = NULL;
13796 }
13797 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13798 if (completeWild->negNsSet == NULL)
13799 return (-1);
13800 completeWild->negNsSet->value = curWild->negNsSet->value;
13801 }
13802 }
13803 return (0);
13804 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013806 * 6.
13807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013808 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013809 (completeWild->negNsSet->value == NULL) &&
13810 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013811 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013812 (curWild->negNsSet->value == NULL) &&
13813 (completeWild->nsSet != NULL))) {
13814
13815 if (completeWild->nsSet != NULL) {
13816 cur = completeWild->nsSet;
13817 } else {
13818 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013819 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013820 while (cur != NULL) {
13821 if (cur->value == NULL) {
13822 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013823 * 6.1 If the set S includes `absent`, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013824 * value.
13825 */
13826 completeWild->any = 1;
13827 if (completeWild->nsSet != NULL) {
13828 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13829 completeWild->nsSet = NULL;
13830 }
13831 if (completeWild->negNsSet != NULL) {
13832 xmlFree(completeWild->negNsSet);
13833 completeWild->negNsSet = NULL;
13834 }
13835 return (0);
13836 }
13837 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013839 if (completeWild->negNsSet == NULL) {
13840 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013841 * 6.2 If the set S does not include `absent`, then a pair of not
13842 * and `absent` must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013843 */
13844 if (completeWild->nsSet != NULL) {
13845 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13846 completeWild->nsSet = NULL;
13847 }
13848 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13849 if (completeWild->negNsSet == NULL)
13850 return (-1);
13851 completeWild->negNsSet->value = NULL;
13852 }
13853 return (0);
13854 }
13855 return (0);
13856
13857}
13858
Daniel Veillard50355f02004-06-08 17:52:16 +000013859/**
13860 * xmlSchemaIntersectWildcards:
13861 * @ctxt: the schema parser context
13862 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000013864 *
13865 * Intersects the namespace constraints of the given wildcards.
13866 * @completeWild will hold the resulting intersection.
13867 * Returns a positive error code on failure, -1 in case of an
13868 * internal error, 0 otherwise.
13869 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013870static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013871xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000013872 xmlSchemaWildcardPtr completeWild,
13873 xmlSchemaWildcardPtr curWild)
13874{
William M. Brack803812b2004-06-03 02:11:24 +000013875 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013876
13877 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000013879 * value.
13880 */
13881 if ((completeWild->any == curWild->any) &&
13882 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13883 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013884
Daniel Veillard3646d642004-06-02 19:19:14 +000013885 if ((completeWild->negNsSet == NULL) ||
13886 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013887
Daniel Veillard3646d642004-06-02 19:19:14 +000013888 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000013889 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013890
13891 /*
13892 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000013893 */
13894 cur = completeWild->nsSet;
13895 while (cur != NULL) {
13896 found = 0;
13897 curB = curWild->nsSet;
13898 while (curB != NULL) {
13899 if (cur->value == curB->value) {
13900 found = 1;
13901 break;
13902 }
13903 curB = curB->next;
13904 }
13905 if (!found)
13906 break;
13907 cur = cur->next;
13908 }
13909 if (found)
13910 return(0);
13911 } else
13912 return(0);
13913 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013914 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013915 /*
13916 * 2 If either O1 or O2 is any, then the other must be the value.
13917 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013918 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013919 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013921 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013922 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013923 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013924 * 3 If either O1 or O2 is a pair of not and a value (a namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010013925 * name or `absent`) and the other is a set of (namespace names or
13926 * `absent`), then that set, minus the negated value if it was in
13927 * the set, minus `absent` if it was in the set, must be the value.
Daniel Veillard3646d642004-06-02 19:19:14 +000013928 */
13929 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13930 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13931 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013932
Daniel Veillard3646d642004-06-02 19:19:14 +000013933 if (completeWild->nsSet == NULL) {
13934 neg = completeWild->negNsSet->value;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000013935 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
Daniel Veillard3646d642004-06-02 19:19:14 +000013936 return(-1);
13937 } else
13938 neg = curWild->negNsSet->value;
13939 /*
13940 * Remove absent and negated.
13941 */
13942 prev = NULL;
13943 cur = completeWild->nsSet;
13944 while (cur != NULL) {
13945 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013947 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013949 prev->next = cur->next;
13950 xmlFree(cur);
13951 break;
13952 }
13953 prev = cur;
13954 cur = cur->next;
13955 }
13956 if (neg != NULL) {
13957 prev = NULL;
13958 cur = completeWild->nsSet;
13959 while (cur != NULL) {
13960 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013961 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013962 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013963 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013964 prev->next = cur->next;
13965 xmlFree(cur);
13966 break;
13967 }
13968 prev = cur;
13969 cur = cur->next;
13970 }
13971 }
13972
13973 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013975 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010013976 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
Daniel Veillard3646d642004-06-02 19:19:14 +000013977 * then the intersection of those sets must be the value.
13978 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013979 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013980 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013981
Daniel Veillard3646d642004-06-02 19:19:14 +000013982 cur = completeWild->nsSet;
13983 prev = NULL;
13984 while (cur != NULL) {
13985 found = 0;
13986 curB = curWild->nsSet;
13987 while (curB != NULL) {
13988 if (cur->value == curB->value) {
13989 found = 1;
13990 break;
13991 }
13992 curB = curB->next;
13993 }
13994 if (!found) {
13995 if (prev == NULL)
13996 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013997 else
Daniel Veillard3646d642004-06-02 19:19:14 +000013998 prev->next = cur->next;
13999 tmp = cur->next;
14000 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014001 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014002 continue;
14003 }
14004 prev = cur;
14005 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014006 }
14007
Daniel Veillard3646d642004-06-02 19:19:14 +000014008 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014009 }
14010 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000014011 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 */
14013 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000014014 (curWild->negNsSet != NULL) &&
14015 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014016 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000014017 (curWild->negNsSet->value != NULL)) {
14018
14019 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014020 "The intersection of the wildcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014021 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000014022 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014023 }
14024 /*
14025 * 6 If the one is a negation of a namespace name and the other
Jan Pokorný761c9e92013-11-29 23:26:27 +010014026 * is a negation of `absent`, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000014027 * of a namespace name must be the value.
14028 */
14029 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14030 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014031 (completeWild->negNsSet->value == NULL)) {
14032 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000014033 }
14034 return(0);
14035}
14036
Daniel Veillard50355f02004-06-08 17:52:16 +000014037/**
14038 * xmlSchemaIsWildcardNsConstraintSubset:
14039 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014040 * @sub: the first wildcard
14041 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000014042 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014043 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14044 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014045 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014046 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000014047 */
14048static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014049xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14050 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051{
Daniel Veillard50355f02004-06-08 17:52:16 +000014052 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014053 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000014054 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014055 if (super->any)
14056 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000014057 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014058 * 2.1 sub must be a pair of not and a namespace name or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000014059 * 2.2 super must be a pair of not and the same value.
14060 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014061 if ((sub->negNsSet != NULL) &&
14062 (super->negNsSet != NULL) &&
Ryan Sleevi5cf1deb2012-02-29 10:56:32 +080014063 (sub->negNsSet->value == super->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014064 return (0);
14065 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014066 * 3.1 sub must be a set whose members are either namespace names or `absent`.
Daniel Veillard50355f02004-06-08 17:52:16 +000014067 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014068 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014069 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014070 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000014071 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014072 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014073 xmlSchemaWildcardNsPtr cur, curB;
14074 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014075
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014076 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000014077 while (cur != NULL) {
14078 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014079 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000014080 while (curB != NULL) {
14081 if (cur->value == curB->value) {
14082 found = 1;
14083 break;
14084 }
14085 curB = curB->next;
14086 }
14087 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014088 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014089 cur = cur->next;
14090 }
14091 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014092 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014093 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000014094 xmlSchemaWildcardNsPtr cur;
14095 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014096 * 3.2.2 super must be a pair of not and a namespace name or
Jan Pokorný761c9e92013-11-29 23:26:27 +010014097 * `absent` and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000014098 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014099 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014100 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014101 if (cur->value == super->negNsSet->value)
14102 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014103 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014104 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014105 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000014106 }
14107 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014108 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000014109}
14110
Daniel Veillard50355f02004-06-08 17:52:16 +000014111static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014112xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113 int *fixed,
14114 const xmlChar **value,
14115 xmlSchemaValPtr *val)
14116{
14117 *fixed = 0;
14118 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014119 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014120 *val = NULL;
14121
Daniel Veillarddee23482008-04-11 12:58:43 +000014122 if (attruse->defValue != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014123 *value = attruse->defValue;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014124 if (val != NULL)
14125 *val = attruse->defVal;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014126 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014127 *fixed = 1;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014128 return(1);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000014129 } else if ((attruse->attrDecl != NULL) &&
14130 (attruse->attrDecl->defValue != NULL)) {
14131 *value = attruse->attrDecl->defValue;
14132 if (val != NULL)
14133 *val = attruse->attrDecl->defVal;
14134 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014135 *fixed = 1;
14136 return(1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014137 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014138 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014139}
Daniel Veillard3646d642004-06-02 19:19:14 +000014140/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014141 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000014142 * @wild: the wildcard
14143 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014144 *
14145 * Validation Rule: Wildcard allows Namespace Name
14146 * (cvc-wildcard-namespace)
14147 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014148 * Returns 0 if the given namespace matches the wildcard,
14149 * 1 otherwise and -1 on API errors.
Daniel Veillard3646d642004-06-02 19:19:14 +000014150 */
14151static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014152xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14153 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000014154{
14155 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014156 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014157
14158 if (wild->any)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014159 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014160 else if (wild->nsSet != NULL) {
14161 xmlSchemaWildcardNsPtr cur;
14162
14163 cur = wild->nsSet;
14164 while (cur != NULL) {
14165 if (xmlStrEqual(cur->value, ns))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014166 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000014167 cur = cur->next;
14168 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014169 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000014170 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014171 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014172
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014173 return(1);
14174}
14175
14176#define XML_SCHEMA_ACTION_DERIVE 0
14177#define XML_SCHEMA_ACTION_REDEFINE 1
14178
14179#define WXS_ACTION_STR(a) \
14180((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14181
14182/*
14183* Schema Component Constraint:
14184* Derivation Valid (Restriction, Complex)
14185* derivation-ok-restriction (2) - (4)
14186*
14187* ATTENTION:
14188* In XML Schema 1.1 this will be:
14189* Validation Rule:
14190* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14191*
14192*/
14193static int
14194xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14195 int action,
14196 xmlSchemaBasicItemPtr item,
14197 xmlSchemaBasicItemPtr baseItem,
14198 xmlSchemaItemListPtr uses,
14199 xmlSchemaItemListPtr baseUses,
14200 xmlSchemaWildcardPtr wild,
14201 xmlSchemaWildcardPtr baseWild)
Daniel Veillarddee23482008-04-11 12:58:43 +000014202{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014203 xmlSchemaAttributeUsePtr cur = NULL, bcur;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014204 int i, j, found; /* err = 0; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014205 const xmlChar *bEffValue;
14206 int effFixed;
Daniel Veillarddee23482008-04-11 12:58:43 +000014207
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014208 if (uses != NULL) {
14209 for (i = 0; i < uses->nbItems; i++) {
14210 cur = uses->items[i];
14211 found = 0;
14212 if (baseUses == NULL)
14213 goto not_found;
14214 for (j = 0; j < baseUses->nbItems; j++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014215 bcur = baseUses->items[j];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014216 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14217 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14218 (WXS_ATTRUSE_DECL_TNS(cur) ==
14219 WXS_ATTRUSE_DECL_TNS(bcur)))
14220 {
14221 /*
14222 * (2.1) "If there is an attribute use in the {attribute
14223 * uses} of the {base type definition} (call this B) whose
14224 * {attribute declaration} has the same {name} and {target
14225 * namespace}, then all of the following must be true:"
14226 */
14227 found = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000014228
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014229 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14230 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14231 {
14232 xmlChar *str = NULL;
14233 /*
14234 * (2.1.1) "one of the following must be true:"
14235 * (2.1.1.1) "B's {required} is false."
14236 * (2.1.1.2) "R's {required} is true."
14237 */
14238 xmlSchemaPAttrUseErr4(pctxt,
14239 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14240 WXS_ITEM_NODE(item), item, cur,
14241 "The 'optional' attribute use is inconsistent "
14242 "with the corresponding 'required' attribute use of "
14243 "the %s %s",
14244 WXS_ACTION_STR(action),
14245 xmlSchemaGetComponentDesignation(&str, baseItem),
14246 NULL, NULL);
14247 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014248 /* err = pctxt->err; */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014249 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014250 WXS_ATTRUSE_TYPEDEF(cur),
14251 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14252 {
14253 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014254
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014255 /*
14256 * SPEC (2.1.2) "R's {attribute declaration}'s
14257 * {type definition} must be validly derived from
14258 * B's {type definition} given the empty set as
Jan Pokorný761c9e92013-11-29 23:26:27 +010014259 * defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014260 */
14261 xmlSchemaPAttrUseErr4(pctxt,
14262 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14263 WXS_ITEM_NODE(item), item, cur,
14264 "The attribute declaration's %s "
14265 "is not validly derived from "
14266 "the corresponding %s of the "
14267 "attribute declaration in the %s %s",
14268 xmlSchemaGetComponentDesignation(&strA,
14269 WXS_ATTRUSE_TYPEDEF(cur)),
14270 xmlSchemaGetComponentDesignation(&strB,
14271 WXS_ATTRUSE_TYPEDEF(bcur)),
14272 WXS_ACTION_STR(action),
14273 xmlSchemaGetComponentDesignation(&strC, baseItem));
14274 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14275 FREE_AND_NULL(strA);
14276 FREE_AND_NULL(strB);
14277 FREE_AND_NULL(strC);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014278 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014279 } else {
14280 /*
14281 * 2.1.3 [Definition:] Let the effective value
14282 * constraint of an attribute use be its {value
14283 * constraint}, if present, otherwise its {attribute
14284 * declaration}'s {value constraint} .
14285 */
14286 xmlSchemaGetEffectiveValueConstraint(bcur,
14287 &effFixed, &bEffValue, NULL);
14288 /*
14289 * 2.1.3 ... one of the following must be true
14290 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010014291 * 2.1.3.1 B's `effective value constraint` is
14292 * `absent` or default.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014293 */
14294 if ((bEffValue != NULL) &&
14295 (effFixed == 1)) {
14296 const xmlChar *rEffValue = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014297
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014298 xmlSchemaGetEffectiveValueConstraint(bcur,
14299 &effFixed, &rEffValue, NULL);
14300 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014301 * 2.1.3.2 R's `effective value constraint` is
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014302 * fixed with the same string as B's.
14303 * MAYBE TODO: Compare the computed values.
14304 * Hmm, it says "same string" so
14305 * string-equality might really be sufficient.
14306 */
14307 if ((effFixed == 0) ||
14308 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14309 {
14310 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014311
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014312 xmlSchemaPAttrUseErr4(pctxt,
14313 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14314 WXS_ITEM_NODE(item), item, cur,
14315 "The effective value constraint of the "
14316 "attribute use is inconsistent with "
14317 "its correspondent in the %s %s",
14318 WXS_ACTION_STR(action),
14319 xmlSchemaGetComponentDesignation(&str,
14320 baseItem),
14321 NULL, NULL);
14322 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014323 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014324 }
14325 }
14326 }
14327 break;
14328 }
14329 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014330not_found:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014331 if (!found) {
14332 /*
14333 * (2.2) "otherwise the {base type definition} must have an
14334 * {attribute wildcard} and the {target namespace} of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014335 * R's {attribute declaration} must be `valid` with respect
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014336 * to that wildcard, as defined in Wildcard allows Namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010014337 * Name ($3.10.4)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014338 */
14339 if ((baseWild == NULL) ||
14340 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14341 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14342 {
14343 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014344
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014345 xmlSchemaPAttrUseErr4(pctxt,
14346 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14347 WXS_ITEM_NODE(item), item, cur,
14348 "Neither a matching attribute use, "
14349 "nor a matching wildcard exists in the %s %s",
14350 WXS_ACTION_STR(action),
14351 xmlSchemaGetComponentDesignation(&str, baseItem),
14352 NULL, NULL);
14353 FREE_AND_NULL(str);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000014354 /* err = pctxt->err; */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014355 }
14356 }
14357 }
14358 }
14359 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000014360 * SPEC derivation-ok-restriction (3):
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014361 * (3) "For each attribute use in the {attribute uses} of the {base type
14362 * definition} whose {required} is true, there must be an attribute
14363 * use with an {attribute declaration} with the same {name} and
14364 * {target namespace} as its {attribute declaration} in the {attribute
14365 * uses} of the complex type definition itself whose {required} is true.
14366 */
14367 if (baseUses != NULL) {
14368 for (j = 0; j < baseUses->nbItems; j++) {
14369 bcur = baseUses->items[j];
14370 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14371 continue;
14372 found = 0;
14373 if (uses != NULL) {
14374 for (i = 0; i < uses->nbItems; i++) {
Daniel Veillarddee23482008-04-11 12:58:43 +000014375 cur = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014376 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14377 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14378 (WXS_ATTRUSE_DECL_TNS(cur) ==
14379 WXS_ATTRUSE_DECL_TNS(bcur))) {
14380 found = 1;
14381 break;
14382 }
14383 }
14384 }
14385 if (!found) {
14386 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014387
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014388 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14389 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14390 NULL, item,
14391 "A matching attribute use for the "
14392 "'required' %s of the %s %s is missing",
14393 xmlSchemaGetComponentDesignation(&strA, bcur),
14394 WXS_ACTION_STR(action),
14395 xmlSchemaGetComponentDesignation(&strB, baseItem),
14396 NULL);
14397 FREE_AND_NULL(strA);
14398 FREE_AND_NULL(strB);
14399 }
14400 }
14401 }
14402 /*
14403 * derivation-ok-restriction (4)
14404 */
14405 if (wild != NULL) {
14406 /*
14407 * (4) "If there is an {attribute wildcard}, all of the
14408 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000014409 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014410 if (baseWild == NULL) {
14411 xmlChar *str = NULL;
14412
14413 /*
14414 * (4.1) "The {base type definition} must also have one."
Daniel Veillarddee23482008-04-11 12:58:43 +000014415 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014416 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14417 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14418 NULL, item,
14419 "The %s has an attribute wildcard, "
14420 "but the %s %s '%s' does not have one",
Daniel Veillarddee23482008-04-11 12:58:43 +000014421 WXS_ITEM_TYPE_NAME(item),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014422 WXS_ACTION_STR(action),
14423 WXS_ITEM_TYPE_NAME(baseItem),
14424 xmlSchemaGetComponentQName(&str, baseItem));
14425 FREE_AND_NULL(str);
14426 return(pctxt->err);
14427 } else if ((baseWild->any == 0) &&
14428 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14429 {
14430 xmlChar *str = NULL;
14431 /*
14432 * (4.2) "The complex type definition's {attribute wildcard}'s
14433 * {namespace constraint} must be a subset of the {base type
14434 * definition}'s {attribute wildcard}'s {namespace constraint},
Jan Pokorný761c9e92013-11-29 23:26:27 +010014435 * as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014436 */
14437 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14438 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14439 NULL, item,
14440 "The attribute wildcard is not a valid "
14441 "subset of the wildcard in the %s %s '%s'",
14442 WXS_ACTION_STR(action),
14443 WXS_ITEM_TYPE_NAME(baseItem),
14444 xmlSchemaGetComponentQName(&str, baseItem),
14445 NULL);
14446 FREE_AND_NULL(str);
14447 return(pctxt->err);
14448 }
Jan Pokorný761c9e92013-11-29 23:26:27 +010014449 /* 4.3 Unless the {base type definition} is the `ur-type
14450 * definition`, the complex type definition's {attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014451 * wildcard}'s {process contents} must be identical to or
14452 * stronger than the {base type definition}'s {attribute
14453 * wildcard}'s {process contents}, where strict is stronger
14454 * than lax is stronger than skip.
14455 */
14456 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14457 (wild->processContents < baseWild->processContents)) {
14458 xmlChar *str = NULL;
14459 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14460 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14461 NULL, baseItem,
14462 "The {process contents} of the attribute wildcard is "
14463 "weaker than the one in the %s %s '%s'",
14464 WXS_ACTION_STR(action),
14465 WXS_ITEM_TYPE_NAME(baseItem),
14466 xmlSchemaGetComponentQName(&str, baseItem),
14467 NULL);
14468 FREE_AND_NULL(str)
14469 return(pctxt->err);
14470 }
14471 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014472 return(0);
14473}
14474
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014475
14476static int
14477xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14478 xmlSchemaBasicItemPtr item,
14479 xmlSchemaWildcardPtr *completeWild,
14480 xmlSchemaItemListPtr list,
14481 xmlSchemaItemListPtr prohibs);
Daniel Veillard3646d642004-06-02 19:19:14 +000014482/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014483 * xmlSchemaFixupTypeAttributeUses:
Daniel Veillard3646d642004-06-02 19:19:14 +000014484 * @ctxt: the schema parser context
14485 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014486 *
Daniel Veillard3646d642004-06-02 19:19:14 +000014487 *
14488 * Builds the wildcard and the attribute uses on the given complex type.
14489 * Returns -1 if an internal error occurs, 0 otherwise.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014490 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014491 * ATTENTION TODO: Experimentally this uses pointer comparisons for
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014492 * strings, so recheck this if we start to hardcode some schemata, since
14493 * they might not be in the same dict.
14494 * NOTE: It is allowed to "extend" the xs:anyType type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014495 */
14496static int
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014497xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014498 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000014499{
14500 xmlSchemaTypePtr baseType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000014501 xmlSchemaAttributeUsePtr use;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014502 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014503
Daniel Veillard01fa6152004-06-29 17:04:39 +000014504 if (type->baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014505 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014507 return (-1);
14508 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014509 baseType = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014510 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014511 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014512 return(-1);
14513
14514 uses = type->attrUses;
14515 baseUses = baseType->attrUses;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014516 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014517 * Expand attribute group references. And build the 'complete'
14518 * wildcard, i.e. intersect multiple wildcards.
14519 * Move attribute prohibitions into a separate list.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014520 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014521 if (uses != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014522 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014523 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014524 * This one will transfer all attr. prohibitions
14525 * into pctxt->attrProhibs.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014526 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014527 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14528 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14529 pctxt->attrProhibs) == -1)
14530 {
14531 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14532 "failed to expand attributes");
14533 }
14534 if (pctxt->attrProhibs->nbItems != 0)
14535 prohibs = pctxt->attrProhibs;
14536 } else {
14537 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14538 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14539 NULL) == -1)
14540 {
14541 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14542 "failed to expand attributes");
14543 }
14544 }
14545 }
14546 /*
14547 * Inherit the attribute uses of the base type.
14548 */
14549 if (baseUses != NULL) {
14550 int i, j;
14551 xmlSchemaAttributeUseProhibPtr pro;
14552
14553 if (WXS_IS_RESTRICTION(type)) {
14554 int usesCount;
Daniel Veillarddee23482008-04-11 12:58:43 +000014555 xmlSchemaAttributeUsePtr tmp;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014556
14557 if (uses != NULL)
14558 usesCount = uses->nbItems;
14559 else
14560 usesCount = 0;
14561
14562 /* Restriction. */
14563 for (i = 0; i < baseUses->nbItems; i++) {
14564 use = baseUses->items[i];
14565 if (prohibs) {
14566 /*
14567 * Filter out prohibited uses.
14568 */
14569 for (j = 0; j < prohibs->nbItems; j++) {
14570 pro = prohibs->items[j];
14571 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14572 (WXS_ATTRUSE_DECL_TNS(use) ==
14573 pro->targetNamespace))
14574 {
14575 goto inherit_next;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014576 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014577 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014578 }
14579 if (usesCount) {
14580 /*
14581 * Filter out existing uses.
14582 */
14583 for (j = 0; j < usesCount; j++) {
14584 tmp = uses->items[j];
14585 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14586 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14587 (WXS_ATTRUSE_DECL_TNS(use) ==
14588 WXS_ATTRUSE_DECL_TNS(tmp)))
14589 {
14590 goto inherit_next;
14591 }
14592 }
14593 }
14594 if (uses == NULL) {
14595 type->attrUses = xmlSchemaItemListCreate();
14596 if (type->attrUses == NULL)
14597 goto exit_failure;
14598 uses = type->attrUses;
14599 }
14600 xmlSchemaItemListAddSize(uses, 2, use);
14601inherit_next: {}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014602 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014603 } else {
14604 /* Extension. */
Daniel Veillarddee23482008-04-11 12:58:43 +000014605 for (i = 0; i < baseUses->nbItems; i++) {
14606 use = baseUses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014607 if (uses == NULL) {
14608 type->attrUses = xmlSchemaItemListCreate();
14609 if (type->attrUses == NULL)
14610 goto exit_failure;
14611 uses = type->attrUses;
14612 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014613 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014614 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014615 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014616 }
14617 /*
14618 * Shrink attr. uses.
14619 */
14620 if (uses) {
14621 if (uses->nbItems == 0) {
14622 xmlSchemaItemListFree(uses);
14623 type->attrUses = NULL;
14624 }
14625 /*
14626 * TODO: We could shrink the size of the array
14627 * to fit the actual number of items.
14628 */
14629 }
14630 /*
14631 * Compute the complete wildcard.
14632 */
Daniel Veillarddee23482008-04-11 12:58:43 +000014633 if (WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014634 if (baseType->attributeWildcard != NULL) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014635 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014636 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014637 * the appropriate case among the following:"
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014638 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014639 if (type->attributeWildcard != NULL) {
14640 /*
14641 * Union the complete wildcard with the base wildcard.
14642 * SPEC {attribute wildcard}
14643 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
Jan Pokorný761c9e92013-11-29 23:26:27 +010014644 * and {annotation} are those of the `complete wildcard`,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014645 * and whose {namespace constraint} is the intensional union
Jan Pokorný761c9e92013-11-29 23:26:27 +010014646 * of the {namespace constraint} of the `complete wildcard`
14647 * and of the `base wildcard`, as defined in Attribute
14648 * Wildcard Union ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014649 */
14650 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14651 baseType->attributeWildcard) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000014652 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014653 } else {
14654 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014655 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14656 * then the `base wildcard`."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014657 */
14658 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillarddee23482008-04-11 12:58:43 +000014659 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014660 } else {
14661 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014662 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14663 * `complete wildcard`"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014664 * NOOP
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014665 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014666 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014667 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014668 /*
14669 * SPEC {attribute wildcard}
14670 * (3.1) "If the <restriction> alternative is chosen, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010014671 * `complete wildcard`;"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014672 * NOOP
14673 */
Daniel Veillard50355f02004-06-08 17:52:16 +000014674 }
Daniel Veillarddee23482008-04-11 12:58:43 +000014675
Daniel Veillard3646d642004-06-02 19:19:14 +000014676 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014677
14678exit_failure:
14679 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000014680}
14681
14682/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014683 * xmlSchemaTypeFinalContains:
14684 * @schema: the schema
14685 * @type: the type definition
14686 * @final: the final
14687 *
14688 * Evaluates if a type definition contains the given "final".
14689 * This does take "finalDefault" into account as well.
14690 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014691 * Returns 1 if the type does contain the given "final",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014692 * 0 otherwise.
14693 */
14694static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014695xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014696{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014697 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014698 return (0);
14699 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014700 return (1);
14701 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014702 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014703}
14704
14705/**
14706 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14707 * @type: the Union Simple Type
14708 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014709 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014710 * returns NULL otherwise.
14711 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000014712static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000014713xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14714{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014715 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014716 if (type->memberTypes != NULL)
14717 return (type->memberTypes);
14718 else
14719 type = type->baseType;
14720 }
14721 return (NULL);
14722}
14723
Haibo Huangd75f3892021-01-05 21:34:50 -080014724#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000014725/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014726 * xmlSchemaGetParticleTotalRangeMin:
14727 * @particle: the particle
14728 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014730 * (all and sequence) + (choice)
14731 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014732 * Returns the minimum Effective Total Range.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014733 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014734static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014735xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014736{
14737 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014738 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014739 return (0);
14740 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014741 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014742 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014743 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744
14745 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 while (part != NULL) {
14748 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14749 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014750 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014751 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014752 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014753 if (cur == 0)
14754 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014755 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014757 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014758 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014759 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014760 } else {
14761 /* <all> and <sequence> */
14762 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014763 xmlSchemaParticlePtr part =
14764 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014765
14766 if (part == NULL)
14767 return (0);
14768 do {
14769 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14770 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014771 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014772 else
14773 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014774 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014776 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 }
14778}
14779
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014780/**
14781 * xmlSchemaGetParticleTotalRangeMax:
14782 * @particle: the particle
14783 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014784 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014785 * (all and sequence) + (choice)
14786 *
14787 * Returns the maximum Effective Total Range.
14788 */
14789static int
14790xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14791{
14792 if ((particle->children == NULL) ||
14793 (particle->children->children == NULL))
14794 return (0);
14795 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14796 int max = -1, cur;
14797 xmlSchemaParticlePtr part =
14798 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014799
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014800 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14801 if (part->children == NULL)
14802 continue;
14803 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14804 (part->children->type == XML_SCHEMA_TYPE_ANY))
14805 cur = part->maxOccurs;
14806 else
14807 cur = xmlSchemaGetParticleTotalRangeMax(part);
14808 if (cur == UNBOUNDED)
14809 return (UNBOUNDED);
14810 if ((max < cur) || (max == -1))
14811 max = cur;
14812 }
14813 /* TODO: Handle overflows? */
14814 return (particle->maxOccurs * max);
14815 } else {
14816 /* <all> and <sequence> */
14817 int sum = 0, cur;
14818 xmlSchemaParticlePtr part =
14819 (xmlSchemaParticlePtr) particle->children->children;
14820
14821 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14822 if (part->children == NULL)
14823 continue;
14824 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14825 (part->children->type == XML_SCHEMA_TYPE_ANY))
14826 cur = part->maxOccurs;
14827 else
14828 cur = xmlSchemaGetParticleTotalRangeMax(part);
14829 if (cur == UNBOUNDED)
14830 return (UNBOUNDED);
14831 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14832 return (UNBOUNDED);
14833 sum += cur;
14834 }
14835 /* TODO: Handle overflows? */
14836 return (particle->maxOccurs * sum);
14837 }
14838}
Daniel Veillard15724252008-08-30 15:01:04 +000014839#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014840
14841/**
Haibo Huangd75f3892021-01-05 21:34:50 -080014842 * xmlSchemaGetParticleEmptiable:
14843 * @particle: the particle
14844 *
14845 * Returns 1 if emptiable, 0 otherwise.
14846 */
14847static int
14848xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14849{
14850 xmlSchemaParticlePtr part;
14851 int emptiable;
14852
14853 if ((particle->children == NULL) || (particle->minOccurs == 0))
14854 return (1);
14855
14856 part = (xmlSchemaParticlePtr) particle->children->children;
14857 if (part == NULL)
14858 return (1);
14859
14860 while (part != NULL) {
14861 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14862 (part->children->type == XML_SCHEMA_TYPE_ANY))
14863 emptiable = (part->minOccurs == 0);
14864 else
14865 emptiable = xmlSchemaGetParticleEmptiable(part);
14866 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14867 if (emptiable)
14868 return (1);
14869 } else {
14870 /* <all> and <sequence> */
14871 if (!emptiable)
14872 return (0);
14873 }
14874 part = (xmlSchemaParticlePtr) part->next;
14875 }
14876
14877 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14878 return (0);
14879 else
14880 return (1);
14881}
14882
14883/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014884 * xmlSchemaIsParticleEmptiable:
14885 * @particle: the particle
14886 *
14887 * Schema Component Constraint: Particle Emptiable
14888 * Checks whether the given particle is emptiable.
14889 *
14890 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014891 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014892static int
14893xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14894{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014895 /*
14896 * SPEC (1) "Its {min occurs} is 0."
14897 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014898 if ((particle == NULL) || (particle->minOccurs == 0) ||
14899 (particle->children == NULL))
14900 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014901 /*
14902 * SPEC (2) "Its {term} is a group and the minimum part of the
14903 * effective total range of that group, [...] is 0."
14904 */
Haibo Huangd75f3892021-01-05 21:34:50 -080014905 if (WXS_IS_MODEL_GROUP(particle->children))
14906 return (xmlSchemaGetParticleEmptiable(particle));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014907 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014908}
14909
14910/**
14911 * xmlSchemaCheckCOSSTDerivedOK:
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014912 * @actxt: a context
Daniel Veillard01fa6152004-06-29 17:04:39 +000014913 * @type: the derived simple type definition
14914 * @baseType: the base type definition
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014915 * @subset: the subset of ('restriction', etc.)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014916 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014917 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014918 * Type Derivation OK (Simple) (cos-st-derived-OK)
14919 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014920 * Checks whether @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000014921 * derived from @baseType.
14922 *
14923 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014924 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014925static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014926xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014927 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014928 xmlSchemaTypePtr baseType,
14929 int subset)
14930{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014931 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014932 * 1 They are the same type definition.
Haibo Huangcfd91dc2020-07-30 23:01:33 -070014933 * TODO: The identity check might have to be more complex than this.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014934 */
14935 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014936 return (0);
14937 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014938 * 2.1 restriction is not in the subset, or in the {final}
14939 * of its own {base type definition};
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014940 *
14941 * NOTE that this will be used also via "xsi:type".
14942 *
14943 * TODO: Revise this, it looks strange. How can the "type"
14944 * not be fixed or *in* fixing?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014945 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014946 if (WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014947 if (xmlSchemaTypeFixup(type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014948 return(-1);
14949 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014950 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014951 return(-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014952 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014953 (xmlSchemaTypeFinalContains(type->baseType,
14954 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14955 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014956 }
14957 /* 2.2 */
14958 if (type->baseType == baseType) {
14959 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014960 * 2.2.1 D's `base type definition` is B.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014961 */
14962 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014963 }
14964 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014965 * 2.2.2 D's `base type definition` is not the `ur-type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014966 * and is validly derived from B given the subset, as defined by this
14967 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014968 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014969 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014970 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014971 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014972 return (0);
14973 }
14974 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010014975 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14976 * definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014977 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014978 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14979 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014980 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014981 }
14982 /*
14983 * 2.2.4 B's {variety} is union and D is validly derived from a type
14984 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014985 * defined by this constraint.
14986 *
14987 * NOTE: This seems not to involve built-in types, since there is no
14988 * built-in Union Simple Type.
14989 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014990 if (WXS_IS_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014991 xmlSchemaTypeLinkPtr cur;
14992
14993 cur = baseType->memberTypes;
14994 while (cur != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014995 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014996 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014997 return(-1);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000014998 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000014999 type, cur->type, subset) == 0)
15000 {
15001 /*
15002 * It just has to be validly derived from at least one
15003 * member-type.
15004 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015005 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015006 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015007 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015008 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015009 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015010 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15011}
15012
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015013/**
15014 * xmlSchemaCheckTypeDefCircularInternal:
15015 * @pctxt: the schema parser context
15016 * @ctxtType: the type definition
15017 * @ancestor: an ancestor of @ctxtType
15018 *
15019 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015020 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015021 *
15022 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15023 * circular, 0 otherwise.
15024 */
15025static int
15026xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15027 xmlSchemaTypePtr ctxtType,
15028 xmlSchemaTypePtr ancestor)
15029{
15030 int ret;
15031
15032 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15033 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015034
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015035 if (ctxtType == ancestor) {
15036 xmlSchemaPCustomErr(pctxt,
15037 XML_SCHEMAP_ST_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015038 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015039 "The definition is circular", NULL);
15040 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15041 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015042 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15043 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070015044 * Avoid infinite recursion on circular types not yet checked.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015045 */
15046 return (0);
15047 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015048 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15049 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15050 ancestor->baseType);
15051 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15052 return (ret);
15053}
15054
15055/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015056 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015057 * @item: the complex/simple type definition
15058 * @ctxt: the parser context
15059 * @name: the name
15060 *
15061 * Checks for circular type definitions.
15062 */
15063static void
15064xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015065 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015066{
15067 if ((item == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015068 (item->type == XML_SCHEMA_TYPE_BASIC) ||
15069 (item->baseType == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015070 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015071 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15072 item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015073}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015074
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015075/*
15076* Simple Type Definition Representation OK (src-simple-type) 4
15077*
15078* "4 Circular union type definition is disallowed. That is, if the
15079* <union> alternative is chosen, there must not be any entries in the
15080* memberTypes [attribute] at any depth which resolve to the component
15081* corresponding to the <simpleType>."
15082*
15083* Note that this should work on the *representation* of a component,
15084* thus assumes any union types in the member types not being yet
15085* substituted. At this stage we need the variety of the types
15086* to be already computed.
15087*/
15088static int
15089xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15090 xmlSchemaTypePtr ctxType,
15091 xmlSchemaTypeLinkPtr members)
Daniel Veillarddee23482008-04-11 12:58:43 +000015092{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015093 xmlSchemaTypeLinkPtr member;
15094 xmlSchemaTypePtr memberType;
Daniel Veillarddee23482008-04-11 12:58:43 +000015095
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015096 member = members;
15097 while (member != NULL) {
15098 memberType = member->type;
15099 while ((memberType != NULL) &&
15100 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15101 if (memberType == ctxType) {
15102 xmlSchemaPCustomErr(pctxt,
15103 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015104 WXS_BASIC_CAST ctxType, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015105 "The union type definition is circular", NULL);
15106 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15107 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015108 if ((WXS_IS_UNION(memberType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015109 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15110 {
15111 int res;
15112 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15113 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15114 ctxType,
15115 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15116 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15117 if (res != 0)
15118 return(res);
15119 }
15120 memberType = memberType->baseType;
15121 }
15122 member = member->next;
15123 }
15124 return(0);
15125}
15126
15127static int
15128xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15129 xmlSchemaTypePtr type)
15130{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015131 if (! WXS_IS_UNION(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015132 return(0);
15133 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15134 type->memberTypes));
15135}
15136
Daniel Veillard01fa6152004-06-29 17:04:39 +000015137/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015138 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015139 * @item: the complex/simple type definition
15140 * @ctxt: the parser context
15141 * @name: the name
15142 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070015143 * Resolves type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015144 */
15145static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015146xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015147 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015148{
15149 if (typeDef == NULL)
15150 return;
15151
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015152 /*
15153 * Resolve the base type.
15154 */
15155 if (typeDef->baseType == NULL) {
15156 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15157 typeDef->base, typeDef->baseNs);
15158 if (typeDef->baseType == NULL) {
15159 xmlSchemaPResCompAttrErr(ctxt,
15160 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015161 WXS_BASIC_CAST typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015162 "base", typeDef->base, typeDef->baseNs,
15163 XML_SCHEMA_TYPE_SIMPLE, NULL);
15164 return;
15165 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015166 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015167 if (WXS_IS_SIMPLE(typeDef)) {
15168 if (WXS_IS_UNION(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015169 /*
15170 * Resolve the memberTypes.
15171 */
15172 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15173 return;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015174 } else if (WXS_IS_LIST(typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015175 /*
15176 * Resolve the itemType.
15177 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015178 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15179
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015181 typeDef->base, typeDef->baseNs);
15182
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015183 if ((typeDef->subtypes == NULL) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015184 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15185 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015186 typeDef->subtypes = NULL;
15187 xmlSchemaPResCompAttrErr(ctxt,
15188 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015189 WXS_BASIC_CAST typeDef, typeDef->node,
15190 "itemType", typeDef->base, typeDef->baseNs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 XML_SCHEMA_TYPE_SIMPLE, NULL);
15192 }
15193 }
15194 return;
15195 }
Daniel Veillarddee23482008-04-11 12:58:43 +000015196 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015197 /*
15198 * The ball of letters below means, that if we have a particle
15199 * which has a QName-helper component as its {term}, we want
15200 * to resolve it...
15201 */
15202 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15203 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15204 XML_SCHEMA_TYPE_PARTICLE) &&
15205 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15206 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15207 XML_SCHEMA_EXTRA_QNAMEREF))
15208 {
15209 xmlSchemaQNameRefPtr ref =
15210 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15211 xmlSchemaModelGroupDefPtr groupDef;
15212
15213 /*
15214 * URGENT TODO: Test this.
15215 */
15216 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15217 /*
15218 * Resolve the MG definition reference.
15219 */
15220 groupDef =
15221 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15222 ref->itemType, ref->name, ref->targetNamespace);
15223 if (groupDef == NULL) {
15224 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15225 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15226 "ref", ref->name, ref->targetNamespace, ref->itemType,
15227 NULL);
15228 /* Remove the particle. */
15229 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15230 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15231 /* Remove the particle. */
15232 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15233 else {
15234 /*
15235 * Assign the MG definition's {model group} to the
15236 * particle's {term}.
15237 */
15238 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
Daniel Veillarddee23482008-04-11 12:58:43 +000015239
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015240 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15241 /*
15242 * SPEC cos-all-limited (1.2)
15243 * "1.2 the {term} property of a particle with
15244 * {max occurs}=1 which is part of a pair which constitutes
15245 * the {content type} of a complex type definition."
15246 */
15247 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15248 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15249 /* TODO: error code */
15250 XML_SCHEMAP_COS_ALL_LIMITED,
15251 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15252 "The particle's {max occurs} must be 1, since the "
15253 "reference resolves to an 'all' model group",
15254 NULL, NULL);
15255 }
15256 }
15257 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015258 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015259}
15260
15261
15262
15263/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000015264 * xmlSchemaCheckSTPropsCorrect:
15265 * @ctxt: the schema parser context
15266 * @type: the simple type definition
15267 *
15268 * Checks st-props-correct.
15269 *
15270 * Returns 0 if the properties are correct,
15271 * if not, a positive error code and -1 on internal
15272 * errors.
15273 */
15274static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015275xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015276 xmlSchemaTypePtr type)
15277{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015278 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015279 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015280
Daniel Veillardc0826a72004-08-10 14:17:33 +000015281 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015282 /*
15283 * Schema Component Constraint: Simple Type Definition Properties Correct
15284 *
15285 * NOTE: This is somehow redundant, since we actually built a simple type
15286 * to have all the needed information; this acts as an self test.
15287 */
Jan Pokorný761c9e92013-11-29 23:26:27 +010015288 /* Base type: If the datatype has been `derived` by `restriction`
15289 * then the Simple Type Definition component from which it is `derived`,
15290 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015291 */
15292 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015293 /*
15294 * TODO: Think about: "modulo the impact of Missing
Jan Pokorný761c9e92013-11-29 23:26:27 +010015295 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015296 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015297 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015298 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015299 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015300 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015302
Daniel Veillard01fa6152004-06-29 17:04:39 +000015303 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015304 if (! WXS_IS_SIMPLE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015305 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015306 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015307 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015308 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015309 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015310 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015311 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15312 }
Toyoda Eizi8bb12982011-08-04 16:40:48 +080015313 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15314 (WXS_IS_RESTRICTION(type) == 0) &&
15315 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15316 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015317 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015318 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015319 WXS_BASIC_CAST type, NULL,
Daniel Veillardbf9c1da2008-08-26 07:46:42 +000015320 "A type, derived by list or union, must have "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015321 "the simple ur-type definition as base type, not '%s'",
15322 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015323 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015324 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15325 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015326 /*
15327 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015328 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015329 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15330 (! WXS_IS_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015331 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015332 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015333 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015334 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015335 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15336 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015337 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015338
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339 /*
15340 * 3 The {final} of the {base type definition} must not contain restriction.
15341 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015342 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015343 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15344 xmlSchemaPCustomErr(ctxt,
15345 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015346 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 "The 'final' of its base type '%s' must not contain "
15348 "'restriction'",
15349 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015350 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015351 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015352 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015353
15354 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015355 * 2 All simple type definitions must be derived ultimately from the `simple
15356 * ur-type definition` (so circular definitions are disallowed). That is, it
15357 * must be possible to reach a built-in primitive datatype or the `simple
15358 * ur-type definition` by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015359 *
15360 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000015361 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015362 return (0);
15363}
15364
15365/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015366 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015367 * @ctxt: the schema parser context
15368 * @type: the simple type definition
15369 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015370 * Schema Component Constraint:
15371 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15372
15373 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015374 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000015375 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015376 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015377 * a positive error code otherwise.
15378 */
15379static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015380xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015381 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015382{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015383 xmlChar *str = NULL;
15384
Daniel Veillard01fa6152004-06-29 17:04:39 +000015385 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15387 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015388 return (-1);
15389 }
15390
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015391 if (WXS_IS_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015392 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015393 /*
15394 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000015395 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015396 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015397 if (! WXS_IS_ATOMIC(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015398 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015399 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015400 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015401 "The base type '%s' is not an atomic simple type",
15402 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015403 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015404 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15405 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000015407 * restriction.
15408 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015409 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015410 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015411 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015412 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015413 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015414 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015415 "The final of its base type '%s' must not contain 'restriction'",
15416 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015417 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015418 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15419 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015420
15421 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015422 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015423 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015424 * Primitive datatypes.
15425 */
15426 if (type->facets != NULL) {
15427 xmlSchemaFacetPtr facet;
15428 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429
Daniel Veillard01fa6152004-06-29 17:04:39 +000015430 primitive = xmlSchemaGetPrimitiveType(type);
15431 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015432 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15433 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015434 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015436 facet = type->facets;
15437 do {
15438 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015439 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015440 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015441 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015442 type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015443 }
15444 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015445 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015446 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015447 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015448 }
15449 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015450 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15451 * of the {base type definition} (call this BF),then the DF's {value}
15452 * must be a valid restriction of BF's {value} as defined in
15453 * [XML Schemas: Datatypes]."
15454 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015455 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015456 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015457 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015458 } else if (WXS_IS_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015459 xmlSchemaTypePtr itemType = NULL;
15460
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015461 itemType = type->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015462 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015463 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15464 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015465 return (-1);
15466 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015467 if (WXS_IS_TYPE_NOT_FIXED(itemType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015468 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015469 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015470 * 2.1 The {item type definition} must have a {variety} of atomic or
15471 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000015472 * must be atomic).
15473 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015474 if ((! WXS_IS_ATOMIC(itemType)) &&
15475 (! WXS_IS_UNION(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015476 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015477 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015478 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015479 "The item type '%s' does not have a variety of atomic or union",
15480 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015481 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015482 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015483 } else if (WXS_IS_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015484 xmlSchemaTypeLinkPtr member;
15485
15486 member = itemType->memberTypes;
15487 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015488 if (! WXS_IS_ATOMIC(member->type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015489 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015490 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015491 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015492 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015493 "member type '%s' of this item type is not atomic",
15494 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015495 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015496 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15497 }
15498 member = member->next;
15499 }
15500 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015501
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015502 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015503 xmlSchemaFacetPtr facet;
15504 /*
15505 * This is the case if we have: <simpleType><list ..
15506 */
15507 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015508 * 2.3.1
15509 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000015510 * contain list.
15511 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015512 if (xmlSchemaTypeFinalContains(itemType,
15513 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15514 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015515 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015516 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015517 "The final of its item type '%s' must not contain 'list'",
15518 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015519 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015520 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15521 }
15522 /*
15523 * 2.3.1.2 The {facets} must only contain the whiteSpace
15524 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015525 * OPTIMIZE TODO: the S4S already disallows any facet
15526 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015527 */
15528 if (type->facets != NULL) {
15529 facet = type->facets;
15530 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015531 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
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_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015534 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015535 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15536 }
15537 facet = facet->next;
15538 } while (facet != NULL);
15539 }
15540 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015541 * MAYBE TODO: (Hmm, not really) Datatypes states:
Jan Pokorný761c9e92013-11-29 23:26:27 +010015542 * A `list` datatype can be `derived` from an `atomic` datatype
15543 * whose `lexical space` allows space (such as string or anyURI)or
15544 * a `union` datatype any of whose {member type definitions}'s
15545 * `lexical space` allows space.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015546 */
15547 } else {
15548 /*
15549 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015550 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015551 */
15552 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015553 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000015554 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15555 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015556 if (! WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015557 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015558 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015559 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015560 "The base type '%s' must be a list type",
15561 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015562 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015563 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15564 }
15565 /*
15566 * 2.3.2.2 The {final} of the {base type definition} must not
15567 * contain restriction.
15568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015569 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015570 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015571 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015572 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015573 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015574 "The 'final' of the base type '%s' must not contain 'restriction'",
15575 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015576 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015577 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15578 }
15579 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015580 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000015581 * from the {base type definition}'s {item type definition} given
Jan Pokorný761c9e92013-11-29 23:26:27 +010015582 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015583 */
15584 {
15585 xmlSchemaTypePtr baseItemType;
15586
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015587 baseItemType = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015588 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015589 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15590 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015591 return (-1);
15592 }
15593 if ((itemType != baseItemType) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015594 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015595 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015596 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015598 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015599 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015600 "The item type '%s' is not validly derived from "
15601 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015602 xmlSchemaGetComponentQName(&str, itemType),
15603 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15604 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015605
15606 FREE_AND_NULL(str)
15607 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015608 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015609 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15610 }
15611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015612
Daniel Veillard01fa6152004-06-29 17:04:39 +000015613 if (type->facets != NULL) {
15614 xmlSchemaFacetPtr facet;
15615 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015616 /*
15617 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000015618 * and enumeration facet components are allowed among the {facets}.
15619 */
15620 facet = type->facets;
15621 do {
15622 switch (facet->type) {
15623 case XML_SCHEMA_FACET_LENGTH:
15624 case XML_SCHEMA_FACET_MINLENGTH:
15625 case XML_SCHEMA_FACET_MAXLENGTH:
15626 case XML_SCHEMA_FACET_WHITESPACE:
15627 /*
15628 * TODO: 2.5.1.2 List datatypes
Jan Pokorný761c9e92013-11-29 23:26:27 +010015629 * The value of `whiteSpace` is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015630 */
15631 case XML_SCHEMA_FACET_PATTERN:
15632 case XML_SCHEMA_FACET_ENUMERATION:
15633 break;
15634 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015635 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015636 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015637 type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015638 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015639 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000015640 * invalid facets.
15641 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015642 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015643 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015644 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015645 facet = facet->next;
15646 } while (facet != NULL);
15647 if (ok == 0)
15648 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15649 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015650 * SPEC (2.3.2.5) (same as 1.3.2)
15651 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015652 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015653 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015654 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015655 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015656 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015657 } else if (WXS_IS_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015658 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015659 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000015660 * atomic or list.
15661 */
15662 xmlSchemaTypeLinkPtr member;
15663
15664 member = type->memberTypes;
15665 while (member != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015666 if (WXS_IS_TYPE_NOT_FIXED(member->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015667 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015668
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015669 if ((! WXS_IS_ATOMIC(member->type)) &&
15670 (! WXS_IS_LIST(member->type))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015671 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015672 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015673 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015674 "The member type '%s' is neither an atomic, nor a list type",
15675 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015676 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015677 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15678 }
15679 member = member->next;
15680 }
15681 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010015682 * 3.3.1 If the {base type definition} is the `simple ur-type
15683 * definition`
Daniel Veillard01fa6152004-06-29 17:04:39 +000015684 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015685 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015686 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015687 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000015688 * {final} which does not contain union.
15689 */
15690 member = type->memberTypes;
15691 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015692 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015693 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015695 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015696 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015697 "The 'final' of member type '%s' contains 'union'",
15698 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015699 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015700 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15701 }
15702 member = member->next;
15703 }
15704 /*
15705 * 3.3.1.2 The {facets} must be empty.
15706 */
15707 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015708 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015709 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015710 WXS_BASIC_CAST type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015711 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015712 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15713 }
15714 } else {
15715 /*
15716 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015717 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015718 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015719 if (! WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015720 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015721 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015722 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015723 "The base type '%s' is not a union type",
15724 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015725 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015726 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15727 }
15728 /*
15729 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15730 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015731 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015732 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015733 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015734 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015735 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015736 "The 'final' of its base type '%s' must not contain 'restriction'",
15737 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015738 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015739 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15740 }
15741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015742 * 3.3.2.3 The {member type definitions}, in order, must be validly
15743 * derived from the corresponding type definitions in the {base
15744 * type definition}'s {member type definitions} given the empty set,
Jan Pokorný761c9e92013-11-29 23:26:27 +010015745 * as defined in Type Derivation OK (Simple) ($3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000015746 */
15747 {
15748 xmlSchemaTypeLinkPtr baseMember;
15749
15750 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015751 * OPTIMIZE: if the type is restricting, it has no local defined
15752 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015753 * thus a check for equality can be skipped.
15754 */
15755 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015756 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015757 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000015758 * types of it's base type. This check seems not necessary with
15759 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015760 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015761 */
15762 if (type->memberTypes != NULL) {
15763 member = type->memberTypes;
15764 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015765 if ((member == NULL) && (baseMember != NULL)) {
15766 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15767 "different number of member types in base");
15768 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015769 while (member != NULL) {
15770 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15772 "different number of member types in base");
Daniel Veillard14b56432006-03-09 18:41:40 +000015773 } else if ((member->type != baseMember->type) &&
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000015774 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015775 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015776 xmlChar *strBMT = NULL, *strBT = NULL;
15777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015779 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015780 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015781 "The member type %s is not validly "
15782 "derived from its corresponding member "
15783 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015784 xmlSchemaGetComponentQName(&str, member->type),
15785 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15786 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015787 FREE_AND_NULL(str)
15788 FREE_AND_NULL(strBMT)
15789 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015790 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015791 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015792 member = member->next;
Daniel Veillardd44b9362009-09-07 12:15:08 +020015793 if (baseMember != NULL)
15794 baseMember = baseMember->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015795 }
15796 }
15797 }
15798 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000015800 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015801 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015802 if (type->facets != NULL) {
15803 xmlSchemaFacetPtr facet;
15804 int ok = 1;
15805
15806 facet = type->facets;
15807 do {
15808 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15809 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015810 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015811 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015812 type, facet);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015813 ok = 0;
15814 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015815 facet = facet->next;
15816 } while (facet != NULL);
15817 if (ok == 0)
15818 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015819
Daniel Veillard01fa6152004-06-29 17:04:39 +000015820 }
15821 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015822 * SPEC (3.3.2.5) (same as 1.3.2)
15823 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015824 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015825 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000015826 */
15827 }
15828 }
15829
15830 return (0);
15831}
15832
15833/**
15834 * xmlSchemaCheckSRCSimpleType:
15835 * @ctxt: the schema parser context
15836 * @type: the simple type definition
15837 *
Daniel Veillarddee23482008-04-11 12:58:43 +000015838 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015839 *
15840 * Returns 0 if the constraints are satisfied,
15841 * if not a positive error code and -1 on internal
15842 * errors.
15843 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015844#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000015845static int
15846xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15847 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015848{
15849 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000015850 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015851 * must satisfy the conditions set out in Constraints on Simple Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010015852 * Definition Schema Components ($3.14.6).
Daniel Veillarddee23482008-04-11 12:58:43 +000015853 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015854 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015855 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015856 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015857 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015858 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015859 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015860 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015861 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000015862 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015863 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015864 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015865 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015866 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015867 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015868 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015869 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015870 */
Daniel Veillarddee23482008-04-11 12:58:43 +000015871 } else if (WXS_IS_UNION(type)) {
15872 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015873 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015874 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015875 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015876 return (0);
15877}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015878#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015879
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015880static int
15881xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15882{
15883 if (ctxt->vctxt == NULL) {
15884 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15885 if (ctxt->vctxt == NULL) {
15886 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015887 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015888 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015889 "failed to create a temp. validation context.\n",
15890 NULL, NULL);
15891 return (-1);
15892 }
15893 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015894 xmlSchemaSetValidErrors(ctxt->vctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000015895 ctxt->error, ctxt->warning, ctxt->errCtxt);
15896 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15897 ctxt->serror, ctxt->errCtxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015898 }
15899 return (0);
15900}
15901
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015902static int
15903xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15904 xmlNodePtr node,
15905 xmlSchemaTypePtr type,
15906 const xmlChar *value,
15907 xmlSchemaValPtr *retVal,
15908 int fireErrors,
15909 int normalize,
15910 int isNormalized);
15911
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015912/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015913 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015914 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015915 * @type: the simple type definition
15916 * @value: the default value
15917 * @node: an optional node (the holder of the value)
15918 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015919 * Schema Component Constraint: Element Default Valid (Immediate)
15920 * (cos-valid-default)
15921 * This will be used by the parser only. For the validator there's
15922 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015923 *
15924 * Returns 0 if the constraints are satisfied,
15925 * if not, a positive error code and -1 on internal
15926 * errors.
15927 */
15928static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015929xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15930 xmlNodePtr node,
15931 xmlSchemaTypePtr type,
15932 const xmlChar *value,
15933 xmlSchemaValPtr *val)
15934{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015935 int ret = 0;
15936
15937 /*
15938 * cos-valid-default:
15939 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015940 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015941 * definition the appropriate case among the following must be true:
15942 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015943 if WXS_IS_COMPLEX(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015944 /*
15945 * Complex type.
15946 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015947 * SPEC (2.1) "its {content type} must be a simple type definition
15948 * or mixed."
15949 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010015950 * type}'s particle must be `emptiable` as defined by
15951 * Particle Emptiable ($3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015952 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015953 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15954 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015955 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015956 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015957 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015958 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015959 "For a string to be a valid default, the type definition "
15960 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015961 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015962 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15963 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015964 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015965 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015966 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010015967 * must be `valid` with respect to that definition as defined by String
15968 * Valid ($3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015969 *
15970 * AND
15971 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015972 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010015973 * string must be `valid` with respect to that simple type definition
15974 * as defined by String Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015975 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015976 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015977 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015978 type, value, val, 1, 1, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000015979 else if (WXS_HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015980 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015981 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015982 else
15983 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015984
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015985 if (ret < 0) {
15986 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15987 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015988 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015989
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015990 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000015991}
15992
15993/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015994 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000015995 * @ctxt: the schema parser context
15996 * @type: the complex type definition
15997 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015998 *.(4.6) Constraints on Complex Type Definition Schema Components
15999 * Schema Component Constraint:
16000 * Complex Type Definition Properties Correct (ct-props-correct)
16001 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000016002 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016003 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016004 * error code if not and -1 if an internal error occurred.
William M. Brack2f2a6632004-08-20 23:09:47 +000016005 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016006static int
16007xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16008 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000016009{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016010 /*
16011 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16012 *
16013 * SPEC (1) "The values of the properties of a complex type definition must
16014 * be as described in the property tableau in The Complex Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010016015 * Schema Component ($3.4.1), modulo the impact of Missing
16016 * Sub-components ($5.3)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016017 */
16018 if ((type->baseType != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016019 (WXS_IS_SIMPLE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016020 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016021 /*
16022 * SPEC (2) "If the {base type definition} is a simple type definition,
16023 * the {derivation method} must be extension."
16024 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016025 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016026 XML_SCHEMAP_SRC_CT_1,
Daniel Veillarddee23482008-04-11 12:58:43 +000016027 NULL, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016028 "If the base type is a simple type, the derivation method must be "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016029 "'extension'", NULL, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016030 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016031 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016032 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016033 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16034 * definition`. That is, it must be possible to reach the `ur-type
16035 * definition` by repeatedly following the {base type definition}."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016036 *
16037 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016038 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016039 /*
16040 * NOTE that (4) and (5) need the following:
16041 * - attribute uses need to be already inherited (apply attr. prohibitions)
16042 * - attribute group references need to be expanded already
16043 * - simple types need to be typefixed already
Daniel Veillarddee23482008-04-11 12:58:43 +000016044 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016045 if (type->attrUses &&
16046 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16047 {
16048 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16049 xmlSchemaAttributeUsePtr use, tmp;
16050 int i, j, hasId = 0;
16051
16052 for (i = uses->nbItems -1; i >= 0; i--) {
16053 use = uses->items[i];
Daniel Veillarddee23482008-04-11 12:58:43 +000016054
16055 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016056 * SPEC ct-props-correct
16057 * (4) "Two distinct attribute declarations in the
16058 * {attribute uses} must not have identical {name}s and
16059 * {target namespace}s."
16060 */
16061 if (i > 0) {
16062 for (j = i -1; j >= 0; j--) {
16063 tmp = uses->items[j];
16064 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16065 WXS_ATTRUSE_DECL_NAME(tmp)) &&
16066 (WXS_ATTRUSE_DECL_TNS(use) ==
16067 WXS_ATTRUSE_DECL_TNS(tmp)))
16068 {
16069 xmlChar *str = NULL;
16070
16071 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16072 XML_SCHEMAP_AG_PROPS_CORRECT,
16073 NULL, WXS_BASIC_CAST type,
16074 "Duplicate %s",
16075 xmlSchemaGetComponentDesignation(&str, use),
16076 NULL);
16077 FREE_AND_NULL(str);
16078 /*
16079 * Remove the duplicate.
16080 */
16081 if (xmlSchemaItemListRemove(uses, i) == -1)
16082 goto exit_failure;
16083 goto next_use;
16084 }
16085 }
16086 }
16087 /*
16088 * SPEC ct-props-correct
16089 * (5) "Two distinct attribute declarations in the
16090 * {attribute uses} must not have {type definition}s which
16091 * are or are derived from ID."
16092 */
16093 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16094 if (xmlSchemaIsDerivedFromBuiltInType(
16095 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000016096 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016097 if (hasId) {
16098 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016099
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016100 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16101 XML_SCHEMAP_AG_PROPS_CORRECT,
16102 NULL, WXS_BASIC_CAST type,
16103 "There must not exist more than one attribute "
16104 "declaration of type 'xs:ID' "
16105 "(or derived from 'xs:ID'). The %s violates this "
16106 "constraint",
16107 xmlSchemaGetComponentDesignation(&str, use),
16108 NULL);
16109 FREE_AND_NULL(str);
16110 if (xmlSchemaItemListRemove(uses, i) == -1)
16111 goto exit_failure;
16112 }
Daniel Veillarddee23482008-04-11 12:58:43 +000016113
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016114 hasId = 1;
16115 }
16116 }
16117next_use: {}
16118 }
16119 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016120 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016121exit_failure:
16122 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000016123}
16124
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016125static int
16126xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16127 xmlSchemaTypePtr typeB)
16128{
16129 /*
16130 * TODO: This should implement component-identity
16131 * in the future.
16132 */
16133 if ((typeA == NULL) || (typeB == NULL))
16134 return (0);
16135 return (typeA == typeB);
16136}
16137
16138/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016139 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016140 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016141 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016142 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000016143 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016144 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016145 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016146 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16147 *
16148 * STATUS: completed
16149 *
16150 * Returns 0 if the constraints are satisfied, or 1
16151 * if not.
16152 */
16153static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016154xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016155 xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016156 xmlSchemaTypePtr baseType,
16157 int set)
16158{
16159 int equal = xmlSchemaAreEqualTypes(type, baseType);
16160 /* TODO: Error codes. */
16161 /*
16162 * SPEC "For a complex type definition (call it D, for derived)
16163 * to be validly derived from a type definition (call this
16164 * B, for base) given a subset of {extension, restriction}
16165 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016166 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016167 if (! equal) {
16168 /*
16169 * SPEC (1) "If B and D are not the same type definition, then the
16170 * {derivation method} of D must not be in the subset."
16171 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016172 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16173 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016174 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016175 } else {
16176 /*
16177 * SPEC (2.1) "B and D must be the same type definition."
16178 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016179 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016180 }
16181 /*
16182 * SPEC (2.2) "B must be D's {base type definition}."
16183 */
16184 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016185 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016186 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010016187 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16188 * definition`."
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016189 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016190 if (WXS_IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016191 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016193 if (WXS_IS_COMPLEX(type->baseType)) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016194 /*
16195 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16196 * must be validly derived from B given the subset as defined by this
16197 * constraint."
16198 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016199 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016200 baseType, set));
16201 } else {
16202 /*
16203 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16204 * must be validly derived from B given the subset as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016205 * Derivation OK (Simple) ($3.14.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016206 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016207 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016208 baseType, set));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016209 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016210}
16211
16212/**
16213 * xmlSchemaCheckCOSDerivedOK:
16214 * @type: the derived simple type definition
16215 * @baseType: the base type definition
16216 *
16217 * Calls:
16218 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016219 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070016220 * Checks whether @type can be validly derived from @baseType.
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016221 *
16222 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016223 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016224static int
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016225xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016226 xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016227 xmlSchemaTypePtr baseType,
16228 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016229{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016230 if (WXS_IS_SIMPLE(type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016231 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016232 else
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016233 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016234}
16235
William M. Brack2f2a6632004-08-20 23:09:47 +000016236/**
16237 * xmlSchemaCheckCOSCTExtends:
16238 * @ctxt: the schema parser context
16239 * @type: the complex type definition
16240 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016241 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016242 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016243 * Derivation Valid (Extension) (cos-ct-extends)
16244 *
16245 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016246 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 * (1.5)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016248 * (1.4.3.2.2.2) "Particle Valid (Extension)"
William M. Brack2f2a6632004-08-20 23:09:47 +000016249 *
16250 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016251 * error code if not and -1 if an internal error occurred.
William M. Brack2f2a6632004-08-20 23:09:47 +000016252 */
16253static int
16254xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16255 xmlSchemaTypePtr type)
16256{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 xmlSchemaTypePtr base = type->baseType;
16258 /*
16259 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16260 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000016261 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016262 /*
16263 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 * then all of the following must be true:"
16265 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016266 if (WXS_IS_COMPLEX(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016267 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016268 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016269 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000016270 */
16271 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16272 xmlSchemaPCustomErr(ctxt,
16273 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016274 WXS_BASIC_CAST type, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016275 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016276 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000016277 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16278 }
Daniel Veillarddee23482008-04-11 12:58:43 +000016279
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016280 /*
16281 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16282 * since they are automatically satisfied through the
16283 * inheriting mechanism.
16284 * Note that even if redefining components, the inheriting mechanism
16285 * is used.
16286 */
16287#if 0
William M. Brack2f2a6632004-08-20 23:09:47 +000016288 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016289 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016290 * uses}
16291 * of the complex type definition itself, that is, for every attribute
16292 * use in the {attribute uses} of the {base type definition}, there
16293 * must be an attribute use in the {attribute uses} of the complex
16294 * type definition itself whose {attribute declaration} has the same
16295 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016296 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000016297 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016298 if (base->attrUses != NULL) {
16299 int i, j, found;
16300 xmlSchemaAttributeUsePtr use, buse;
William M. Brack2f2a6632004-08-20 23:09:47 +000016301
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016302 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16303 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16304 found = 0;
16305 if (type->attrUses != NULL) {
16306 use = (WXS_LIST_CAST type->attrUses)->items[j];
16307 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16308 {
16309 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16310 WXS_ATTRUSE_DECL_NAME(buse)) &&
16311 (WXS_ATTRUSE_DECL_TNS(use) ==
16312 WXS_ATTRUSE_DECL_TNS(buse)) &&
16313 (WXS_ATTRUSE_TYPEDEF(use) ==
16314 WXS_ATTRUSE_TYPEDEF(buse))
16315 {
16316 found = 1;
16317 break;
16318 }
16319 }
16320 }
16321 if (! found) {
16322 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016323
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016324 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16325 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16326 NULL, WXS_BASIC_CAST type,
Daniel Veillarddee23482008-04-11 12:58:43 +000016327 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016328 * TODO: The report does not indicate that also the
16329 * type needs to be the same.
16330 */
16331 "This type is missing a matching correspondent "
16332 "for its {base type}'s %s in its {attribute uses}",
16333 xmlSchemaGetComponentDesignation(&str,
16334 buse->children),
16335 NULL);
16336 FREE_AND_NULL(str)
16337 }
16338 }
16339 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016340 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16342 * definition must also have one, and the base type definition's
16343 * {attribute wildcard}'s {namespace constraint} must be a subset
16344 * of the complex type definition's {attribute wildcard}'s {namespace
Jan Pokorný761c9e92013-11-29 23:26:27 +010016345 * constraint}, as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016346 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016347
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016348 /*
16349 * MAYBE TODO: Enable if ever needed. But this will be needed only
16350 * if created the type via a schema construction API.
16351 */
16352 if (base->attributeWildcard != NULL) {
Haibo Huangcfd91dc2020-07-30 23:01:33 -070016353 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016354 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016355
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016356 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16357 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16358 NULL, type,
16359 "The base %s has an attribute wildcard, "
16360 "but this type is missing an attribute wildcard",
16361 xmlSchemaGetComponentDesignation(&str, base));
16362 FREE_AND_NULL(str)
16363
16364 } else if (xmlSchemaCheckCOSNSSubset(
16365 base->attributeWildcard, type->attributeWildcard))
16366 {
16367 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000016368
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016369 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16370 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16371 NULL, type,
16372 "The attribute wildcard is not a valid "
16373 "superset of the one in the base %s",
16374 xmlSchemaGetComponentDesignation(&str, base));
16375 FREE_AND_NULL(str)
16376 }
16377 }
16378#endif
16379 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016381 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 if ((type->contentTypeDef != NULL) &&
16383 (type->contentTypeDef == base->contentTypeDef)) {
16384 /*
16385 * SPEC (1.4.1) "The {content type} of the {base type definition}
16386 * and the {content type} of the complex type definition itself
16387 * must be the same simple type definition"
16388 * PASS
16389 */
16390 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16391 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16392 /*
16393 * SPEC (1.4.2) "The {content type} of both the {base type
16394 * definition} and the complex type definition itself must
16395 * be empty."
16396 * PASS
16397 */
16398 } else {
16399 /*
16400 * SPEC (1.4.3) "All of the following must be true:"
16401 */
16402 if (type->subtypes == NULL) {
16403 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016405 * definition itself must specify a particle.
16406 */
16407 xmlSchemaPCustomErr(ctxt,
16408 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016409 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016410 "The content type must specify a particle", NULL);
16411 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16412 }
16413 /*
16414 * SPEC (1.4.3.2) "One of the following must be true:"
16415 */
16416 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16417 /*
16418 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16419 * definition} must be empty.
16420 * PASS
16421 */
16422 } else {
16423 /*
16424 * SPEC (1.4.3.2.2) "All of the following must be true:"
16425 */
16426 if ((type->contentType != base->contentType) ||
16427 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16428 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16429 /*
16430 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16431 * or both must be element-only."
16432 */
16433 xmlSchemaPCustomErr(ctxt,
16434 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016435 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016436 "The content type of both, the type and its base "
16437 "type, must either 'mixed' or 'element-only'", NULL);
16438 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016440 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016441 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016442 * complex type definition must be a `valid extension`
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016443 * of the {base type definition}'s particle, as defined
Jan Pokorný761c9e92013-11-29 23:26:27 +010016444 * in Particle Valid (Extension) ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016445 *
16446 * NOTE that we won't check "Particle Valid (Extension)",
16447 * since it is ensured by the derivation process in
16448 * xmlSchemaTypeFixup(). We need to implement this when heading
16449 * for a construction API
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016450 * TODO: !! This is needed to be checked if redefining a type !!
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016451 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016452 }
16453 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016454 * URGENT TODO (1.5)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016455 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016456 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016457 } else {
16458 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016459 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016460 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000016461 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016462 if (type->contentTypeDef != base) {
16463 /*
16464 * SPEC (2.1) "The {content type} must be the same simple type
16465 * definition."
16466 */
16467 xmlSchemaPCustomErr(ctxt,
16468 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016469 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016470 "The content type must be the simple base type", NULL);
16471 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16472 }
16473 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16474 /*
16475 * SPEC (2.2) "The {final} of the {base type definition} must not
16476 * contain extension"
16477 * NOTE that this is the same as (1.1).
16478 */
16479 xmlSchemaPCustomErr(ctxt,
16480 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016481 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016482 "The 'final' of the base type definition "
16483 "contains 'extension'", NULL);
16484 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016485 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016486 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016487 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016488}
16489
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016490/**
16491 * xmlSchemaCheckDerivationOKRestriction:
16492 * @ctxt: the schema parser context
16493 * @type: the complex type definition
16494 *
16495 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016496 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016497 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16498 *
16499 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016500 * missing:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016501 * (5.4.2) ???
16502 *
16503 * ATTENTION:
16504 * In XML Schema 1.1 this will be:
16505 * Validation Rule: Checking complex type subsumption
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016506 *
16507 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016508 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016509 */
16510static int
16511xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16512 xmlSchemaTypePtr type)
16513{
16514 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016515
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016516 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016517 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016518 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016519 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016520 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016521 if (! WXS_IS_COMPLEX(base)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000016522 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016523 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16524 type->node, WXS_BASIC_CAST type,
16525 "The base type must be a complex type", NULL, NULL);
16526 return(ctxt->err);
16527 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016528 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16529 /*
16530 * SPEC (1) "The {base type definition} must be a complex type
16531 * definition whose {final} does not contain restriction."
16532 */
Daniel Veillarddee23482008-04-11 12:58:43 +000016533 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016534 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16535 type->node, WXS_BASIC_CAST type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016536 "The 'final' of the base type definition "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016537 "contains 'restriction'", NULL, NULL);
16538 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016539 }
16540 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016541 * SPEC (2), (3) and (4)
16542 * Those are handled in a separate function, since the
16543 * same constraints are needed for redefinition of
16544 * attribute groups as well.
16545 */
16546 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16547 XML_SCHEMA_ACTION_DERIVE,
16548 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16549 type->attrUses, base->attrUses,
16550 type->attributeWildcard,
16551 base->attributeWildcard) == -1)
16552 {
16553 return(-1);
16554 }
16555 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016556 * SPEC (5) "One of the following must be true:"
16557 */
16558 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16559 /*
16560 * SPEC (5.1) "The {base type definition} must be the
Jan Pokorný761c9e92013-11-29 23:26:27 +010016561 * `ur-type definition`."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016562 * PASS
16563 */
16564 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16565 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16566 /*
16567 * SPEC (5.2.1) "The {content type} of the complex type definition
16568 * must be a simple type definition"
16569 *
16570 * SPEC (5.2.2) "One of the following must be true:"
16571 */
16572 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016573 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16574 {
16575 int err;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016576 /*
16577 * SPEC (5.2.2.1) "The {content type} of the {base type
16578 * definition} must be a simple type definition from which
16579 * the {content type} is validly derived given the empty
Jan Pokorný761c9e92013-11-29 23:26:27 +010016580 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016581 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070016582 * ATTENTION TODO: This seems not needed if the type implicitly
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016583 * derived from the base type.
Daniel Veillarddee23482008-04-11 12:58:43 +000016584 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016585 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000016586 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16587 type->contentTypeDef, base->contentTypeDef, 0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016588 if (err != 0) {
16589 xmlChar *strA = NULL, *strB = NULL;
16590
16591 if (err == -1)
16592 return(-1);
16593 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16594 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16595 NULL, WXS_BASIC_CAST type,
16596 "The {content type} %s is not validly derived from the "
16597 "base type's {content type} %s",
16598 xmlSchemaGetComponentDesignation(&strA,
16599 type->contentTypeDef),
16600 xmlSchemaGetComponentDesignation(&strB,
16601 base->contentTypeDef));
16602 FREE_AND_NULL(strA);
16603 FREE_AND_NULL(strB);
16604 return(ctxt->err);
16605 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016606 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16607 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016608 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016609 /*
16610 * SPEC (5.2.2.2) "The {base type definition} must be mixed
Jan Pokorný761c9e92013-11-29 23:26:27 +010016611 * and have a particle which is `emptiable` as defined in
16612 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016613 * PASS
16614 */
16615 } else {
16616 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016617 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16618 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016619 "The content type of the base type must be either "
16620 "a simple type or 'mixed' and an emptiable particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016621 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016622 }
16623 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16624 /*
16625 * SPEC (5.3.1) "The {content type} of the complex type itself must
16626 * be empty"
16627 */
16628 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16629 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016630 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016631 * definition} must also be empty."
16632 * PASS
16633 */
16634 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16635 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16636 xmlSchemaIsParticleEmptiable(
16637 (xmlSchemaParticlePtr) base->subtypes)) {
16638 /*
16639 * SPEC (5.3.2.2) "The {content type} of the {base type
16640 * definition} must be elementOnly or mixed and have a particle
Jan Pokorný761c9e92013-11-29 23:26:27 +010016641 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016642 * PASS
16643 */
16644 } else {
16645 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016646 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16647 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016648 "The content type of the base type must be either "
16649 "empty or 'mixed' (or 'elements-only') and an emptiable "
16650 "particle", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016651 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016652 }
16653 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016654 WXS_HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016655 /*
16656 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16657 * itself must be element-only"
Daniel Veillarddee23482008-04-11 12:58:43 +000016658 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016659 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016660 /*
16661 * SPEC (5.4.1.2) "The {content type} of the complex type
16662 * definition itself and of the {base type definition} must be
16663 * mixed"
16664 */
16665 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016666 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16667 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016668 "If the content type is 'mixed', then the content type of the "
16669 "base type must also be 'mixed'", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016670 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016671 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016672 /*
16673 * SPEC (5.4.2) "The particle of the complex type definition itself
Jan Pokorný761c9e92013-11-29 23:26:27 +010016674 * must be a `valid restriction` of the particle of the {content
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016675 * type} of the {base type definition} as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010016676 * (Restriction) ($3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016677 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016678 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016679 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016680 } else {
16681 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016682 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16683 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016684 "The type is not a valid restriction of its base type", NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016685 return (ctxt->err);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016686 }
16687 return (0);
16688}
16689
16690/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000016691 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016692 * @ctxt: the schema parser context
16693 * @type: the complex type definition
16694 *
16695 * (3.4.6) Constraints on Complex Type Definition Schema Components
16696 *
16697 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016698 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016699 */
16700static int
16701xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16702 xmlSchemaTypePtr type)
16703{
16704 int ret;
16705 /*
16706 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016707 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016708 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16709 if (ret != 0)
16710 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016711 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016712 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16713 else
16714 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16715 return (ret);
16716}
16717
16718/**
16719 * xmlSchemaCheckSRCCT:
16720 * @ctxt: the schema parser context
16721 * @type: the complex type definition
16722 *
16723 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016724 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 * Complex Type Definition Representation OK (src-ct)
16726 *
16727 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016728 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016729 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016730static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016731xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016732 xmlSchemaTypePtr type)
16733{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016734 xmlSchemaTypePtr base;
16735 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016736
16737 /*
16738 * TODO: Adjust the error codes here, as I used
16739 * XML_SCHEMAP_SRC_CT_1 only yet.
16740 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016741 base = type->baseType;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016742 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016743 /*
16744 * 1 If the <complexContent> alternative is chosen, the type definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010016745 * `resolved` to by the `actual value` of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016746 * must be a complex type definition;
16747 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016748 if (! WXS_IS_COMPLEX(base)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016749 xmlChar *str = NULL;
16750 xmlSchemaPCustomErr(ctxt,
16751 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016752 WXS_BASIC_CAST type, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016753 "If using <complexContent>, the base type is expected to be "
16754 "a complex type. The base type '%s' is a simple type",
16755 xmlSchemaFormatQName(&str, base->targetNamespace,
16756 base->name));
16757 FREE_AND_NULL(str)
16758 return (XML_SCHEMAP_SRC_CT_1);
16759 }
16760 } else {
16761 /*
16762 * SPEC
16763 * 2 If the <simpleContent> alternative is chosen, all of the
16764 * following must be true:
Jan Pokorný761c9e92013-11-29 23:26:27 +010016765 * 2.1 The type definition `resolved` to by the `actual value` of the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016766 * base [attribute] must be one of the following:
16767 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016768 if (WXS_IS_SIMPLE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016769 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016770 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016771 /*
16772 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016773 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016774 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016775 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016776 xmlSchemaPCustomErr(ctxt,
16777 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016778 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016779 "If using <simpleContent> and <restriction>, the base "
16780 "type must be a complex type. The base type '%s' is "
16781 "a simple type",
16782 xmlSchemaFormatQName(&str, base->targetNamespace,
16783 base->name));
16784 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016785 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016786 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016787 } else {
16788 /* Base type is a complex type. */
16789 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16790 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16791 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016792 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016793 * simple type definition;
16794 * PASS
16795 */
16796 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016797 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016798 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016799 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016800 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016801 type->name);
16802 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016803 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016804 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016805 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016806
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016807 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016808 * 2.1.2 only if the <restriction> alternative is also
16809 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016810 * is mixed and a particle emptiable.
16811 */
16812 if (! xmlSchemaIsParticleEmptiable(
16813 (xmlSchemaParticlePtr) base->subtypes)) {
16814 ret = XML_SCHEMAP_SRC_CT_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000016815 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016816 /*
16817 * Attention: at this point the <simpleType> child is in
16818 * ->contentTypeDef (put there during parsing).
Daniel Veillarddee23482008-04-11 12:58:43 +000016819 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016820 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016821 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016823 * 2.2 If clause 2.1.2 above is satisfied, then there
16824 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016825 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016826 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016827 /* TODO: Change error code to ..._SRC_CT_2_2. */
16828 xmlSchemaPCustomErr(ctxt,
16829 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016830 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016831 "A <simpleType> is expected among the children "
16832 "of <restriction>, if <simpleContent> is used and "
16833 "the base type '%s' is a complex type",
16834 xmlSchemaFormatQName(&str, base->targetNamespace,
16835 base->name));
16836 FREE_AND_NULL(str)
16837 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016838 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016839 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016840 ret = XML_SCHEMAP_SRC_CT_1;
16841 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016842 }
16843 if (ret > 0) {
16844 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016845 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016846 xmlSchemaPCustomErr(ctxt,
16847 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016848 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016849 "If <simpleContent> and <restriction> is used, the "
16850 "base type must be a simple type or a complex type with "
16851 "mixed content and particle emptiable. The base type "
16852 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016853 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016854 base->name));
16855 } else {
16856 xmlSchemaPCustomErr(ctxt,
16857 XML_SCHEMAP_SRC_CT_1,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016858 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016859 "If <simpleContent> and <extension> is used, the "
16860 "base type must be a simple type. The base type '%s' "
16861 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016862 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016863 base->name));
16864 }
16865 FREE_AND_NULL(str)
16866 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016867 }
16868 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016869 * SPEC (3) "The corresponding complex type definition component must
16870 * satisfy the conditions set out in Constraints on Complex Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010016871 * Definition Schema Components ($3.4.6);"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016872 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016873 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016874 /*
16875 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016876 * above for {attribute wildcard} is satisfied, the intensional
16877 * intersection must be expressible, as defined in Attribute Wildcard
Jan Pokorný761c9e92013-11-29 23:26:27 +010016878 * Intersection ($3.10.6).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000016879 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016880 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016881 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016882}
William M. Brack2f2a6632004-08-20 23:09:47 +000016883
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016884#ifdef ENABLE_PARTICLE_RESTRICTION
16885/**
16886 * xmlSchemaCheckParticleRangeOK:
16887 * @ctxt: the schema parser context
16888 * @type: the complex type definition
16889 *
16890 * (3.9.6) Constraints on Particle Schema Components
16891 * Schema Component Constraint:
16892 * Occurrence Range OK (range-ok)
16893 *
16894 * STATUS: complete
16895 *
16896 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016897 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016898 */
16899static int
16900xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16901 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016902{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016903 if (rmin < bmin)
16904 return (1);
16905 if ((bmax != UNBOUNDED) &&
16906 (rmax > bmax))
16907 return (1);
16908 return (0);
16909}
16910
16911/**
16912 * xmlSchemaCheckRCaseNameAndTypeOK:
16913 * @ctxt: the schema parser context
16914 * @r: the restricting element declaration particle
16915 * @b: the base element declaration particle
16916 *
16917 * (3.9.6) Constraints on Particle Schema Components
16918 * Schema Component Constraint:
16919 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16920 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016921 *
16922 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016923 * MISSING (3.2.3)
16924 * CLARIFY: (3.2.2)
16925 *
16926 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020016927 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016928 */
16929static int
16930xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16931 xmlSchemaParticlePtr r,
16932 xmlSchemaParticlePtr b)
16933{
16934 xmlSchemaElementPtr elemR, elemB;
16935
16936 /* TODO: Error codes (rcase-NameAndTypeOK). */
16937 elemR = (xmlSchemaElementPtr) r->children;
16938 elemB = (xmlSchemaElementPtr) b->children;
16939 /*
16940 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16941 * the same."
16942 */
16943 if ((elemR != elemB) &&
16944 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16945 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16946 return (1);
16947 /*
16948 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010016949 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016950 */
16951 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16952 b->minOccurs, b->maxOccurs) != 0)
16953 return (1);
16954 /*
16955 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16956 * {scope} are global."
16957 */
16958 if (elemR == elemB)
16959 return (0);
16960 /*
16961 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16962 */
16963 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16964 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16965 return (1);
16966 /*
16967 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16968 * or is not fixed, or R's declaration's {value constraint} is fixed
16969 * with the same value."
16970 */
16971 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16972 ((elemR->value == NULL) ||
16973 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16974 /* TODO: Equality of the initial value or normalized or canonical? */
16975 (! xmlStrEqual(elemR->value, elemB->value))))
16976 return (1);
16977 /*
16978 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16979 * definitions} is a subset of B's declaration's {identity-constraint
16980 * definitions}, if any."
16981 */
16982 if (elemB->idcs != NULL) {
16983 /* TODO */
16984 }
16985 /*
16986 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16987 * superset of B's declaration's {disallowed substitutions}."
16988 */
16989 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16990 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16991 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16992 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16993 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16994 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16995 return (1);
16996 /*
16997 * SPEC (3.2.5) "R's {type definition} is validly derived given
16998 * {extension, list, union} from B's {type definition}"
16999 *
17000 * BADSPEC TODO: What's the point of adding "list" and "union" to the
17001 * set, if the corresponding constraints handle "restriction" and
17002 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017003 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017004 */
17005 {
17006 int set = 0;
17007
17008 set |= SUBSET_EXTENSION;
17009 set |= SUBSET_LIST;
17010 set |= SUBSET_UNION;
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017011 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017012 elemB->subtypes, set) != 0)
17013 return (1);
17014 }
17015 return (0);
17016}
17017
17018/**
17019 * xmlSchemaCheckRCaseNSCompat:
17020 * @ctxt: the schema parser context
17021 * @r: the restricting element declaration particle
17022 * @b: the base wildcard particle
17023 *
17024 * (3.9.6) Constraints on Particle Schema Components
17025 * Schema Component Constraint:
17026 * Particle Derivation OK (Elt:Any -- NSCompat)
17027 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017028 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017029 * STATUS: complete
17030 *
17031 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017032 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017033 */
17034static int
17035xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17036 xmlSchemaParticlePtr r,
17037 xmlSchemaParticlePtr b)
17038{
17039 /* TODO:Error codes (rcase-NSCompat). */
17040 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017041 * SPEC "For an element declaration particle to be a `valid restriction`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017042 * of a wildcard particle all of the following must be true:"
17043 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010017044 * SPEC (1) "The element declaration's {target namespace} is `valid`
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017045 * with respect to the wildcard's {namespace constraint} as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010017046 * Wildcard allows Namespace Name ($3.10.4)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017048 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017049 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17050 return (1);
17051 /*
17052 * SPEC (2) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017053 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017054 */
17055 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17056 b->minOccurs, b->maxOccurs) != 0)
17057 return (1);
17058
17059 return (0);
17060}
17061
17062/**
17063 * xmlSchemaCheckRCaseRecurseAsIfGroup:
17064 * @ctxt: the schema parser context
17065 * @r: the restricting element declaration particle
17066 * @b: the base model group particle
17067 *
17068 * (3.9.6) Constraints on Particle Schema Components
17069 * Schema Component Constraint:
17070 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17071 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017072 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017073 * STATUS: TODO
17074 *
17075 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017076 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017077 */
17078static int
17079xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17080 xmlSchemaParticlePtr r,
17081 xmlSchemaParticlePtr b)
17082{
17083 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17084 TODO
17085 return (0);
17086}
17087
17088/**
17089 * xmlSchemaCheckRCaseNSSubset:
17090 * @ctxt: the schema parser context
17091 * @r: the restricting wildcard particle
17092 * @b: the base wildcard particle
17093 *
17094 * (3.9.6) Constraints on Particle Schema Components
17095 * Schema Component Constraint:
17096 * Particle Derivation OK (Any:Any -- NSSubset)
17097 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017098 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017099 * STATUS: complete
17100 *
17101 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017102 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017103 */
17104static int
17105xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17106 xmlSchemaParticlePtr r,
17107 xmlSchemaParticlePtr b,
17108 int isAnyTypeBase)
17109{
17110 /* TODO: Error codes (rcase-NSSubset). */
17111 /*
17112 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017113 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017114 */
17115 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17116 b->minOccurs, b->maxOccurs))
17117 return (1);
17118 /*
17119 * SPEC (2) "R's {namespace constraint} must be an intensional subset
Jan Pokorný761c9e92013-11-29 23:26:27 +010017120 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017121 */
17122 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17123 (xmlSchemaWildcardPtr) b->children))
17124 return (1);
17125 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017126 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17127 * definition`, R's {process contents} must be identical to or stronger
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017128 * than B's {process contents}, where strict is stronger than lax is
17129 * stronger than skip."
17130 */
17131 if (! isAnyTypeBase) {
17132 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17133 ((xmlSchemaWildcardPtr) b->children)->processContents)
17134 return (1);
17135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017136
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017137 return (0);
17138}
17139
17140/**
17141 * xmlSchemaCheckCOSParticleRestrict:
17142 * @ctxt: the schema parser context
17143 * @type: the complex type definition
17144 *
17145 * (3.9.6) Constraints on Particle Schema Components
17146 * Schema Component Constraint:
17147 * Particle Valid (Restriction) (cos-particle-restrict)
17148 *
17149 * STATUS: TODO
17150 *
17151 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017152 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017153 */
17154static int
17155xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17156 xmlSchemaParticlePtr r,
17157 xmlSchemaParticlePtr b)
17158{
17159 int ret = 0;
17160
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017161 /*part = WXS_TYPE_PARTICLE(type);
17162 basePart = WXS_TYPE_PARTICLE(base);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017163 */
17164
17165 TODO
17166
17167 /*
17168 * SPEC (1) "They are the same particle."
17169 */
17170 if (r == b)
17171 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017172
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017173
17174 return (0);
17175}
17176
Daniel Veillard15724252008-08-30 15:01:04 +000017177#if 0
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017178/**
17179 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17180 * @ctxt: the schema parser context
17181 * @r: the model group particle
17182 * @b: the base wildcard particle
17183 *
17184 * (3.9.6) Constraints on Particle Schema Components
17185 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017186 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017187 * NSRecurseCheckCardinality)
17188 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017189 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017190 * STATUS: TODO: subst-groups
17191 *
17192 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017193 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017194 */
17195static int
17196xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17197 xmlSchemaParticlePtr r,
17198 xmlSchemaParticlePtr b)
17199{
17200 xmlSchemaParticlePtr part;
17201 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17202 if ((r->children == NULL) || (r->children->children == NULL))
17203 return (-1);
17204 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017205 * SPEC "For a group particle to be a `valid restriction` of a
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017206 * wildcard particle..."
17207 *
Jan Pokorný761c9e92013-11-29 23:26:27 +010017208 * SPEC (1) "Every member of the {particles} of the group is a `valid
17209 * restriction` of the wildcard as defined by
17210 * Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017211 */
17212 part = (xmlSchemaParticlePtr) r->children->children;
17213 do {
17214 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17215 return (1);
17216 part = (xmlSchemaParticlePtr) part->next;
17217 } while (part != NULL);
17218 /*
17219 * SPEC (2) "The effective total range of the group [...] is a
17220 * valid restriction of B's occurrence range as defined by
Jan Pokorný761c9e92013-11-29 23:26:27 +010017221 * Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017222 */
17223 if (xmlSchemaCheckParticleRangeOK(
17224 xmlSchemaGetParticleTotalRangeMin(r),
17225 xmlSchemaGetParticleTotalRangeMax(r),
17226 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017227 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017228 return (0);
17229}
Daniel Veillard15724252008-08-30 15:01:04 +000017230#endif
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017231
17232/**
17233 * xmlSchemaCheckRCaseRecurse:
17234 * @ctxt: the schema parser context
17235 * @r: the <all> or <sequence> model group particle
17236 * @b: the base <all> or <sequence> model group particle
17237 *
17238 * (3.9.6) Constraints on Particle Schema Components
17239 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017240 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017241 Recurse)
17242 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017243 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017244 * STATUS: ?
17245 * TODO: subst-groups
17246 *
17247 * Returns 0 if the constraints are satisfied, a positive
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017248 * error code if not and -1 if an internal error occurred.
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017249 */
17250static int
17251xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17252 xmlSchemaParticlePtr r,
17253 xmlSchemaParticlePtr b)
17254{
17255 /* xmlSchemaParticlePtr part; */
17256 /* TODO: Error codes (rcase-Recurse). */
17257 if ((r->children == NULL) || (b->children == NULL) ||
17258 (r->children->type != b->children->type))
17259 return (-1);
17260 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010017261 * SPEC "For an all or sequence group particle to be a `valid
17262 * restriction` of another group particle with the same {compositor}..."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017263 *
17264 * SPEC (1) "R's occurrence range is a valid restriction of B's
Jan Pokorný761c9e92013-11-29 23:26:27 +010017265 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017266 */
17267 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17268 b->minOccurs, b->maxOccurs))
17269 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017270
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000017271
17272 return (0);
17273}
17274
17275#endif
17276
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017277#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17278 xmlSchemaPCustomErrExt(pctxt, \
17279 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017280 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017281 "It is an error for both '%s' and '%s' to be specified on the "\
17282 "same type definition", \
17283 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17284 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17285
17286#define FACET_RESTR_ERR(fac1, msg) \
17287 xmlSchemaPCustomErr(pctxt, \
17288 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017289 WXS_BASIC_CAST fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017290 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017291
17292#define FACET_RESTR_FIXED_ERR(fac) \
17293 xmlSchemaPCustomErr(pctxt, \
17294 XML_SCHEMAP_INVALID_FACET_VALUE, \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017295 WXS_BASIC_CAST fac, fac->node, \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017296 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017297 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017298
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017299static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017300xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17301 xmlSchemaFacetPtr facet1,
17302 xmlSchemaFacetPtr facet2,
17303 int lessGreater,
17304 int orEqual,
17305 int ofBase)
17306{
17307 xmlChar *msg = NULL;
17308
17309 msg = xmlStrdup(BAD_CAST "'");
17310 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17311 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17312 if (lessGreater == 0)
17313 msg = xmlStrcat(msg, BAD_CAST " equal to");
17314 if (lessGreater == 1)
17315 msg = xmlStrcat(msg, BAD_CAST " greater than");
17316 else
17317 msg = xmlStrcat(msg, BAD_CAST " less than");
17318
17319 if (orEqual)
17320 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17321 msg = xmlStrcat(msg, BAD_CAST " '");
17322 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17323 if (ofBase)
17324 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17325 else
17326 msg = xmlStrcat(msg, BAD_CAST "'");
17327
17328 xmlSchemaPCustomErr(pctxt,
17329 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017330 WXS_BASIC_CAST facet1, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017331 (const char *) msg, NULL);
17332
17333 if (msg != NULL)
17334 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017335}
17336
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017337/*
17338* xmlSchemaDeriveAndValidateFacets:
17339*
17340* Schema Component Constraint: Simple Type Restriction (Facets)
17341* (st-restrict-facets)
17342*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017343static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017344xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17345 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017346{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017347 xmlSchemaTypePtr base = type->baseType;
17348 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017349 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017350 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17351 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17352 fmininc = NULL, fmaxinc = NULL,
17353 fminexc = NULL, fmaxexc = NULL,
17354 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17355 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17356 bfmininc = NULL, bfmaxinc = NULL,
17357 bfminexc = NULL, bfmaxexc = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017358 int res; /* err = 0, fixedErr; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017359
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017360 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017361 * SPEC st-restrict-facets 1:
Daniel Veillarddee23482008-04-11 12:58:43 +000017362 * "The {variety} of R is the same as that of B."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017363 */
17364 /*
17365 * SPEC st-restrict-facets 2:
17366 * "If {variety} is atomic, the {primitive type definition}
17367 * of R is the same as that of B."
17368 *
17369 * NOTE: we leave 1 & 2 out for now, since this will be
17370 * satisfied by the derivation process.
17371 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17372 */
17373 /*
17374 * SPEC st-restrict-facets 3:
17375 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017376 * of B, eliminating duplicates. To eliminate duplicates,
17377 * when a facet of the same kind occurs in both S and the
17378 * {facets} of B, the one in the {facets} of B is not
17379 * included, with the exception of enumeration and pattern
17380 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017381 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017383
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017384 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17385 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017386
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017387 last = type->facetSet;
17388 if (last != NULL)
17389 while (last->next != NULL)
17390 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017391
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017392 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17393 facet = cur->facet;
17394 switch (facet->type) {
17395 case XML_SCHEMA_FACET_LENGTH:
17396 flength = facet; break;
17397 case XML_SCHEMA_FACET_MINLENGTH:
17398 fminlen = facet; break;
17399 case XML_SCHEMA_FACET_MININCLUSIVE:
17400 fmininc = facet; break;
17401 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17402 fminexc = facet; break;
17403 case XML_SCHEMA_FACET_MAXLENGTH:
17404 fmaxlen = facet; break;
17405 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17406 fmaxinc = facet; break;
17407 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17408 fmaxexc = facet; break;
17409 case XML_SCHEMA_FACET_TOTALDIGITS:
17410 ftotdig = facet; break;
17411 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17412 ffracdig = facet; break;
17413 default:
17414 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017415 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017416 }
17417 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17418 facet = cur->facet;
17419 switch (facet->type) {
17420 case XML_SCHEMA_FACET_LENGTH:
17421 bflength = facet; break;
17422 case XML_SCHEMA_FACET_MINLENGTH:
17423 bfminlen = facet; break;
17424 case XML_SCHEMA_FACET_MININCLUSIVE:
17425 bfmininc = facet; break;
17426 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17427 bfminexc = facet; break;
17428 case XML_SCHEMA_FACET_MAXLENGTH:
17429 bfmaxlen = facet; break;
17430 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17431 bfmaxinc = facet; break;
17432 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17433 bfmaxexc = facet; break;
17434 case XML_SCHEMA_FACET_TOTALDIGITS:
17435 bftotdig = facet; break;
17436 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17437 bffracdig = facet; break;
17438 default:
17439 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017440 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017442 /*
17443 * length and minLength or maxLength (2.2) + (3.2)
17444 */
17445 if (flength && (fminlen || fmaxlen)) {
17446 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17447 "either of 'minLength' or 'maxLength' to be specified on "
17448 "the same type definition")
17449 }
17450 /*
17451 * Mutual exclusions in the same derivation step.
17452 */
17453 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017454 /*
17455 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017456 */
17457 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17458 }
17459 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017460 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017461 * SCC "minInclusive and minExclusive"
17462 */
17463 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017464 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017465
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017466 if (flength && bflength) {
17467 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017468 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017469 * The values have to be equal.
17470 */
17471 res = xmlSchemaCompareValues(flength->val, bflength->val);
17472 if (res == -2)
17473 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017474 if (res != 0)
17475 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17476 if ((res != 0) && (bflength->fixed)) {
17477 FACET_RESTR_FIXED_ERR(flength)
17478 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017479
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017480 }
17481 if (fminlen && bfminlen) {
17482 /*
17483 * SCC "minLength valid restriction"
17484 * minLength >= BASE minLength
17485 */
17486 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17487 if (res == -2)
17488 goto internal_error;
17489 if (res == -1)
17490 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17491 if ((res != 0) && (bfminlen->fixed)) {
17492 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017493 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017494 }
17495 if (fmaxlen && bfmaxlen) {
17496 /*
17497 * SCC "maxLength valid restriction"
17498 * maxLength <= BASE minLength
17499 */
17500 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17501 if (res == -2)
17502 goto internal_error;
17503 if (res == 1)
17504 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17505 if ((res != 0) && (bfmaxlen->fixed)) {
17506 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017508 }
17509 /*
17510 * SCC "length and minLength or maxLength"
17511 */
17512 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017513 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017514 if (flength) {
17515 if (! fminlen)
Miroslav Bajtos8f58f892009-08-07 17:22:12 +020017516 fminlen = bfminlen;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017517 if (fminlen) {
17518 /* (1.1) length >= minLength */
17519 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17520 if (res == -2)
17521 goto internal_error;
17522 if (res == -1)
17523 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17524 }
17525 if (! fmaxlen)
17526 fmaxlen = bfmaxlen;
17527 if (fmaxlen) {
17528 /* (2.1) length <= maxLength */
17529 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17530 if (res == -2)
17531 goto internal_error;
17532 if (res == 1)
17533 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17534 }
17535 }
17536 if (fmaxinc) {
17537 /*
17538 * "maxInclusive"
17539 */
17540 if (fmininc) {
17541 /* SCC "maxInclusive >= minInclusive" */
17542 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17543 if (res == -2)
17544 goto internal_error;
17545 if (res == -1) {
17546 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17547 }
17548 }
17549 /*
17550 * SCC "maxInclusive valid restriction"
17551 */
17552 if (bfmaxinc) {
17553 /* maxInclusive <= BASE maxInclusive */
17554 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17555 if (res == -2)
17556 goto internal_error;
17557 if (res == 1)
17558 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17559 if ((res != 0) && (bfmaxinc->fixed)) {
17560 FACET_RESTR_FIXED_ERR(fmaxinc)
17561 }
17562 }
17563 if (bfmaxexc) {
17564 /* maxInclusive < BASE maxExclusive */
17565 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17566 if (res == -2)
17567 goto internal_error;
17568 if (res != -1) {
17569 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17570 }
17571 }
17572 if (bfmininc) {
17573 /* maxInclusive >= BASE minInclusive */
17574 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17575 if (res == -2)
17576 goto internal_error;
17577 if (res == -1) {
17578 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17579 }
17580 }
17581 if (bfminexc) {
17582 /* maxInclusive > BASE minExclusive */
17583 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17584 if (res == -2)
17585 goto internal_error;
17586 if (res != 1) {
17587 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017590 }
17591 if (fmaxexc) {
17592 /*
17593 * "maxExclusive >= minExclusive"
17594 */
17595 if (fminexc) {
17596 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17597 if (res == -2)
17598 goto internal_error;
17599 if (res == -1) {
17600 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17601 }
17602 }
17603 /*
17604 * "maxExclusive valid restriction"
17605 */
17606 if (bfmaxexc) {
17607 /* maxExclusive <= BASE maxExclusive */
17608 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17609 if (res == -2)
17610 goto internal_error;
17611 if (res == 1) {
17612 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17613 }
17614 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017615 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017616 }
17617 }
17618 if (bfmaxinc) {
17619 /* maxExclusive <= BASE maxInclusive */
17620 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17621 if (res == -2)
17622 goto internal_error;
17623 if (res == 1) {
17624 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17625 }
17626 }
17627 if (bfmininc) {
17628 /* maxExclusive > BASE minInclusive */
17629 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17630 if (res == -2)
17631 goto internal_error;
17632 if (res != 1) {
17633 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17634 }
17635 }
17636 if (bfminexc) {
17637 /* maxExclusive > BASE minExclusive */
17638 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17639 if (res == -2)
17640 goto internal_error;
17641 if (res != 1) {
17642 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17643 }
17644 }
17645 }
17646 if (fminexc) {
17647 /*
17648 * "minExclusive < maxInclusive"
17649 */
17650 if (fmaxinc) {
17651 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17652 if (res == -2)
17653 goto internal_error;
17654 if (res != -1) {
17655 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17656 }
17657 }
17658 /*
17659 * "minExclusive valid restriction"
17660 */
17661 if (bfminexc) {
17662 /* minExclusive >= BASE minExclusive */
17663 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17664 if (res == -2)
17665 goto internal_error;
17666 if (res == -1) {
17667 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17668 }
17669 if ((res != 0) && (bfminexc->fixed)) {
17670 FACET_RESTR_FIXED_ERR(fminexc)
17671 }
17672 }
17673 if (bfmaxinc) {
17674 /* minExclusive <= BASE maxInclusive */
17675 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17676 if (res == -2)
17677 goto internal_error;
17678 if (res == 1) {
17679 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17680 }
17681 }
17682 if (bfmininc) {
17683 /* minExclusive >= BASE minInclusive */
17684 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17685 if (res == -2)
17686 goto internal_error;
17687 if (res == -1) {
17688 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17689 }
17690 }
17691 if (bfmaxexc) {
17692 /* minExclusive < BASE maxExclusive */
17693 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17694 if (res == -2)
17695 goto internal_error;
17696 if (res != -1) {
17697 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17698 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017699 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017700 }
17701 if (fmininc) {
17702 /*
17703 * "minInclusive < maxExclusive"
17704 */
17705 if (fmaxexc) {
17706 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17707 if (res == -2)
17708 goto internal_error;
17709 if (res != -1) {
17710 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17711 }
17712 }
17713 /*
17714 * "minExclusive valid restriction"
17715 */
17716 if (bfmininc) {
17717 /* minInclusive >= BASE minInclusive */
17718 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17719 if (res == -2)
17720 goto internal_error;
17721 if (res == -1) {
17722 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17723 }
17724 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017725 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017726 }
17727 }
17728 if (bfmaxinc) {
17729 /* minInclusive <= BASE maxInclusive */
17730 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17731 if (res == -2)
17732 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000017733 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017734 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17735 }
17736 }
17737 if (bfminexc) {
17738 /* minInclusive > BASE minExclusive */
17739 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17740 if (res == -2)
17741 goto internal_error;
17742 if (res != 1)
17743 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17744 }
17745 if (bfmaxexc) {
17746 /* minInclusive < BASE maxExclusive */
17747 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17748 if (res == -2)
17749 goto internal_error;
17750 if (res != -1)
17751 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17752 }
17753 }
17754 if (ftotdig && bftotdig) {
17755 /*
17756 * SCC " totalDigits valid restriction"
17757 * totalDigits <= BASE totalDigits
17758 */
17759 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17760 if (res == -2)
17761 goto internal_error;
17762 if (res == 1)
17763 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17764 -1, 1, 1);
17765 if ((res != 0) && (bftotdig->fixed)) {
17766 FACET_RESTR_FIXED_ERR(ftotdig)
17767 }
17768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017770 /*
17771 * SCC "fractionDigits valid restriction"
17772 * fractionDigits <= BASE fractionDigits
17773 */
17774 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17775 if (res == -2)
17776 goto internal_error;
17777 if (res == 1)
17778 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17779 -1, 1, 1);
17780 if ((res != 0) && (bffracdig->fixed)) {
17781 FACET_RESTR_FIXED_ERR(ffracdig)
17782 }
17783 }
17784 /*
17785 * SCC "fractionDigits less than or equal to totalDigits"
17786 */
17787 if (! ftotdig)
17788 ftotdig = bftotdig;
17789 if (! ffracdig)
17790 ffracdig = bffracdig;
17791 if (ftotdig && ffracdig) {
17792 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17793 if (res == -2)
17794 goto internal_error;
17795 if (res == 1)
17796 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17797 -1, 1, 0);
17798 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017799 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017800 * *Enumerations* won' be added here, since only the first set
17801 * of enumerations in the ancestor-or-self axis is used
17802 * for validation, plus we need to use the base type of those
17803 * enumerations for whitespace.
17804 *
17805 * *Patterns*: won't be add here, since they are ORed at
17806 * type level and ANDed at ancestor level. This will
Haibo Huangcfd91dc2020-07-30 23:01:33 -070017807 * happen during validation by walking the base axis
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017808 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017809 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017810 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17811 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017812 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017813 * Special handling of enumerations and patterns.
17814 * TODO: hmm, they should not appear in the set, so remove this.
17815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017816 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017817 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017818 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017819 /*
17820 * Search for a duplicate facet in the current type.
17821 */
17822 link = type->facetSet;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000017823 /* err = 0; */
17824 /* fixedErr = 0; */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017825 while (link != NULL) {
17826 facet = link->facet;
17827 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017828 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017829 case XML_SCHEMA_FACET_WHITESPACE:
17830 /*
17831 * The whitespace must be stronger.
17832 */
17833 if (facet->whitespace < bfacet->whitespace) {
Rob Richardsc6947bb2008-06-29 15:04:41 +000017834 FACET_RESTR_ERR(facet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017835 "The 'whitespace' value has to be equal to "
17836 "or stronger than the 'whitespace' value of "
17837 "the base type")
17838 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017839 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017840 (facet->whitespace != bfacet->whitespace)) {
17841 FACET_RESTR_FIXED_ERR(facet)
17842 }
17843 break;
17844 default:
17845 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017846 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017847 /* Duplicate found. */
17848 break;
17849 }
17850 link = link->next;
17851 }
17852 /*
17853 * If no duplicate was found: add the base types's facet
17854 * to the set.
17855 */
17856 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017857 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017858 xmlMalloc(sizeof(xmlSchemaFacetLink));
17859 if (link == NULL) {
17860 xmlSchemaPErrMemory(pctxt,
17861 "deriving facets, creating a facet link", NULL);
17862 return (-1);
17863 }
17864 link->facet = cur->facet;
17865 link->next = NULL;
17866 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017867 type->facetSet = link;
17868 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017869 last->next = link;
17870 last = link;
17871 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017872
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017873 }
17874
17875 return (0);
17876internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017877 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020017878 "an error occurred");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017879 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017880}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017881
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017882static int
17883xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17884 xmlSchemaTypePtr type)
17885{
17886 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17887 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017888 * The actual value is then formed by replacing any union type
Jan Pokorný761c9e92013-11-29 23:26:27 +010017889 * definition in the `explicit members` with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017890 * {member type definitions}, in order.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017891 *
17892 * TODO: There's a bug entry at
17893 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17894 * which indicates that we'll keep the union types the future.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017895 */
17896 link = type->memberTypes;
17897 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017898
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017899 if (WXS_IS_TYPE_NOT_FIXED(link->type))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000017900 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017901
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017902 if (WXS_IS_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017903 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017904 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017905 link->type = subLink->type;
17906 if (subLink->next != NULL) {
17907 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017909 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017910 while (subLink != NULL) {
17911 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017912 xmlMalloc(sizeof(xmlSchemaTypeLink));
17913 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017914 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017915 NULL);
17916 return (-1);
17917 }
17918 newLink->type = subLink->type;
17919 prevLink->next = newLink;
17920 prevLink = newLink;
17921 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017922
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017923 subLink = subLink->next;
17924 }
17925 }
17926 }
17927 }
17928 link = link->next;
17929 }
17930 return (0);
17931}
17932
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017933static void
17934xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
Daniel Veillarddee23482008-04-11 12:58:43 +000017935{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017936 int has = 0, needVal = 0, normVal = 0;
17937
17938 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17939 if (has) {
17940 needVal = (type->baseType->flags &
17941 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17942 normVal = (type->baseType->flags &
17943 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17944 }
17945 if (type->facets != NULL) {
17946 xmlSchemaFacetPtr fac;
Daniel Veillarddee23482008-04-11 12:58:43 +000017947
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017948 for (fac = type->facets; fac != NULL; fac = fac->next) {
17949 switch (fac->type) {
17950 case XML_SCHEMA_FACET_WHITESPACE:
17951 break;
17952 case XML_SCHEMA_FACET_PATTERN:
17953 normVal = 1;
17954 has = 1;
17955 break;
17956 case XML_SCHEMA_FACET_ENUMERATION:
17957 needVal = 1;
17958 normVal = 1;
17959 has = 1;
17960 break;
17961 default:
17962 has = 1;
17963 break;
17964 }
Daniel Veillarddee23482008-04-11 12:58:43 +000017965 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017966 }
17967 if (normVal)
17968 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17969 if (needVal)
17970 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17971 if (has)
17972 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17973
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017974 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017975 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17976 /*
17977 * OPTIMIZE VAL TODO: Some facets need a computed value.
17978 */
17979 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17980 (prim->builtInType != XML_SCHEMAS_STRING)) {
17981 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
Daniel Veillarddee23482008-04-11 12:58:43 +000017982 }
17983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017984}
17985
17986static int
17987xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17988{
Daniel Veillarddee23482008-04-11 12:58:43 +000017989
17990
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017991 /*
17992 * Evaluate the whitespace-facet value.
Daniel Veillarddee23482008-04-11 12:58:43 +000017993 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017994 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017995 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17996 return (0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000017997 } else if (WXS_IS_UNION(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017998 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000017999
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018000 if (type->facetSet != NULL) {
18001 xmlSchemaFacetLinkPtr lin;
18002
18003 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18004 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18005 switch (lin->facet->whitespace) {
18006 case XML_SCHEMAS_FACET_PRESERVE:
18007 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18008 break;
18009 case XML_SCHEMAS_FACET_REPLACE:
18010 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18011 break;
18012 case XML_SCHEMAS_FACET_COLLAPSE:
18013 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18014 break;
18015 default:
18016 return (-1);
18017 }
18018 return (0);
18019 }
18020 }
18021 }
18022 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018023 * For all `atomic` datatypes other than string (and types `derived`
18024 * by `restriction` from it) the value of whiteSpace is fixed to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018025 * collapse
18026 */
18027 {
18028 xmlSchemaTypePtr anc;
18029
Daniel Veillarddee23482008-04-11 12:58:43 +000018030 for (anc = type->baseType; anc != NULL &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018031 anc->builtInType != XML_SCHEMAS_ANYTYPE;
18032 anc = anc->baseType) {
18033
18034 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillarddee23482008-04-11 12:58:43 +000018035 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018036 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18037
18038 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
Daniel Veillarddee23482008-04-11 12:58:43 +000018039 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018040 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18041
18042 } else
18043 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18044 break;
18045 }
18046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018047 }
18048 return (0);
18049}
18050
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018051static int
18052xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18053 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000018054{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018055 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18056 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018057 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018058 return(0);
18059 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018060
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018061 if (WXS_IS_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018062 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018063 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018064 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018065 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018066 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018067 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018068 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018069 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018070 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018071 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018072 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018073 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018074 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018075 * Corresponds to <simpleType><union>...
Daniel Veillarddee23482008-04-11 12:58:43 +000018076 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018077 if (type->memberTypes == NULL) {
18078 /*
18079 * This one is really needed, so get out.
18080 */
18081 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18082 "union type has no member-types assigned");
18083 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000018084 }
18085 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018086 /*
18087 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018088 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018089 if (type->baseType == NULL) {
18090 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18091 "type has no base-type assigned");
18092 return(-1);
18093 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018094 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018095 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18096 return(-1);
18097 /*
18098 * Variety
18099 * If the <restriction> alternative is chosen, then the
18100 * {variety} of the {base type definition}.
18101 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018102 if (WXS_IS_ATOMIC(type->baseType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018103 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018104 else if (WXS_IS_LIST(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018105 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018106 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018107 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018108 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018109 type->subtypes = type->baseType->subtypes;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018110 } else if (WXS_IS_UNION(type->baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018111 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018112 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018113 * NOTE that we won't assign the memberTypes of the base,
18114 * since this will make trouble when freeing them; we will
18115 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018116 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018117 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018118 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018119 return(0);
18120}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018121
Daniel Veillard8651f532002-04-17 09:06:27 +000018122#ifdef DEBUG_TYPE
Daniel Veillard67952602006-01-05 15:29:44 +000018123static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018124xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18125 xmlSchemaTypePtr type)
18126{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018127 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018128 xmlGenericError(xmlGenericErrorContext,
18129 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018130 type->node->doc->URL,
18131 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018132 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018133 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000018134 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018135 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018136 switch (type->contentType) {
18137 case XML_SCHEMA_CONTENT_SIMPLE:
18138 xmlGenericError(xmlGenericErrorContext, "simple\n");
18139 break;
18140 case XML_SCHEMA_CONTENT_ELEMENTS:
18141 xmlGenericError(xmlGenericErrorContext, "elements\n");
18142 break;
18143 case XML_SCHEMA_CONTENT_UNKNOWN:
18144 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18145 break;
18146 case XML_SCHEMA_CONTENT_EMPTY:
18147 xmlGenericError(xmlGenericErrorContext, "empty\n");
18148 break;
18149 case XML_SCHEMA_CONTENT_MIXED:
18150 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018151 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018152 xmlGenericError(xmlGenericErrorContext,
18153 "mixed as emptiable particle\n");
18154 else
18155 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18156 break;
18157 /* Removed, since not used. */
18158 /*
18159 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18160 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18161 break;
18162 */
18163 case XML_SCHEMA_CONTENT_BASIC:
18164 xmlGenericError(xmlGenericErrorContext, "basic\n");
18165 break;
18166 default:
18167 xmlGenericError(xmlGenericErrorContext,
18168 "not registered !!!\n");
18169 break;
18170 }
Daniel Veillard8651f532002-04-17 09:06:27 +000018171 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018172}
Daniel Veillard8651f532002-04-17 09:06:27 +000018173#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018174
18175/*
18176* 3.14.6 Constraints on Simple Type Definition Schema Components
18177*/
18178static int
18179xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18180 xmlSchemaTypePtr type)
18181{
18182 int res, olderrs = pctxt->nberrors;
18183
18184 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18185 return(-1);
18186
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018187 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018188 return(0);
18189
18190 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18191 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18192
18193 if (type->baseType == NULL) {
18194 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18195 "missing baseType");
18196 goto exit_failure;
18197 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018198 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018199 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000018200 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018201 * If a member type of a union is a union itself, we need to substitute
18202 * that member type for its member types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018203 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18204 * types in WXS 1.1.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018205 */
18206 if ((type->memberTypes != NULL) &&
18207 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
Daniel Veillarddee23482008-04-11 12:58:43 +000018208 return(-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018209 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000018210 * SPEC src-simple-type 1
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018211 * "The corresponding simple type definition, if any, must satisfy
18212 * the conditions set out in Constraints on Simple Type Definition
Jan Pokorný761c9e92013-11-29 23:26:27 +010018213 * Schema Components ($3.14.6)."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018214 */
18215 /*
18216 * Schema Component Constraint: Simple Type Definition Properties Correct
18217 * (st-props-correct)
18218 */
18219 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18220 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018221 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018222 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18223 * (cos-st-restricts)
18224 */
18225 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18226 HFAILURE HERROR
18227 /*
18228 * TODO: Removed the error report, since it got annoying to get an
18229 * extra error report, if anything failed until now.
18230 * Enable this if needed.
18231 *
18232 * xmlSchemaPErr(ctxt, type->node,
18233 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18234 * "Simple type '%s' does not satisfy the constraints "
18235 * "on simple type definitions.\n",
18236 * type->name, NULL);
18237 */
18238 /*
18239 * Schema Component Constraint: Simple Type Restriction (Facets)
18240 * (st-restrict-facets)
18241 */
18242 res = xmlSchemaCheckFacetValues(type, pctxt);
18243 HFAILURE HERROR
18244 if ((type->facetSet != NULL) ||
18245 (type->baseType->facetSet != NULL)) {
18246 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18247 HFAILURE HERROR
18248 }
18249 /*
18250 * Whitespace value.
18251 */
18252 res = xmlSchemaTypeFixupWhitespace(type);
18253 HFAILURE HERROR
Daniel Veillarddee23482008-04-11 12:58:43 +000018254 xmlSchemaTypeFixupOptimFacets(type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018255
18256exit_error:
18257#ifdef DEBUG_TYPE
18258 xmlSchemaDebugFixedType(pctxt, type);
18259#endif
18260 if (olderrs != pctxt->nberrors)
18261 return(pctxt->err);
18262 return(0);
18263
18264exit_failure:
18265#ifdef DEBUG_TYPE
18266 xmlSchemaDebugFixedType(pctxt, type);
18267#endif
18268 return(-1);
18269}
18270
18271static int
18272xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18273 xmlSchemaTypePtr type)
18274{
18275 int res = 0, olderrs = pctxt->nberrors;
18276 xmlSchemaTypePtr baseType = type->baseType;
18277
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018278 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018279 return(0);
18280 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18281 if (baseType == NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018282 PERROR_INT("xmlSchemaFixupComplexType",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018283 "missing baseType");
18284 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018285 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018286 /*
18287 * Fixup the base type.
18288 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018289 if (WXS_IS_TYPE_NOT_FIXED(baseType))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018290 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018291 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18292 /*
18293 * Skip fixup if the base type is invalid.
18294 * TODO: Generate a warning!
18295 */
18296 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000018297 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018298 /*
18299 * This basically checks if the base type can be derived.
18300 */
18301 res = xmlSchemaCheckSRCCT(pctxt, type);
Daniel Veillarddee23482008-04-11 12:58:43 +000018302 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018303 /*
18304 * Fixup the content type.
18305 */
18306 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18307 /*
18308 * Corresponds to <complexType><simpleContent>...
18309 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018310 if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018311 (baseType->contentTypeDef != NULL) &&
18312 (WXS_IS_RESTRICTION(type))) {
18313 xmlSchemaTypePtr contentBase, content;
18314#ifdef ENABLE_NAMED_LOCALS
18315 char buf[30];
18316 const xmlChar *tmpname;
18317#endif
18318 /*
18319 * SPEC (1) If <restriction> + base type is <complexType>,
18320 * "whose own {content type} is a simple type..."
18321 */
18322 if (type->contentTypeDef != NULL) {
18323 /*
18324 * SPEC (1.1) "the simple type definition corresponding to the
18325 * <simpleType> among the [children] of <restriction> if there
18326 * is one;"
18327 * Note that this "<simpleType> among the [children]" was put
18328 * into ->contentTypeDef during parsing.
18329 */
18330 contentBase = type->contentTypeDef;
18331 type->contentTypeDef = NULL;
18332 } else {
18333 /*
18334 * (1.2) "...otherwise (<restriction> has no <simpleType>
18335 * among its [children]), the simple type definition which
18336 * is the {content type} of the ... base type."
18337 */
18338 contentBase = baseType->contentTypeDef;
18339 }
18340 /*
18341 * SPEC
18342 * "... a simple type definition which restricts the simple
18343 * type definition identified in clause 1.1 or clause 1.2
18344 * with a set of facet components"
18345 *
18346 * Create the anonymous simple type, which will be the content
18347 * type of the complex type.
18348 */
18349#ifdef ENABLE_NAMED_LOCALS
18350 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18351 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018352 content = xmlSchemaAddType(pctxt, pctxt->schema,
18353 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018354 type->node, 0);
18355#else
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018356 content = xmlSchemaAddType(pctxt, pctxt->schema,
18357 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018358 type->node, 0);
18359#endif
18360 if (content == NULL)
18361 goto exit_failure;
18362 /*
18363 * We will use the same node as for the <complexType>
18364 * to have it somehow anchored in the schema doc.
18365 */
18366 content->type = XML_SCHEMA_TYPE_SIMPLE;
18367 content->baseType = contentBase;
18368 /*
18369 * Move the facets, previously anchored on the
18370 * complexType during parsing.
18371 */
18372 content->facets = type->facets;
18373 type->facets = NULL;
18374 content->facetSet = type->facetSet;
18375 type->facetSet = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000018376
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018377 type->contentTypeDef = content;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018378 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018379 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018380 /*
18381 * Fixup the newly created type. We don't need to check
18382 * for circularity here.
18383 */
18384 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018385 HFAILURE HERROR
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018386 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
Daniel Veillarddee23482008-04-11 12:58:43 +000018387 HFAILURE HERROR
18388
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018389 } else if ((WXS_IS_COMPLEX(baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018390 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18391 (WXS_IS_RESTRICTION(type))) {
18392 /*
18393 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18394 * an emptiable particle, then a simple type definition which
18395 * restricts the <restriction>'s <simpleType> child.
18396 */
18397 if ((type->contentTypeDef == NULL) ||
18398 (type->contentTypeDef->baseType == NULL)) {
18399 /*
18400 * TODO: Check if this ever happens.
18401 */
18402 xmlSchemaPCustomErr(pctxt,
18403 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018404 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018405 "Internal error: xmlSchemaTypeFixup, "
18406 "complex type '%s': the <simpleContent><restriction> "
Haibo Huangcfd91dc2020-07-30 23:01:33 -070018407 "is missing a <simpleType> child, but was not caught "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018408 "by xmlSchemaCheckSRCCT()", type->name);
18409 goto exit_failure;
18410 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018411 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018412 /*
18413 * SPEC (3) If <extension> + base is <complexType> with
18414 * <simpleType> content, "...then the {content type} of that
18415 * complex type definition"
18416 */
18417 if (baseType->contentTypeDef == NULL) {
18418 /*
18419 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
Haibo Huangcfd91dc2020-07-30 23:01:33 -070018420 * should have caught this already.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018421 */
18422 xmlSchemaPCustomErr(pctxt,
18423 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018424 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018425 "Internal error: xmlSchemaTypeFixup, "
18426 "complex type '%s': the <extension>ed base type is "
18427 "a complex type with no simple content type",
18428 type->name);
18429 goto exit_failure;
18430 }
18431 type->contentTypeDef = baseType->contentTypeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018432 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018433 /*
18434 * SPEC (4) <extension> + base is <simpleType>
18435 * "... then that simple type definition"
18436 */
18437 type->contentTypeDef = baseType;
18438 } else {
18439 /*
18440 * TODO: Check if this ever happens.
18441 */
18442 xmlSchemaPCustomErr(pctxt,
18443 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018444 WXS_BASIC_CAST type, NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018445 "Internal error: xmlSchemaTypeFixup, "
18446 "complex type '%s' with <simpleContent>: unhandled "
18447 "derivation case", type->name);
18448 goto exit_failure;
18449 }
18450 } else {
18451 int dummySequence = 0;
18452 xmlSchemaParticlePtr particle =
18453 (xmlSchemaParticlePtr) type->subtypes;
18454 /*
18455 * Corresponds to <complexType><complexContent>...
18456 *
18457 * NOTE that the effective mixed was already set during parsing of
18458 * <complexType> and <complexContent>; its flag value is
18459 * XML_SCHEMAS_TYPE_MIXED.
18460 *
18461 * Compute the "effective content":
18462 * (2.1.1) + (2.1.2) + (2.1.3)
18463 */
18464 if ((particle == NULL) ||
18465 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18466 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18467 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18468 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18469 (particle->minOccurs == 0))) &&
18470 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18471 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18472 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018473 * SPEC (2.1.4) "If the `effective mixed` is true, then
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018474 * a particle whose properties are as follows:..."
18475 *
18476 * Empty sequence model group with
18477 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18478 * NOTE that we sill assign it the <complexType> node to
18479 * somehow anchor it in the doc.
18480 */
18481 if ((particle == NULL) ||
18482 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18483 /*
18484 * Create the particle.
18485 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018486 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018487 type->node, 1, 1);
18488 if (particle == NULL)
18489 goto exit_failure;
18490 /*
18491 * Create the model group.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018492 */ /* URGENT TODO: avoid adding to pending items. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018493 particle->children = (xmlSchemaTreeItemPtr)
18494 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18495 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18496 if (particle->children == NULL)
18497 goto exit_failure;
Daniel Veillarddee23482008-04-11 12:58:43 +000018498
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018499 type->subtypes = (xmlSchemaTypePtr) particle;
18500 }
18501 dummySequence = 1;
18502 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18503 } else {
18504 /*
18505 * SPEC (2.1.5) "otherwise empty"
18506 */
18507 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18508 }
18509 } else {
18510 /*
18511 * SPEC (2.2) "otherwise the particle corresponding to the
18512 * <all>, <choice>, <group> or <sequence> among the
18513 * [children]."
18514 */
18515 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18516 }
18517 /*
18518 * Compute the "content type".
18519 */
18520 if (WXS_IS_RESTRICTION(type)) {
18521 /*
18522 * SPEC (3.1) "If <restriction>..."
18523 * (3.1.1) + (3.1.2) */
18524 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18525 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18526 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18527 }
18528 } else {
18529 /*
18530 * SPEC (3.2) "If <extension>..."
18531 */
18532 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18533 /*
18534 * SPEC (3.2.1)
Jan Pokorný761c9e92013-11-29 23:26:27 +010018535 * "If the `effective content` is empty, then the
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018536 * {content type} of the [...] base ..."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018537 */
18538 type->contentType = baseType->contentType;
18539 type->subtypes = baseType->subtypes;
18540 /*
Kasimier T. Buchcikf896d442006-07-12 15:18:08 +000018541 * Fixes bug #347316:
18542 * This is the case when the base type has a simple
18543 * type definition as content.
18544 */
18545 type->contentTypeDef = baseType->contentTypeDef;
18546 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018547 * NOTE that the effective mixed is ignored here.
18548 */
18549 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18550 /*
18551 * SPEC (3.2.2)
18552 */
18553 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18554 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18555 } else {
18556 /*
18557 * SPEC (3.2.3)
18558 */
18559 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18560 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18561 /*
18562 * "A model group whose {compositor} is sequence and whose
18563 * {particles} are..."
18564 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018565 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18566 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18567 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18568 XML_SCHEMA_TYPE_ALL))
18569 {
18570 /*
18571 * SPEC cos-all-limited (1)
18572 */
18573 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18574 /* TODO: error code */
18575 XML_SCHEMAP_COS_ALL_LIMITED,
18576 WXS_ITEM_NODE(type), NULL,
18577 "The type has an 'all' model group in its "
18578 "{content type} and thus cannot be derived from "
18579 "a non-empty type, since this would produce a "
18580 "'sequence' model group containing the 'all' "
18581 "model group; 'all' model groups are not "
18582 "allowed to appear inside other model groups",
18583 NULL, NULL);
18584
18585 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18586 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18587 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18588 XML_SCHEMA_TYPE_ALL))
18589 {
18590 /*
18591 * SPEC cos-all-limited (1)
18592 */
18593 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18594 /* TODO: error code */
18595 XML_SCHEMAP_COS_ALL_LIMITED,
18596 WXS_ITEM_NODE(type), NULL,
18597 "A type cannot be derived by extension from a type "
18598 "which has an 'all' model group in its "
18599 "{content type}, since this would produce a "
18600 "'sequence' model group containing the 'all' "
18601 "model group; 'all' model groups are not "
18602 "allowed to appear inside other model groups",
18603 NULL, NULL);
18604
18605 } else if (! dummySequence) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018606 xmlSchemaTreeItemPtr effectiveContent =
18607 (xmlSchemaTreeItemPtr) type->subtypes;
18608 /*
18609 * Create the particle.
18610 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018611 particle = xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018612 type->node, 1, 1);
18613 if (particle == NULL)
18614 goto exit_failure;
18615 /*
18616 * Create the "sequence" model group.
18617 */
18618 particle->children = (xmlSchemaTreeItemPtr)
18619 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18620 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18621 if (particle->children == NULL)
18622 goto exit_failure;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018623 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018624 /*
18625 * SPEC "the particle of the {content type} of
18626 * the ... base ..."
18627 * Create a duplicate of the base type's particle
18628 * and assign its "term" to it.
18629 */
18630 particle->children->children =
18631 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000018632 type->node,
Remi Gacogne4609e6c2012-05-11 15:31:05 +080018633 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18634 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018635 if (particle->children->children == NULL)
18636 goto exit_failure;
18637 particle = (xmlSchemaParticlePtr)
18638 particle->children->children;
18639 particle->children =
18640 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18641 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010018642 * SPEC "followed by the `effective content`."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018643 */
18644 particle->next = effectiveContent;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018645 /*
18646 * This all will result in:
18647 * new-particle
18648 * --> new-sequence(
18649 * new-particle
18650 * --> base-model,
18651 * this-particle
18652 * --> this-model
18653 * )
18654 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018655 } else {
18656 /*
18657 * This is the case when there is already an empty
18658 * <sequence> with minOccurs==maxOccurs==1.
18659 * Just add the base types's content type.
18660 * NOTE that, although we miss to add an intermediate
18661 * <sequence>, this should produce no difference to
18662 * neither the regex compilation of the content model,
Haibo Huangcfd91dc2020-07-30 23:01:33 -070018663 * nor to the complex type constraints.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018664 */
18665 particle->children->children =
18666 (xmlSchemaTreeItemPtr) baseType->subtypes;
18667 }
18668 }
18669 }
18670 }
18671 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018672 * Now fixup attribute uses:
18673 * - expand attr. group references
18674 * - intersect attribute wildcards
18675 * - inherit attribute uses of the base type
18676 * - inherit or union attr. wildcards if extending
18677 * - apply attr. use prohibitions if restricting
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018678 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018679 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018680 HFAILURE HERROR
18681 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018682 * Apply the complex type component constraints; this will not
18683 * check attributes, since this is done in
18684 * xmlSchemaFixupTypeAttributeUses().
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018685 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018686 res = xmlSchemaCheckCTComponent(pctxt, type);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018687 HFAILURE HERROR
18688
18689#ifdef DEBUG_TYPE
18690 xmlSchemaDebugFixedType(pctxt, type);
18691#endif
18692 if (olderrs != pctxt->nberrors)
18693 return(pctxt->err);
18694 else
18695 return(0);
18696
18697exit_error:
18698 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18699#ifdef DEBUG_TYPE
18700 xmlSchemaDebugFixedType(pctxt, type);
18701#endif
18702 return(pctxt->err);
18703
18704exit_failure:
18705 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18706#ifdef DEBUG_TYPE
18707 xmlSchemaDebugFixedType(pctxt, type);
18708#endif
18709 return(-1);
18710}
18711
18712
18713/**
18714 * xmlSchemaTypeFixup:
18715 * @typeDecl: the schema type definition
18716 * @ctxt: the schema parser context
18717 *
18718 * Fixes the content model of the type.
18719 * URGENT TODO: We need an int result!
18720 */
18721static int
18722xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018723 xmlSchemaAbstractCtxtPtr actxt)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018724{
18725 if (type == NULL)
18726 return(0);
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018727 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18728 AERROR_INT("xmlSchemaTypeFixup",
18729 "this function needs a parser context");
18730 return(-1);
18731 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018732 if (! WXS_IS_TYPE_NOT_FIXED(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018733 return(0);
18734 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018735 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018736 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000018737 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018738 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000018739}
18740
18741/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018742 * xmlSchemaCheckFacet:
18743 * @facet: the facet
18744 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000018745 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018746 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018747 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018748 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018749 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018750 * Returns 0 if valid, a positive error code if not valid and
18751 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018752 */
18753int
18754xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018755 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018756 xmlSchemaParserCtxtPtr pctxt,
18757 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018758{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018759 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018760
Daniel Veillardce682bc2004-11-05 17:22:25 +000018761 if ((facet == NULL) || (typeDecl == NULL))
18762 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018763 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018764 * TODO: will the parser context be given if used from
18765 * the relaxNG module?
18766 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018767 if (pctxt == NULL)
18768 ctxtGiven = 0;
18769 else
18770 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018771
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018772 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018773 case XML_SCHEMA_FACET_MININCLUSIVE:
18774 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18775 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018776 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18777 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018778 /*
18779 * Okay we need to validate the value
18780 * at that point.
18781 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018782 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018783
18784 /* 4.3.5.5 Constraints on enumeration Schema Components
18785 * Schema Component Constraint: enumeration valid restriction
Jan Pokorný761c9e92013-11-29 23:26:27 +010018786 * It is an `error` if any member of {value} is not in the
18787 * `value space` of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018788 *
18789 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Jan Pokorný761c9e92013-11-29 23:26:27 +010018790 * The value `must` be in the
18791 * `value space` of the `base type`.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018792 */
18793 /*
18794 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018795 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018796 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018797 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018798 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018799 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018800 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018801 */
18802 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18803 base = typeDecl->baseType;
18804 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018805 PERROR_INT("xmlSchemaCheckFacet",
18806 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018807 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018808 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000018809 } else
18810 base = typeDecl;
Daniel Veillarddee23482008-04-11 12:58:43 +000018811
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018812 if (! ctxtGiven) {
18813 /*
18814 * A context is needed if called from RelaxNG.
Daniel Veillarddee23482008-04-11 12:58:43 +000018815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018816 pctxt = xmlSchemaNewParserCtxt("*");
18817 if (pctxt == NULL)
18818 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018819 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018820 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018821 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018822 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018823 * facet->node is just the node holding the facet
18824 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018825 * of the facet.
Daniel Veillarddee23482008-04-11 12:58:43 +000018826 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018827 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018828 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018829 facet->value, &(facet->val), 1, 1, 0);
18830 if (ret != 0) {
18831 if (ret < 0) {
18832 /* No error message for RelaxNG. */
Daniel Veillarddee23482008-04-11 12:58:43 +000018833 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018834 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018835 XML_SCHEMAP_INTERNAL, facet->node, NULL,
Daniel Veillarddee23482008-04-11 12:58:43 +000018836 "Internal error: xmlSchemaCheckFacet, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018837 "failed to validate the value '%s' of the "
18838 "facet '%s' against the base type",
18839 facet->value, xmlSchemaFacetTypeToString(facet->type));
18840 }
18841 goto internal_error;
18842 }
18843 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18844 /* No error message for RelaxNG. */
18845 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018846 xmlChar *str = NULL;
18847
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018848 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018849 ret, facet->node, WXS_BASIC_CAST facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018850 "The value '%s' of the facet does not validate "
18851 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018852 facet->value,
18853 xmlSchemaFormatQName(&str,
18854 base->targetNamespace, base->name));
18855 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018856 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018857 goto exit;
18858 } else if (facet->val == NULL) {
18859 if (ctxtGiven) {
18860 PERROR_INT("xmlSchemaCheckFacet",
18861 "value was not computed");
18862 }
18863 TODO
18864 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018865 break;
18866 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018867 case XML_SCHEMA_FACET_PATTERN:
18868 facet->regexp = xmlRegexpCompile(facet->value);
18869 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018870 ret = XML_SCHEMAP_REGEXP_INVALID;
18871 /* No error message for RelaxNG. */
18872 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018873 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018874 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018875 "The value '%s' of the facet 'pattern' is not a "
18876 "valid regular expression",
18877 facet->value, NULL);
18878 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018879 }
18880 break;
18881 case XML_SCHEMA_FACET_TOTALDIGITS:
18882 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18883 case XML_SCHEMA_FACET_LENGTH:
18884 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018885 case XML_SCHEMA_FACET_MINLENGTH:
18886
18887 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18888 ret = xmlSchemaValidatePredefinedType(
18889 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18890 facet->value, &(facet->val));
18891 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018892 ret = xmlSchemaValidatePredefinedType(
18893 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18894 facet->value, &(facet->val));
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018895 }
18896 if (ret != 0) {
18897 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018898 /* No error message for RelaxNG. */
18899 if (ctxtGiven) {
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018900 PERROR_INT("xmlSchemaCheckFacet",
18901 "validating facet value");
18902 }
18903 goto internal_error;
18904 }
18905 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18906 /* No error message for RelaxNG. */
18907 if (ctxtGiven) {
18908 /* error code */
18909 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18910 ret, facet->node, WXS_BASIC_CAST typeDecl,
Daniel Veillarddee23482008-04-11 12:58:43 +000018911 "The value '%s' of the facet '%s' is not a valid '%s'",
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018912 facet->value,
18913 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillarddee23482008-04-11 12:58:43 +000018914 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
Kasimier T. Buchcik69dea3a2005-11-07 14:02:44 +000018915 BAD_CAST "nonNegativeInteger" :
18916 BAD_CAST "positiveInteger",
18917 NULL);
18918 }
18919 }
18920 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000018921
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018922 case XML_SCHEMA_FACET_WHITESPACE:{
18923 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18924 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18925 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18926 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18927 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18928 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18929 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018930 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18931 /* No error message for RelaxNG. */
18932 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018933 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018934 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000018935 ret, facet->node, WXS_BASIC_CAST typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018936 "The value '%s' of the facet 'whitespace' is not "
18937 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018938 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018939 }
18940 }
18941 default:
18942 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018944exit:
18945 if ((! ctxtGiven) && (pctxt != NULL))
18946 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018947 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018948internal_error:
18949 if ((! ctxtGiven) && (pctxt != NULL))
18950 xmlSchemaFreeParserCtxt(pctxt);
18951 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000018952}
18953
18954/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018955 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000018956 * @typeDecl: the schema type definition
18957 * @ctxt: the schema parser context
18958 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018959 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000018960 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018961static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018962xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018963 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000018964{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018965 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018966 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018967 /*
18968 * NOTE: It is intended to use the facets list, instead
18969 * of facetSet.
18970 */
18971 if (typeDecl->facets != NULL) {
18972 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018973
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018974 /*
18975 * Temporarily assign the "schema" to the validation context
18976 * of the parser context. This is needed for NOTATION validation.
18977 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018978 if (pctxt->vctxt == NULL) {
18979 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18980 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018981 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018982 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018983 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018984 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18985 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000018986 facet = facet->next;
18987 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018988 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018989 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018990 if (olderrs != pctxt->nberrors)
18991 return(pctxt->err);
18992 return(0);
18993exit_failure:
18994 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018995}
18996
18997/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018998 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018999 * @ctxtMGroup: the searched model group
19000 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019001 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019002 *
19003 * This one is intended to be used by
19004 * xmlSchemaCheckGroupDefCircular only.
19005 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019006 * Returns the particle with the circular model group definition reference,
19007 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019008 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019009static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019010xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019011 xmlSchemaTreeItemPtr particle)
19012{
19013 xmlSchemaTreeItemPtr circ = NULL;
19014 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019015 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019016
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019017 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019018 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019019 if (term == NULL)
19020 continue;
19021 switch (term->type) {
19022 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019023 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019024 if (gdef == groupDef)
19025 return (particle);
19026 /*
19027 * Mark this model group definition to avoid infinite
19028 * recursion on circular references not yet examined.
19029 */
19030 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19031 continue;
19032 if (gdef->children != NULL) {
19033 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19034 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19035 gdef->children->children);
19036 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19037 if (circ != NULL)
19038 return (circ);
19039 }
19040 break;
19041 case XML_SCHEMA_TYPE_SEQUENCE:
19042 case XML_SCHEMA_TYPE_CHOICE:
19043 case XML_SCHEMA_TYPE_ALL:
19044 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19045 if (circ != NULL)
19046 return (circ);
19047 break;
19048 default:
19049 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019050 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019051 }
19052 return (NULL);
19053}
19054
19055/**
19056 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019057 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019058 * @ctxt: the parser context
19059 * @name: the name
19060 *
19061 * Checks for circular references to model group definitions.
19062 */
19063static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019064xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019065 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019066{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019067 /*
19068 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019069 * 2 Circular groups are disallowed. That is, within the {particles}
19070 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019071 * is the group itself.
19072 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019073 if ((item == NULL) ||
19074 (item->type != XML_SCHEMA_TYPE_GROUP) ||
19075 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019076 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019077 {
19078 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019079
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019080 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019081 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019082 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019083 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019084 * TODO: The error report is not adequate: this constraint
19085 * is defined for model groups but not definitions, but since
19086 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019087 * definition (if not using a construction API), we check those
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019088 * definitions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019089 */
19090 xmlSchemaPCustomErr(ctxt,
19091 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019092 NULL, WXS_ITEM_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019093 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019094 "defined", xmlSchemaFormatQName(&str,
19095 item->targetNamespace, item->name));
19096 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019097 /*
19098 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019099 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019100 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019101 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019102 }
19103 }
19104}
19105
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019106/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019107 * xmlSchemaModelGroupToModelGroupDefFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019108 * @ctxt: the parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019109 * @mg: the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019110 *
19111 * Assigns the model group of model group definitions to the "term"
19112 * of the referencing particle.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019113 * In xmlSchemaResolveModelGroupParticleReferences the model group
19114 * definitions were assigned to the "term", since needed for the
19115 * circularity check.
19116 *
19117 * Schema Component Constraint:
19118 * All Group Limited (cos-all-limited) (1.2)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019119 */
19120static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019121xmlSchemaModelGroupToModelGroupDefFixup(
19122 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19123 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019124{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019125 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19126
19127 while (particle != NULL) {
19128 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19129 ((WXS_PARTICLE_TERM(particle))->type !=
19130 XML_SCHEMA_TYPE_GROUP))
19131 {
19132 particle = WXS_PTC_CAST particle->next;
19133 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000019134 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019135 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19136 /*
19137 * TODO: Remove the particle.
19138 */
19139 WXS_PARTICLE_TERM(particle) = NULL;
19140 particle = WXS_PTC_CAST particle->next;
19141 continue;
19142 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019143 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019144 * Assign the model group to the {term} of the particle.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019145 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019146 WXS_PARTICLE_TERM(particle) =
19147 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19148
19149 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019150 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019151}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019152
19153/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019154 * xmlSchemaCheckAttrGroupCircularRecur:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019155 * @ctxtGr: the searched attribute group
19156 * @attr: the current attribute list to be processed
19157 *
19158 * This one is intended to be used by
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019159 * xmlSchemaCheckAttrGroupCircular only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019160 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019161 * Returns the circular attribute group reference, otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019162 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019163static xmlSchemaQNameRefPtr
19164xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19165 xmlSchemaItemListPtr list)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019166{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019167 xmlSchemaAttributeGroupPtr gr;
19168 xmlSchemaQNameRefPtr ref, circ;
19169 int i;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019170 /*
19171 * We will search for an attribute group reference which
19172 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019173 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019174 for (i = 0; i < list->nbItems; i++) {
19175 ref = list->items[i];
19176 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19177 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19178 (ref->item != NULL))
19179 {
19180 gr = WXS_ATTR_GROUP_CAST ref->item;
19181 if (gr == ctxtGr)
19182 return(ref);
19183 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
Daniel Veillarddee23482008-04-11 12:58:43 +000019184 continue;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019185 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019186 * Mark as visited to avoid infinite recursion on
19187 * circular references not yet examined.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019188 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019189 if ((gr->attrUses) &&
19190 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19191 {
19192 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19193 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019194 (xmlSchemaItemListPtr) gr->attrUses);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019195 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19196 if (circ != NULL)
19197 return (circ);
19198 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019199
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019200 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019201 }
19202 return (NULL);
19203}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019204
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019205/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019206 * xmlSchemaCheckAttrGroupCircular:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019207 * attrGr: the attribute group definition
19208 * @ctxt: the parser context
19209 * @name: the name
19210 *
19211 * Checks for circular references of attribute groups.
19212 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019213static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019214xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019215 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019216{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019217 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019218 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019219 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019220 * 3 Circular group reference is disallowed outside <redefine>.
19221 * That is, unless this element information item's parent is
19222 * <redefine>, then among the [children], if any, there must
19223 * not be an <attributeGroup> with ref [attribute] which resolves
19224 * to the component corresponding to this <attributeGroup>. Indirect
19225 * circularity is also ruled out. That is, when QName resolution
Jan Pokorný761c9e92013-11-29 23:26:27 +010019226 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019227 * any <attributeGroup>s with a ref [attribute] among the [children],
Jan Pokorný761c9e92013-11-29 23:26:27 +010019228 * it must not be the case that a `QName` is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019229 * which resolves to the component corresponding to this <attributeGroup>.
19230 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019231 if (attrGr->attrUses == NULL)
19232 return(0);
19233 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19234 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019235 else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019236 xmlSchemaQNameRefPtr circ;
Daniel Veillarddee23482008-04-11 12:58:43 +000019237
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019238 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
Daniel Veillarddee23482008-04-11 12:58:43 +000019239 (xmlSchemaItemListPtr) attrGr->attrUses);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019240 if (circ != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019241 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019242 /*
19243 * TODO: Report the referenced attr group as QName.
19244 */
19245 xmlSchemaPCustomErr(ctxt,
19246 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019247 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019248 "Circular reference to the attribute group '%s' "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019249 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19250 FREE_AND_NULL(str);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019251 /*
19252 * NOTE: We will cut the reference to avoid further
19253 * confusion of the processor.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019254 * BADSPEC TODO: The spec should define how to process in this case.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019255 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019256 circ->item = NULL;
19257 return(ctxt->err);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019258 }
19259 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019260 return(0);
19261}
19262
19263static int
19264xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19265 xmlSchemaAttributeGroupPtr attrGr);
19266
19267/**
19268 * xmlSchemaExpandAttributeGroupRefs:
19269 * @pctxt: the parser context
19270 * @node: the node of the component holding the attribute uses
Daniel Veillarddee23482008-04-11 12:58:43 +000019271 * @completeWild: the intersected wildcard to be returned
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019272 * @list: the attribute uses
19273 *
19274 * Substitutes contained attribute group references
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019275 * for their attribute uses. Wildcards are intersected.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019276 * Attribute use prohibitions are removed from the list
19277 * and returned via the @prohibs list.
19278 * Pointlessness of attr. prohibs, if a matching attr. decl
19279 * is existent a well, are checked.
19280 */
19281static int
19282xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19283 xmlSchemaBasicItemPtr item,
19284 xmlSchemaWildcardPtr *completeWild,
19285 xmlSchemaItemListPtr list,
19286 xmlSchemaItemListPtr prohibs)
19287{
19288 xmlSchemaAttributeGroupPtr gr;
19289 xmlSchemaAttributeUsePtr use;
19290 xmlSchemaItemListPtr sublist;
19291 int i, j;
19292 int created = (*completeWild == NULL) ? 0 : 1;
19293
19294 if (prohibs)
19295 prohibs->nbItems = 0;
19296
19297 for (i = 0; i < list->nbItems; i++) {
19298 use = list->items[i];
19299
Daniel Veillarddee23482008-04-11 12:58:43 +000019300 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019301 if (prohibs == NULL) {
19302 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19303 "unexpected attr prohibition found");
19304 return(-1);
19305 }
19306 /*
19307 * Remove from attribute uses.
19308 */
19309 if (xmlSchemaItemListRemove(list, i) == -1)
19310 return(-1);
19311 i--;
19312 /*
19313 * Note that duplicate prohibitions were already
19314 * handled at parsing time.
Daniel Veillarddee23482008-04-11 12:58:43 +000019315 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019316 /*
19317 * Add to list of prohibitions.
19318 */
19319 xmlSchemaItemListAddSize(prohibs, 2, use);
19320 continue;
19321 }
19322 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19323 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19324 {
19325 if ((WXS_QNAME_CAST use)->item == NULL)
19326 return(-1);
19327 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19328 /*
19329 * Expand the referenced attr. group.
19330 * TODO: remove this, this is done in a previous step, so
19331 * already done here.
19332 */
19333 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19334 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19335 return(-1);
19336 }
19337 /*
19338 * Build the 'complete' wildcard; i.e. intersect multiple
19339 * wildcards.
19340 */
19341 if (gr->attributeWildcard != NULL) {
19342 if (*completeWild == NULL) {
19343 *completeWild = gr->attributeWildcard;
19344 } else {
19345 if (! created) {
19346 xmlSchemaWildcardPtr tmpWild;
19347
19348 /*
19349 * Copy the first encountered wildcard as context,
19350 * except for the annotation.
19351 *
19352 * Although the complete wildcard might not correspond
19353 * to any node in the schema, we will anchor it on
19354 * the node of the owner component.
19355 */
19356 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19357 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19358 WXS_ITEM_NODE(item));
19359 if (tmpWild == NULL)
19360 return(-1);
19361 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19362 tmpWild, *completeWild) == -1)
19363 return (-1);
19364 tmpWild->processContents = (*completeWild)->processContents;
19365 *completeWild = tmpWild;
19366 created = 1;
19367 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019368
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019369 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19370 gr->attributeWildcard) == -1)
19371 return(-1);
19372 }
19373 }
19374 /*
19375 * Just remove the reference if the referenced group does not
19376 * contain any attribute uses.
19377 */
William M. Brack06559b32007-03-14 09:34:15 +000019378 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19379 if ((sublist == NULL) || sublist->nbItems == 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019380 if (xmlSchemaItemListRemove(list, i) == -1)
19381 return(-1);
19382 i--;
19383 continue;
19384 }
19385 /*
19386 * Add the attribute uses.
19387 */
William M. Brack06559b32007-03-14 09:34:15 +000019388 list->items[i] = sublist->items[0];
19389 if (sublist->nbItems != 1) {
19390 for (j = 1; j < sublist->nbItems; j++) {
19391 i++;
19392 if (xmlSchemaItemListInsert(list,
19393 sublist->items[j], i) == -1)
19394 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019395 }
William M. Brack06559b32007-03-14 09:34:15 +000019396 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019397 }
19398
19399 }
19400 /*
19401 * Handle pointless prohibitions of declared attributes.
19402 */
19403 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19404 xmlSchemaAttributeUseProhibPtr prohib;
19405
19406 for (i = prohibs->nbItems -1; i >= 0; i--) {
19407 prohib = prohibs->items[i];
19408 for (j = 0; j < list->nbItems; j++) {
19409 use = list->items[j];
19410
19411 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19412 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19413 {
19414 xmlChar *str = NULL;
19415
19416 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19417 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19418 prohib->node, NULL,
19419 "Skipping pointless attribute use prohibition "
19420 "'%s', since a corresponding attribute use "
19421 "exists already in the type definition",
19422 xmlSchemaFormatQName(&str,
19423 prohib->targetNamespace, prohib->name),
19424 NULL, NULL);
19425 FREE_AND_NULL(str);
19426 /*
19427 * Remove the prohibition.
19428 */
19429 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19430 return(-1);
19431 break;
19432 }
19433 }
19434 }
19435 }
19436 return(0);
19437}
19438
19439/**
19440 * xmlSchemaAttributeGroupExpandRefs:
19441 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019442 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019443 *
19444 * Computation of:
19445 * {attribute uses} property
19446 * {attribute wildcard} property
19447 *
19448 * Substitutes contained attribute group references
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019449 * for their attribute uses. Wildcards are intersected.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019450 */
19451static int
19452xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19453 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019454{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019455 if ((attrGr->attrUses == NULL) ||
19456 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19457 return(0);
19458
19459 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19460 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19461 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
Daniel Veillarddee23482008-04-11 12:58:43 +000019462 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019463 return(0);
19464}
19465
19466/**
19467 * xmlSchemaAttributeGroupExpandRefs:
19468 * @pctxt: the parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000019469 * @attrGr: the attribute group definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019470 *
19471 * Substitutes contained attribute group references
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019472 * for their attribute uses. Wildcards are intersected.
Daniel Veillarddee23482008-04-11 12:58:43 +000019473 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019474 * Schema Component Constraint:
Daniel Veillarddee23482008-04-11 12:58:43 +000019475 * Attribute Group Definition Properties Correct (ag-props-correct)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019476 */
19477static int
19478xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19479 xmlSchemaAttributeGroupPtr attrGr)
Daniel Veillarddee23482008-04-11 12:58:43 +000019480{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019481 /*
19482 * SPEC ag-props-correct
19483 * (1) "The values of the properties of an attribute group definition
19484 * must be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019485 * Group Definition Schema Component ($3.6.1), modulo the impact of
19486 * Missing Sub-components ($5.3);"
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019487 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019488
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019489 if ((attrGr->attrUses != NULL) &&
19490 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19491 {
19492 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19493 xmlSchemaAttributeUsePtr use, tmp;
19494 int i, j, hasId = 0;
19495
19496 for (i = uses->nbItems -1; i >= 0; i--) {
Daniel Veillarddee23482008-04-11 12:58:43 +000019497 use = uses->items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019498 /*
19499 * SPEC ag-props-correct
19500 * (2) "Two distinct members of the {attribute uses} must not have
19501 * {attribute declaration}s both of whose {name}s match and whose
19502 * {target namespace}s are identical."
19503 */
19504 if (i > 0) {
19505 for (j = i -1; j >= 0; j--) {
19506 tmp = uses->items[j];
19507 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19508 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19509 (WXS_ATTRUSE_DECL_TNS(use) ==
19510 WXS_ATTRUSE_DECL_TNS(tmp)))
19511 {
19512 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019513
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019514 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19515 XML_SCHEMAP_AG_PROPS_CORRECT,
19516 attrGr->node, WXS_BASIC_CAST attrGr,
19517 "Duplicate %s",
19518 xmlSchemaGetComponentDesignation(&str, use),
19519 NULL);
19520 FREE_AND_NULL(str);
19521 /*
19522 * Remove the duplicate.
19523 */
19524 if (xmlSchemaItemListRemove(uses, i) == -1)
19525 return(-1);
19526 goto next_use;
19527 }
19528 }
19529 }
19530 /*
19531 * SPEC ag-props-correct
19532 * (3) "Two distinct members of the {attribute uses} must not have
19533 * {attribute declaration}s both of whose {type definition}s are or
19534 * are derived from ID."
19535 * TODO: Does 'derived' include member-types of unions?
19536 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019537 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019538 if (xmlSchemaIsDerivedFromBuiltInType(
19539 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
Daniel Veillarddee23482008-04-11 12:58:43 +000019540 {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019541 if (hasId) {
19542 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000019543
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019544 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19545 XML_SCHEMAP_AG_PROPS_CORRECT,
19546 attrGr->node, WXS_BASIC_CAST attrGr,
19547 "There must not exist more than one attribute "
19548 "declaration of type 'xs:ID' "
19549 "(or derived from 'xs:ID'). The %s violates this "
19550 "constraint",
19551 xmlSchemaGetComponentDesignation(&str, use),
19552 NULL);
19553 FREE_AND_NULL(str);
19554 if (xmlSchemaItemListRemove(uses, i) == -1)
19555 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000019556 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019557 hasId = 1;
19558 }
19559 }
19560next_use: {}
19561 }
19562 }
19563 return(0);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000019564}
19565
19566/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019567 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000019568 * @attrgrpDecl: the schema attribute definition
19569 * @ctxt: the schema parser context
19570 * @name: the attribute name
19571 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019572 * Resolves references to attribute group definitions.
Daniel Veillard13e04c62002-04-23 17:51:29 +000019573 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019574static int
19575xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19576 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard13e04c62002-04-23 17:51:29 +000019577{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019578 xmlSchemaAttributeGroupPtr group;
Daniel Veillard13e04c62002-04-23 17:51:29 +000019579
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019580 if (ref->item != NULL)
19581 return(0);
19582 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19583 ref->name,
19584 ref->targetNamespace);
19585 if (group == NULL) {
19586 xmlSchemaPResCompAttrErr(ctxt,
19587 XML_SCHEMAP_SRC_RESOLVE,
19588 NULL, ref->node,
19589 "ref", ref->name, ref->targetNamespace,
19590 ref->itemType, NULL);
19591 return(ctxt->err);
Daniel Veillard3646d642004-06-02 19:19:14 +000019592 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019593 ref->item = WXS_BASIC_CAST group;
19594 return(0);
Daniel Veillard13e04c62002-04-23 17:51:29 +000019595}
19596
19597/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019598 * xmlSchemaCheckAttrPropsCorrect:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019599 * @item: an schema attribute declaration/use
19600 * @ctxt: a schema parser context
19601 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019602 *
19603 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019604 * Schema Component Constraint:
19605 * Attribute Declaration Properties Correct (a-props-correct)
Daniel Veillard4255d502002-04-16 15:50:10 +000019606 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019607 * Validates the value constraints of an attribute declaration/use.
Haibo Huangcfd91dc2020-07-30 23:01:33 -070019608 * NOTE that this needs the simple type definitions to be already
19609 * built and checked.
Daniel Veillard4255d502002-04-16 15:50:10 +000019610 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019611static int
19612xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19613 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019614{
19615
19616 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019617 * SPEC a-props-correct (1)
19618 * "The values of the properties of an attribute declaration must
19619 * be as described in the property tableau in The Attribute
Jan Pokorný761c9e92013-11-29 23:26:27 +010019620 * Declaration Schema Component ($3.2.1), modulo the impact of
19621 * Missing Sub-components ($5.3)."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019622 */
Daniel Veillarddee23482008-04-11 12:58:43 +000019623
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019624 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19625 return(0);
19626
19627 if (attr->defValue != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019628 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019629
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019630 /*
19631 * SPEC a-props-correct (3)
19632 * "If the {type definition} is or is derived from ID then there
19633 * must not be a {value constraint}."
19634 */
19635 if (xmlSchemaIsDerivedFromBuiltInType(
19636 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19637 {
19638 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19639 XML_SCHEMAP_A_PROPS_CORRECT_3,
19640 NULL, WXS_BASIC_CAST attr,
19641 "Value constraints are not allowed if the type definition "
19642 "is or is derived from xs:ID",
19643 NULL, NULL);
19644 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019645 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019646 /*
19647 * SPEC a-props-correct (2)
19648 * "if there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019649 * representation of its value must be `valid` with respect
19650 * to the {type definition} as defined in String Valid ($3.14.4)."
Jan Pokorný7a7cad62013-11-29 23:26:26 +010019651 * TODO: Don't care about the *canonical* stuff here, this requirement
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019652 * will be removed in WXS 1.1 anyway.
19653 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019654 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019655 attr->node, WXS_ATTR_TYPEDEF(attr),
19656 attr->defValue, &(attr->defVal),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019657 1, 1, 0);
19658 if (ret != 0) {
19659 if (ret < 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019660 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019661 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019662 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019663 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019664 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019665 XML_SCHEMAP_A_PROPS_CORRECT_2,
19666 NULL, WXS_BASIC_CAST attr,
19667 "The value of the value constraint is not valid",
19668 NULL, NULL);
19669 return(pctxt->err);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019670 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019671 }
Daniel Veillarddee23482008-04-11 12:58:43 +000019672
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019673 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019674}
19675
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019676static xmlSchemaElementPtr
19677xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19678 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019679{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019680 xmlSchemaElementPtr ret;
19681
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019682 if (WXS_SUBST_HEAD(ancestor) == NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019683 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019684 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019685 return (ancestor);
19686
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019687 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019688 return (NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019689 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019690 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019691 WXS_SUBST_HEAD(ancestor));
19692 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019693
19694 return (ret);
19695}
19696
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019697/**
19698 * xmlSchemaCheckElemPropsCorrect:
19699 * @ctxt: a schema parser context
19700 * @decl: the element declaration
19701 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019702 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019703 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019704 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019705 *
19706 * STATUS:
19707 * missing: (6)
19708 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019709static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019710xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19711 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019712{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019713 int ret = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019714 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019715 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019716 * SPEC (1) "The values of the properties of an element declaration
19717 * must be as described in the property tableau in The Element
Jan Pokorný761c9e92013-11-29 23:26:27 +010019718 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19719 * Sub-components ($5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019720 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019721 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19722 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019723
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019724 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019725 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010019726 * SPEC (3) "If there is a non-`absent` {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019727 * affiliation}, then {scope} must be global."
19728 */
19729 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19730 xmlSchemaPCustomErr(pctxt,
19731 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019732 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019733 "Only global element declarations can have a "
19734 "substitution group affiliation", NULL);
19735 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019736 }
19737 /*
19738 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19739 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019740 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019741 * property."
19742 */
19743 if (head == elemDecl)
19744 circ = head;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019745 else if (WXS_SUBST_HEAD(head) != NULL)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019746 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19747 else
19748 circ = NULL;
19749 if (circ != NULL) {
19750 xmlChar *strA = NULL, *strB = NULL;
19751
19752 xmlSchemaPCustomErrExt(pctxt,
19753 XML_SCHEMAP_E_PROPS_CORRECT_6,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019754 WXS_BASIC_CAST circ, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019755 "The element declaration '%s' defines a circular "
19756 "substitution group to element declaration '%s'",
19757 xmlSchemaGetComponentQName(&strA, circ),
19758 xmlSchemaGetComponentQName(&strB, head),
19759 NULL);
19760 FREE_AND_NULL(strA)
19761 FREE_AND_NULL(strB)
19762 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19763 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019764 /*
19765 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019766 * the {type definition}
19767 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019768 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019769 * of the {substitution group exclusions} of the {substitution group
Jan Pokorný761c9e92013-11-29 23:26:27 +010019770 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019771 * (if the {type definition} is complex) or as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019772 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019773 * simple)."
19774 *
19775 * NOTE: {substitution group exclusions} means the values of the
19776 * attribute "final".
19777 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019778
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019779 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019780 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019781
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019782 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19783 set |= SUBSET_EXTENSION;
19784 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19785 set |= SUBSET_RESTRICTION;
19786
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000019787 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019788 WXS_ELEM_TYPEDEF(head), set) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019789 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19790
19791 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019792 xmlSchemaPCustomErrExt(pctxt,
19793 XML_SCHEMAP_E_PROPS_CORRECT_4,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019794 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019795 "The type definition '%s' was "
19796 "either rejected by the substitution group "
19797 "affiliation '%s', or not validly derived from its type "
19798 "definition '%s'",
19799 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019800 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019801 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019802 FREE_AND_NULL(strA)
19803 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019804 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019805 }
19806 }
19807 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019808 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019809 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019810 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019811 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019812 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019813 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019814 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019815 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019816 ((WXS_IS_SIMPLE(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019817 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019818 (WXS_IS_COMPLEX(typeDef) &&
19819 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019820 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19821 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019822
19823 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19824 xmlSchemaPCustomErr(pctxt,
19825 XML_SCHEMAP_E_PROPS_CORRECT_5,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019826 WXS_BASIC_CAST elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019827 "The type definition (or type definition's content type) is or "
19828 "is derived from ID; value constraints are not allowed in "
19829 "conjunction with such a type definition", NULL);
19830 } else if (elemDecl->value != NULL) {
19831 int vcret;
19832 xmlNodePtr node = NULL;
19833
19834 /*
19835 * SPEC (2) "If there is a {value constraint}, the canonical lexical
Jan Pokorný761c9e92013-11-29 23:26:27 +010019836 * representation of its value must be `valid` with respect to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019837 * {type definition} as defined in Element Default Valid (Immediate)
Jan Pokorný761c9e92013-11-29 23:26:27 +010019838 * ($3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019839 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019840 if (typeDef == NULL) {
19841 xmlSchemaPErr(pctxt, elemDecl->node,
19842 XML_SCHEMAP_INTERNAL,
19843 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19844 "type is missing... skipping validation of "
19845 "the value constraint", NULL, NULL);
19846 return (-1);
19847 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019848 if (elemDecl->node != NULL) {
19849 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19850 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19851 BAD_CAST "fixed");
19852 else
19853 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19854 BAD_CAST "default");
19855 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019856 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19857 typeDef, elemDecl->value, &(elemDecl->defVal));
19858 if (vcret != 0) {
19859 if (vcret < 0) {
19860 PERROR_INT("xmlSchemaElemCheckValConstr",
19861 "failed to validate the value constraint of an "
19862 "element declaration");
19863 return (-1);
19864 }
19865 return (vcret);
19866 }
19867 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019868
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000019869 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019870}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019871
19872/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019873 * xmlSchemaCheckElemSubstGroup:
19874 * @ctxt: a schema parser context
19875 * @decl: the element declaration
19876 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019877 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019878 * Schema Component Constraint:
19879 * Substitution Group (cos-equiv-class)
19880 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019881 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019882 * a list will be built for each subst. group head, holding all direct
19883 * referents to this head.
19884 * NOTE that this function needs:
19885 * 1. circular subst. groups to be checked beforehand
19886 * 2. the declaration's type to be derived from the head's type
19887 *
19888 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019889 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019890 */
19891static void
19892xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19893 xmlSchemaElementPtr elemDecl)
19894{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019895 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019896 /* SPEC (1) "Its {abstract} is false." */
19897 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19898 return;
19899 {
19900 xmlSchemaElementPtr head;
19901 xmlSchemaTypePtr headType, type;
19902 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019903 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019904 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19905 * {disallowed substitutions} as the blocking constraint, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010019906 * Substitution Group OK (Transitive) ($3.3.6)."
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019907 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019908 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19909 head = WXS_SUBST_HEAD(head)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019910 set = 0;
19911 methSet = 0;
19912 /*
19913 * The blocking constraints.
19914 */
19915 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19916 continue;
19917 headType = head->subtypes;
19918 type = elemDecl->subtypes;
19919 if (headType == type)
19920 goto add_member;
19921 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19922 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19923 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19924 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19925 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019926 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019927 * "The set of all {derivation method}s involved in the
19928 * derivation of D's {type definition} from C's {type definition}
19929 * does not intersect with the union of the blocking constraint,
19930 * C's {prohibited substitutions} (if C is complex, otherwise the
19931 * empty set) and the {prohibited substitutions} (respectively the
19932 * empty set) of any intermediate {type definition}s in the
19933 * derivation of D's {type definition} from C's {type definition}."
19934 */
19935 /*
19936 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19937 * subst.head axis, the methSet does not need to be computed for
19938 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019939 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019940 /*
19941 * The set of all {derivation method}s involved in the derivation
19942 */
19943 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019944 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019945 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19946 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019947
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019948 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019949 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19950 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19951
19952 type = type->baseType;
19953 }
19954 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019955 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019956 * the head's type.
19957 */
19958 type = elemDecl->subtypes->baseType;
19959 while (type != NULL) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000019960 if (WXS_IS_COMPLEX(type)) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000019961 if ((type->flags &
19962 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19963 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19964 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19965 if ((type->flags &
19966 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19967 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19968 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19969 } else
19970 break;
19971 if (type == headType)
19972 break;
19973 type = type->baseType;
19974 }
19975 if ((set != 0) &&
19976 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19977 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19978 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19979 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19980 continue;
19981 }
19982add_member:
19983 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19984 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19985 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19986 }
19987 }
19988}
19989
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019990#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19991/**
19992 * xmlSchemaCheckElementDeclComponent
19993 * @pctxt: the schema parser context
19994 * @ctxtComponent: the context component (an element declaration)
19995 * @ctxtParticle: the first particle of the context component
19996 * @searchParticle: the element declaration particle to be analysed
19997 *
Daniel Veillarddee23482008-04-11 12:58:43 +000019998 * Schema Component Constraint: Element Declarations Consistent
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000019999 */
20000static int
20001xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20002 xmlSchemaBasicItemPtr ctxtComponent,
Daniel Veillarddee23482008-04-11 12:58:43 +000020003 xmlSchemaParticlePtr ctxtParticle,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020004 xmlSchemaParticlePtr searchParticle,
20005 xmlSchemaParticlePtr curParticle,
20006 int search)
20007{
20008 return(0);
20009
20010 int ret = 0;
20011 xmlSchemaParticlePtr cur = curParticle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020012 if (curParticle == NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020013 return(0);
20014 }
20015 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20016 /*
20017 * Just return in this case. A missing "term" of the particle
20018 * might arise due to an invalid "term" component.
20019 */
20020 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000020021 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020022 while (cur != NULL) {
20023 switch (WXS_PARTICLE_TERM(cur)->type) {
20024 case XML_SCHEMA_TYPE_ANY:
20025 break;
20026 case XML_SCHEMA_TYPE_ELEMENT:
20027 if (search == 0) {
20028 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20029 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20030 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000020031 return(ret);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020032 } else {
20033 xmlSchemaElementPtr elem =
20034 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20035 /*
20036 * SPEC Element Declarations Consistent:
20037 * "If the {particles} contains, either directly,
20038 * indirectly (that is, within the {particles} of a
Jan Pokorný761c9e92013-11-29 23:26:27 +010020039 * contained model group, recursively) or `implicitly`
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020040 * two or more element declaration particles with
20041 * the same {name} and {target namespace}, then
20042 * all their type definitions must be the same
20043 * top-level definition [...]"
20044 */
20045 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20046 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20047 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20048 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20049 {
20050 xmlChar *strA = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020051
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020052 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20053 /* TODO: error code */
20054 XML_SCHEMAP_COS_NONAMBIG,
20055 WXS_ITEM_NODE(cur), NULL,
20056 "In the content model of %s, there are multiple "
20057 "element declarations for '%s' with different "
20058 "type definitions",
20059 xmlSchemaGetComponentDesignation(&strA,
20060 ctxtComponent),
20061 xmlSchemaFormatQName(&strB,
20062 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20063 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20064 FREE_AND_NULL(strA);
20065 FREE_AND_NULL(strB);
20066 return(XML_SCHEMAP_COS_NONAMBIG);
20067 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020068 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020069 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000020070 case XML_SCHEMA_TYPE_SEQUENCE: {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020071 break;
20072 }
20073 case XML_SCHEMA_TYPE_CHOICE:{
20074 /*
20075 xmlSchemaTreeItemPtr sub;
Daniel Veillarddee23482008-04-11 12:58:43 +000020076
20077 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020078 while (sub != NULL) {
20079 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20080 ctxtParticle, ctxtElem);
20081 if (ret != 0)
20082 return(ret);
20083 sub = sub->next;
20084 }
20085 */
20086 break;
20087 }
20088 case XML_SCHEMA_TYPE_ALL:
20089 break;
20090 case XML_SCHEMA_TYPE_GROUP:
20091 break;
20092 default:
20093 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20094 "xmlSchemaCheckElementDeclConsistent",
20095 "found unexpected term of type '%s' in content model",
20096 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20097 return(-1);
20098 }
20099 cur = (xmlSchemaParticlePtr) cur->next;
20100 }
20101
20102exit:
20103 return(ret);
20104}
20105#endif
20106
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000020107/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020108 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020109 * @item: an schema element declaration/particle
20110 * @ctxt: a schema parser context
20111 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020112 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020113 * Validates the value constraints of an element declaration.
Daniel Veillarddee23482008-04-11 12:58:43 +000020114 * Adds substitution group members.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020115 */
20116static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020117xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020118 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020119{
20120 if (elemDecl == NULL)
20121 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020122 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20123 return;
20124 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020125 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20126 /*
20127 * Adds substitution group members.
20128 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020129 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020130 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020131}
20132
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020133/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020134 * xmlSchemaResolveModelGroupParticleReferences:
20135 * @particle: a particle component
20136 * @ctxt: a parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020137 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020138 * Resolves references of a model group's {particles} to
20139 * model group definitions and to element declarations.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020140 */
20141static void
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020142xmlSchemaResolveModelGroupParticleReferences(
20143 xmlSchemaParserCtxtPtr ctxt,
20144 xmlSchemaModelGroupPtr mg)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020145{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020146 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20147 xmlSchemaQNameRefPtr ref;
20148 xmlSchemaBasicItemPtr refItem;
20149
20150 /*
20151 * URGENT TODO: Test this.
20152 */
20153 while (particle != NULL) {
20154 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20155 ((WXS_PARTICLE_TERM(particle))->type !=
20156 XML_SCHEMA_EXTRA_QNAMEREF))
20157 {
20158 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020159 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020160 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020161 /*
20162 * Resolve the reference.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020163 * NULL the {term} by default.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020164 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020165 particle->children = NULL;
20166
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020167 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20168 ref->itemType, ref->name, ref->targetNamespace);
20169 if (refItem == NULL) {
20170 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020171 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020172 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020173 /* TODO: remove the particle. */
20174 goto next_particle;
Daniel Veillarddee23482008-04-11 12:58:43 +000020175 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020176 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20177 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20178 /* TODO: remove the particle. */
20179 goto next_particle;
20180 /*
20181 * NOTE that we will assign the model group definition
20182 * itself to the "term" of the particle. This will ease
20183 * the check for circular model group definitions. After
20184 * that the "term" will be assigned the model group of the
20185 * model group definition.
20186 */
20187 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20188 XML_SCHEMA_TYPE_ALL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020189 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020190 * SPEC cos-all-limited (1)
20191 * SPEC cos-all-limited (1.2)
20192 * "It appears only as the value of one or both of the
20193 * following properties:"
20194 * (1.1) "the {model group} property of a model group
20195 * definition."
20196 * (1.2) "the {term} property of a particle [... of] the "
20197 * {content type} of a complex type definition."
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020198 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020199 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20200 /* TODO: error code */
20201 XML_SCHEMAP_COS_ALL_LIMITED,
20202 WXS_ITEM_NODE(particle), NULL,
20203 "A model group definition is referenced, but "
20204 "it contains an 'all' model group, which "
20205 "cannot be contained by model groups",
20206 NULL, NULL);
20207 /* TODO: remove the particle. */
20208 goto next_particle;
20209 }
20210 particle->children = (xmlSchemaTreeItemPtr) refItem;
20211 } else {
20212 /*
20213 * TODO: Are referenced element declarations the only
20214 * other components we expect here?
20215 */
20216 particle->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020217 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020218next_particle:
20219 particle = WXS_PTC_CAST particle->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020220 }
20221}
20222
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020223static int
20224xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
Daniel Veillarddee23482008-04-11 12:58:43 +000020225 xmlSchemaValPtr y)
20226{
20227 xmlSchemaTypePtr tx, ty, ptx, pty;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020228 int ret;
20229
20230 while (x != NULL) {
20231 /* Same types. */
20232 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20233 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20234 ptx = xmlSchemaGetPrimitiveType(tx);
20235 pty = xmlSchemaGetPrimitiveType(ty);
20236 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020237 * (1) if a datatype T' is `derived` by `restriction` from an
20238 * atomic datatype T then the `value space` of T' is a subset of
20239 * the `value space` of T. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020240 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010020241 * (2) if datatypes T' and T'' are `derived` by `restriction`
20242 * from a common atomic ancestor T then the `value space`s of T'
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020243 * and T'' may overlap.
20244 */
20245 if (ptx != pty)
20246 return(0);
20247 /*
20248 * We assume computed values to be normalized, so do a fast
20249 * string comparison for string based types.
20250 */
20251 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020252 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020253 if (! xmlStrEqual(
20254 xmlSchemaValueGetAsString(x),
20255 xmlSchemaValueGetAsString(y)))
20256 return (0);
20257 } else {
20258 ret = xmlSchemaCompareValuesWhtsp(
20259 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20260 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20261 if (ret == -2)
20262 return(-1);
20263 if (ret != 0)
20264 return(0);
20265 }
20266 /*
20267 * Lists.
20268 */
20269 x = xmlSchemaValueGetNext(x);
20270 if (x != NULL) {
20271 y = xmlSchemaValueGetNext(y);
20272 if (y == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020273 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020274 } else if (xmlSchemaValueGetNext(y) != NULL)
20275 return (0);
20276 else
20277 return (1);
20278 }
20279 return (0);
20280}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020281
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020282/**
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020283 * xmlSchemaResolveAttrUseReferences:
20284 * @item: an attribute use
20285 * @ctxt: a parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020286 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020287 * Resolves the referenced attribute declaration.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020288 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020289static int
20290xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20291 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000020292{
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020293 if ((ctxt == NULL) || (ause == NULL))
20294 return(-1);
20295 if ((ause->attrDecl == NULL) ||
20296 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20297 return(0);
20298
20299 {
20300 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20301
20302 /*
20303 * TODO: Evaluate, what errors could occur if the declaration is not
20304 * found.
20305 */
20306 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20307 ref->name, ref->targetNamespace);
20308 if (ause->attrDecl == NULL) {
20309 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardf8e3db02012-09-11 13:26:36 +080020310 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020311 WXS_BASIC_CAST ause, ause->node,
20312 "ref", ref->name, ref->targetNamespace,
20313 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20314 return(ctxt->err);;
20315 }
20316 }
20317 return(0);
20318}
20319
20320/**
20321 * xmlSchemaCheckAttrUsePropsCorrect:
20322 * @ctxt: a parser context
Daniel Veillarddee23482008-04-11 12:58:43 +000020323 * @use: an attribute use
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020324 *
20325 * Schema Component Constraint:
20326 * Attribute Use Correct (au-props-correct)
Daniel Veillarddee23482008-04-11 12:58:43 +000020327 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020328 */
20329static int
20330xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20331 xmlSchemaAttributeUsePtr use)
20332{
20333 if ((ctxt == NULL) || (use == NULL))
20334 return(-1);
20335 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20336 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
Daniel Veillarddee23482008-04-11 12:58:43 +000020337 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020338
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020339 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020340 * SPEC au-props-correct (1)
20341 * "The values of the properties of an attribute use must be as
20342 * described in the property tableau in The Attribute Use Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020343 * Component ($3.5.1), modulo the impact of Missing
20344 * Sub-components ($5.3)."
Daniel Veillardc0826a72004-08-10 14:17:33 +000020345 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020346
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020347 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20348 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20349 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20350 {
20351 xmlSchemaPCustomErr(ctxt,
20352 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20353 WXS_BASIC_CAST use, NULL,
20354 "The attribute declaration has a 'fixed' value constraint "
20355 ", thus the attribute use must also have a 'fixed' value "
20356 "constraint",
20357 NULL);
20358 return(ctxt->err);
20359 }
20360 /*
20361 * Compute and check the value constraint's value.
20362 */
20363 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20364 int ret;
20365 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000020366 * TODO: The spec seems to be missing a check of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020367 * value constraint of the attribute use. We will do it here.
20368 */
20369 /*
20370 * SPEC a-props-correct (3)
20371 */
20372 if (xmlSchemaIsDerivedFromBuiltInType(
20373 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20374 {
20375 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20376 XML_SCHEMAP_AU_PROPS_CORRECT,
20377 NULL, WXS_BASIC_CAST use,
20378 "Value constraints are not allowed if the type definition "
20379 "is or is derived from xs:ID",
20380 NULL, NULL);
20381 return(ctxt->err);
20382 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020383
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020384 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20385 use->node, WXS_ATTRUSE_TYPEDEF(use),
20386 use->defValue, &(use->defVal),
20387 1, 1, 0);
20388 if (ret != 0) {
20389 if (ret < 0) {
20390 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20391 "calling xmlSchemaVCheckCVCSimpleType()");
20392 return(-1);
20393 }
20394 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20395 XML_SCHEMAP_AU_PROPS_CORRECT,
20396 NULL, WXS_BASIC_CAST use,
20397 "The value of the value constraint is not valid",
20398 NULL, NULL);
20399 return(ctxt->err);
20400 }
20401 }
20402 /*
20403 * SPEC au-props-correct (2)
20404 * "If the {attribute declaration} has a fixed
20405 * {value constraint}, then if the attribute use itself has a
20406 * {value constraint}, it must also be fixed and its value must match
20407 * that of the {attribute declaration}'s {value constraint}."
20408 */
20409 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20410 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20411 {
20412 if (! xmlSchemaAreValuesEqual(use->defVal,
20413 (WXS_ATTRUSE_DECL(use))->defVal))
20414 {
20415 xmlSchemaPCustomErr(ctxt,
20416 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20417 WXS_BASIC_CAST use, NULL,
20418 "The 'fixed' value constraint of the attribute use "
20419 "must match the attribute declaration's value "
20420 "constraint '%s'",
20421 (WXS_ATTRUSE_DECL(use))->defValue);
20422 }
20423 return(ctxt->err);
20424 }
20425 return(0);
20426}
20427
20428
20429
20430
20431/**
20432 * xmlSchemaResolveAttrTypeReferences:
20433 * @item: an attribute declaration
Daniel Veillarddee23482008-04-11 12:58:43 +000020434 * @ctxt: a parser context
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020435 *
20436 * Resolves the referenced type definition component.
20437 */
20438static int
20439xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20440 xmlSchemaParserCtxtPtr ctxt)
20441{
Daniel Veillard01fa6152004-06-29 17:04:39 +000020442 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020443 * The simple type definition corresponding to the <simpleType> element
20444 * information item in the [children], if present, otherwise the simple
Jan Pokorný761c9e92013-11-29 23:26:27 +010020445 * type definition `resolved` to by the `actual value` of the type
20446 * [attribute], if present, otherwise the `simple ur-type definition`.
Daniel Veillard01fa6152004-06-29 17:04:39 +000020447 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020448 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020449 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020450 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20451 if (item->subtypes != NULL)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020452 return(0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020453 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020454 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000020455
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020456 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20457 item->typeNs);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020458 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020459 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020460 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020461 WXS_BASIC_CAST item, item->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020462 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020463 XML_SCHEMA_TYPE_SIMPLE, NULL);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020464 return(ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020465 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020466 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020467
Daniel Veillard3646d642004-06-02 19:19:14 +000020468 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020469 /*
20470 * The type defaults to the xs:anySimpleType.
20471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020472 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20473 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020474 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020475}
20476
20477/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020478 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020479 * @idc: the identity-constraint definition
20480 * @ctxt: the schema parser context
20481 * @name: the attribute name
20482 *
20483 * Resolve keyRef references to key/unique IDCs.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020484 * Schema Component Constraint:
20485 * Identity-constraint Definition Properties Correct (c-props-correct)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020486 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020487static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020488xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020489 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020490{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020491 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020492 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020493 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020494 idc->ref->item = (xmlSchemaBasicItemPtr)
20495 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20496 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020497 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020498 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020499 * TODO: It is actually not an error to fail to resolve
20500 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020501 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020502 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020503 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020504 WXS_BASIC_CAST idc, idc->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020505 "refer", idc->ref->name,
20506 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020507 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020508 return(pctxt->err);
20509 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20510 /*
20511 * SPEC c-props-correct (1)
20512 */
20513 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20514 XML_SCHEMAP_C_PROPS_CORRECT,
20515 NULL, WXS_BASIC_CAST idc,
20516 "The keyref references a keyref",
20517 NULL, NULL);
20518 idc->ref->item = NULL;
20519 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020520 } else {
20521 if (idc->nbFields !=
20522 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20523 xmlChar *str = NULL;
20524 xmlSchemaIDCPtr refer;
Daniel Veillarddee23482008-04-11 12:58:43 +000020525
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020526 refer = (xmlSchemaIDCPtr) idc->ref->item;
20527 /*
20528 * SPEC c-props-correct(2)
20529 * "If the {identity-constraint category} is keyref,
20530 * the cardinality of the {fields} must equal that of
20531 * the {fields} of the {referenced key}.
20532 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020533 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020534 XML_SCHEMAP_C_PROPS_CORRECT,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020535 NULL, WXS_BASIC_CAST idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020536 "The cardinality of the keyref differs from the "
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020537 "cardinality of the referenced key/unique '%s'",
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020538 xmlSchemaFormatQName(&str, refer->targetNamespace,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020539 refer->name),
20540 NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020541 FREE_AND_NULL(str)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020542 return(pctxt->err);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000020543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020544 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020545 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020546 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020547}
20548
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020549static int
20550xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20551 xmlSchemaParserCtxtPtr pctxt)
20552{
20553 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20554 prohib->targetNamespace) == NULL) {
20555
20556 xmlSchemaPResCompAttrErr(pctxt,
20557 XML_SCHEMAP_SRC_RESOLVE,
20558 NULL, prohib->node,
20559 "ref", prohib->name, prohib->targetNamespace,
20560 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20561 return(XML_SCHEMAP_SRC_RESOLVE);
20562 }
20563 return(0);
20564}
20565
20566#define WXS_REDEFINED_TYPE(c) \
20567(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20568
20569#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20570(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20571
20572#define WXS_REDEFINED_ATTR_GROUP(c) \
20573(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20574
20575static int
20576xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20577{
20578 int err = 0;
20579 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20580 xmlSchemaBasicItemPtr prev, item;
20581 int wasRedefined;
20582
20583 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020584 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020585
20586 do {
20587 item = redef->item;
20588 /*
20589 * First try to locate the redefined component in the
20590 * schema graph starting with the redefined schema.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020591 * NOTE: According to this schema bug entry:
20592 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20593 * it's not clear if the referenced component needs to originate
20594 * from the <redefine>d schema _document_ or the schema; the latter
20595 * would include all imported and included sub-schemas of the
Haibo Huangcfd91dc2020-07-30 23:01:33 -070020596 * <redefine>d schema. Currently the latter approach is used.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020597 * SUPPLEMENT: It seems that the WG moves towards the latter
20598 * approach, so we are doing it right.
Daniel Veillarddee23482008-04-11 12:58:43 +000020599 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020600 */
20601 prev = xmlSchemaFindRedefCompInGraph(
20602 redef->targetBucket, item->type,
20603 redef->refName, redef->refTargetNs);
20604 if (prev == NULL) {
20605 xmlChar *str = NULL;
20606 xmlNodePtr node;
20607
20608 /*
20609 * SPEC src-redefine:
Jan Pokorný761c9e92013-11-29 23:26:27 +010020610 * (6.2.1) "The `actual value` of its own name attribute plus
20611 * target namespace must successfully `resolve` to a model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020612 * group definition in I."
Jan Pokorný761c9e92013-11-29 23:26:27 +010020613 * (7.2.1) "The `actual value` of its own name attribute plus
20614 * target namespace must successfully `resolve` to an attribute
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020615 * group definition in I."
20616
20617 *
20618 * Note that, if we are redefining with the use of references
20619 * to components, the spec assumes the src-resolve to be used;
20620 * but this won't assure that we search only *inside* the
20621 * redefined schema.
20622 */
20623 if (redef->reference)
20624 node = WXS_ITEM_NODE(redef->reference);
20625 else
20626 node = WXS_ITEM_NODE(item);
20627 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20628 /*
20629 * TODO: error code.
20630 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
Daniel Veillarddee23482008-04-11 12:58:43 +000020631 * reference kind.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020632 */
20633 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
Kasimier T. Buchcik5d2998b2005-11-22 17:36:01 +000020634 "The %s '%s' to be redefined could not be found in "
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020635 "the redefined schema",
20636 WXS_ITEM_TYPE_NAME(item),
20637 xmlSchemaFormatQName(&str, redef->refTargetNs,
20638 redef->refName));
Daniel Veillarddee23482008-04-11 12:58:43 +000020639 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020640 err = pctxt->err;
20641 redef = redef->next;
20642 continue;
20643 }
20644 /*
20645 * TODO: Obtaining and setting the redefinition state is really
20646 * clumsy.
20647 */
20648 wasRedefined = 0;
20649 switch (item->type) {
20650 case XML_SCHEMA_TYPE_COMPLEX:
20651 case XML_SCHEMA_TYPE_SIMPLE:
20652 if ((WXS_TYPE_CAST prev)->flags &
20653 XML_SCHEMAS_TYPE_REDEFINED)
20654 {
20655 wasRedefined = 1;
20656 break;
20657 }
20658 /* Mark it as redefined. */
20659 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20660 /*
20661 * Assign the redefined type to the
20662 * base type of the redefining type.
20663 * TODO: How
20664 */
Daniel Veillarddee23482008-04-11 12:58:43 +000020665 ((xmlSchemaTypePtr) item)->baseType =
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020666 (xmlSchemaTypePtr) prev;
20667 break;
20668 case XML_SCHEMA_TYPE_GROUP:
20669 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20670 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20671 {
20672 wasRedefined = 1;
20673 break;
20674 }
20675 /* Mark it as redefined. */
20676 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20677 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20678 if (redef->reference != NULL) {
20679 /*
20680 * Overwrite the QName-reference with the
20681 * referenced model group def.
20682 */
20683 (WXS_PTC_CAST redef->reference)->children =
20684 WXS_TREE_CAST prev;
20685 }
20686 redef->target = prev;
20687 break;
20688 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20689 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20690 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20691 {
20692 wasRedefined = 1;
20693 break;
20694 }
20695 (WXS_ATTR_GROUP_CAST prev)->flags |=
20696 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20697 if (redef->reference != NULL) {
20698 /*
20699 * Assign the redefined attribute group to the
20700 * QName-reference component.
20701 * This is the easy case, since we will just
20702 * expand the redefined group.
20703 */
20704 (WXS_QNAME_CAST redef->reference)->item = prev;
20705 redef->target = NULL;
20706 } else {
20707 /*
20708 * This is the complicated case: we need
20709 * to apply src-redefine (7.2.2) at a later
20710 * stage, i.e. when attribute group references
Haibo Huangcfd91dc2020-07-30 23:01:33 -070020711 * have been expanded and simple types have
20712 * been fixed.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020713 */
20714 redef->target = prev;
20715 }
20716 break;
20717 default:
20718 PERROR_INT("xmlSchemaResolveRedefReferences",
20719 "Unexpected redefined component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020720 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020721 }
20722 if (wasRedefined) {
20723 xmlChar *str = NULL;
20724 xmlNodePtr node;
20725
20726 if (redef->reference)
20727 node = WXS_ITEM_NODE(redef->reference);
20728 else
20729 node = WXS_ITEM_NODE(redef->item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020730
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020731 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20732 /* TODO: error code. */
20733 XML_SCHEMAP_SRC_REDEFINE,
20734 node, NULL,
20735 "The referenced %s was already redefined. Multiple "
20736 "redefinition of the same component is not supported",
20737 xmlSchemaGetComponentDesignation(&str, prev),
20738 NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000020739 FREE_AND_NULL(str)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020740 err = pctxt->err;
20741 redef = redef->next;
20742 continue;
20743 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020744 redef = redef->next;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020745 } while (redef != NULL);
20746
20747 return(err);
20748}
20749
20750static int
20751xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20752{
20753 int err = 0;
20754 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20755 xmlSchemaBasicItemPtr item;
20756
20757 if (redef == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020758 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020759
20760 do {
20761 if (redef->target == NULL) {
20762 redef = redef->next;
20763 continue;
20764 }
20765 item = redef->item;
Daniel Veillarddee23482008-04-11 12:58:43 +000020766
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020767 switch (item->type) {
20768 case XML_SCHEMA_TYPE_SIMPLE:
20769 case XML_SCHEMA_TYPE_COMPLEX:
20770 /*
20771 * Since the spec wants the {name} of the redefined
20772 * type to be 'absent', we'll NULL it.
20773 */
20774 (WXS_TYPE_CAST redef->target)->name = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020775
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020776 /*
20777 * TODO: Seems like there's nothing more to do. The normal
20778 * inheritance mechanism is used. But not 100% sure.
20779 */
20780 break;
20781 case XML_SCHEMA_TYPE_GROUP:
20782 /*
20783 * URGENT TODO:
20784 * SPEC src-redefine:
20785 * (6.2.2) "The {model group} of the model group definition
20786 * which corresponds to it per XML Representation of Model
Jan Pokorný761c9e92013-11-29 23:26:27 +010020787 * Group Definition Schema Components ($3.7.2) must be a
20788 * `valid restriction` of the {model group} of that model
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020789 * group definition in I, as defined in Particle Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010020790 * (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020791 */
20792 break;
20793 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20794 /*
20795 * SPEC src-redefine:
20796 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20797 * the attribute group definition which corresponds to it
20798 * per XML Representation of Attribute Group Definition Schema
Jan Pokorný761c9e92013-11-29 23:26:27 +010020799 * Components ($3.6.2) must be `valid restrictions` of the
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020800 * {attribute uses} and {attribute wildcard} of that attribute
20801 * group definition in I, as defined in clause 2, clause 3 and
20802 * clause 4 of Derivation Valid (Restriction, Complex)
Jan Pokorný761c9e92013-11-29 23:26:27 +010020803 * ($3.4.6) (where references to the base type definition are
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020804 * understood as references to the attribute group definition
20805 * in I)."
20806 */
20807 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20808 XML_SCHEMA_ACTION_REDEFINE,
20809 item, redef->target,
20810 (WXS_ATTR_GROUP_CAST item)->attrUses,
20811 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20812 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20813 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20814 if (err == -1)
20815 return(-1);
20816 break;
20817 default:
20818 break;
20819 }
20820 redef = redef->next;
20821 } while (redef != NULL);
20822 return(0);
20823}
Daniel Veillarddee23482008-04-11 12:58:43 +000020824
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020825
20826static int
20827xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20828 xmlSchemaBucketPtr bucket)
20829{
20830 xmlSchemaBasicItemPtr item;
20831 int err;
20832 xmlHashTablePtr *table;
20833 const xmlChar *name;
20834 int i;
20835
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020836#define WXS_GET_GLOBAL_HASH(c, slot) { \
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020837 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20838 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20839 else \
20840 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20841
20842 /*
20843 * Add global components to the schema's hash tables.
20844 * This is the place where duplicate components will be
20845 * detected.
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000020846 * TODO: I think normally we should support imports of the
20847 * same namespace from multiple locations. We don't do currently,
20848 * but if we do then according to:
20849 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20850 * we would need, if imported directly, to import redefined
20851 * components as well to be able to catch clashing components.
20852 * (I hope I'll still know what this means after some months :-()
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020853 */
20854 if (bucket == NULL)
20855 return(-1);
20856 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20857 return(0);
Daniel Veillarddee23482008-04-11 12:58:43 +000020858 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20859
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020860 for (i = 0; i < bucket->globals->nbItems; i++) {
20861 item = bucket->globals->items[i];
20862 table = NULL;
20863 switch (item->type) {
20864 case XML_SCHEMA_TYPE_COMPLEX:
20865 case XML_SCHEMA_TYPE_SIMPLE:
20866 if (WXS_REDEFINED_TYPE(item))
20867 continue;
20868 name = (WXS_TYPE_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020869 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020870 break;
20871 case XML_SCHEMA_TYPE_ELEMENT:
20872 name = (WXS_ELEM_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020873 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020874 break;
20875 case XML_SCHEMA_TYPE_ATTRIBUTE:
20876 name = (WXS_ATTR_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020877 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020878 break;
20879 case XML_SCHEMA_TYPE_GROUP:
20880 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20881 continue;
20882 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020883 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020884 break;
20885 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20886 if (WXS_REDEFINED_ATTR_GROUP(item))
20887 continue;
20888 name = (WXS_ATTR_GROUP_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020889 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020890 break;
20891 case XML_SCHEMA_TYPE_IDC_KEY:
20892 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20893 case XML_SCHEMA_TYPE_IDC_KEYREF:
20894 name = (WXS_IDC_CAST item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020895 WXS_GET_GLOBAL_HASH(bucket, idcDef)
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020896 break;
20897 case XML_SCHEMA_TYPE_NOTATION:
20898 name = ((xmlSchemaNotationPtr) item)->name;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020899 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
Daniel Veillarddee23482008-04-11 12:58:43 +000020900 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020901 default:
20902 PERROR_INT("xmlSchemaAddComponents",
20903 "Unexpected global component type");
Daniel Veillarddee23482008-04-11 12:58:43 +000020904 continue;
20905 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020906 if (*table == NULL) {
20907 *table = xmlHashCreateDict(10, pctxt->dict);
20908 if (*table == NULL) {
20909 PERROR_INT("xmlSchemaAddComponents",
20910 "failed to create a component hash table");
20911 return(-1);
20912 }
Daniel Veillarddee23482008-04-11 12:58:43 +000020913 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020914 err = xmlHashAddEntry(*table, name, item);
Daniel Veillarddee23482008-04-11 12:58:43 +000020915 if (err != 0) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020916 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000020917
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020918 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20919 XML_SCHEMAP_REDEFINED_TYPE,
20920 WXS_ITEM_NODE(item),
20921 WXS_BASIC_CAST item,
20922 "A global %s '%s' does already exist",
20923 WXS_ITEM_TYPE_NAME(item),
20924 xmlSchemaGetComponentQName(&str, item));
Daniel Veillarddee23482008-04-11 12:58:43 +000020925 FREE_AND_NULL(str);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020926 }
20927 }
20928 /*
20929 * Process imported/included schemas.
20930 */
20931 if (bucket->relations != NULL) {
20932 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20933 do {
20934 if ((rel->bucket != NULL) &&
20935 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20936 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20937 return(-1);
20938 }
20939 rel = rel->next;
20940 } while (rel != NULL);
20941 }
20942 return(0);
20943}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020944
20945static int
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020946xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20947 xmlSchemaBucketPtr rootBucket)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020948{
20949 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20950 xmlSchemaTreeItemPtr item, *items;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020951 int nbItems, i, ret = 0;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020952 xmlSchemaBucketPtr oldbucket = con->bucket;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000020953 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020954
20955#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20956
20957 if ((con->pending == NULL) ||
20958 (con->pending->nbItems == 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000020959 return(0);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020960
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020961 /*
20962 * Since xmlSchemaFixupComplexType() will create new particles
20963 * (local components), and those particle components need a bucket
20964 * on the constructor, we'll assure here that the constructor has
20965 * a bucket.
Daniel Veillarddee23482008-04-11 12:58:43 +000020966 * TODO: Think about storing locals _only_ on the main bucket.
20967 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020968 if (con->bucket == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000020969 con->bucket = rootBucket;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000020970
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020971 /* TODO:
20972 * SPEC (src-redefine):
20973 * (6.2) "If it has no such self-reference, then all of the
20974 * following must be true:"
Daniel Veillarddee23482008-04-11 12:58:43 +000020975
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020976 * (6.2.2) The {model group} of the model group definition which
20977 * corresponds to it per XML Representation of Model Group
Jan Pokorný761c9e92013-11-29 23:26:27 +010020978 * Definition Schema Components ($3.7.2) must be a `valid
20979 * restriction` of the {model group} of that model group definition
20980 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000020981 */
20982 xmlSchemaCheckSRCRedefineFirst(pctxt);
20983
20984 /*
20985 * Add global components to the schemata's hash tables.
Daniel Veillarddee23482008-04-11 12:58:43 +000020986 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000020987 xmlSchemaAddComponents(pctxt, rootBucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020988
20989 pctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020990 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20991 nbItems = con->pending->nbItems;
20992 /*
20993 * Now that we have parsed *all* the schema document(s) and converted
20994 * them to schema components, we can resolve references, apply component
20995 * constraints, create the FSA from the content model, etc.
Daniel Veillarddee23482008-04-11 12:58:43 +000020996 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020997 /*
20998 * Resolve references of..
20999 *
21000 * 1. element declarations:
21001 * - the type definition
21002 * - the substitution group affiliation
21003 * 2. simple/complex types:
21004 * - the base type definition
21005 * - the memberTypes of union types
21006 * - the itemType of list types
21007 * 3. attributes declarations and attribute uses:
21008 * - the type definition
21009 * - if an attribute use, then the attribute declaration
21010 * 4. attribute group references:
21011 * - the attribute group definition
21012 * 5. particles:
21013 * - the term of the particle (e.g. a model group)
21014 * 6. IDC key-references:
21015 * - the referenced IDC 'key' or 'unique' definition
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021016 * 7. Attribute prohibitions which had a "ref" attribute.
Daniel Veillarddee23482008-04-11 12:58:43 +000021017 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021018 for (i = 0; i < nbItems; i++) {
21019 item = items[i];
21020 switch (item->type) {
21021 case XML_SCHEMA_TYPE_ELEMENT:
21022 xmlSchemaResolveElementReferences(
21023 (xmlSchemaElementPtr) item, pctxt);
21024 FIXHFAILURE;
21025 break;
21026 case XML_SCHEMA_TYPE_COMPLEX:
21027 case XML_SCHEMA_TYPE_SIMPLE:
21028 xmlSchemaResolveTypeReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021029 (xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021030 FIXHFAILURE;
21031 break;
21032 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021033 xmlSchemaResolveAttrTypeReferences(
21034 (xmlSchemaAttributePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021035 FIXHFAILURE;
21036 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021037 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21038 xmlSchemaResolveAttrUseReferences(
21039 (xmlSchemaAttributeUsePtr) item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021040 FIXHFAILURE;
21041 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021042 case XML_SCHEMA_EXTRA_QNAMEREF:
Daniel Veillarddee23482008-04-11 12:58:43 +000021043 if ((WXS_QNAME_CAST item)->itemType ==
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021044 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21045 {
21046 xmlSchemaResolveAttrGroupReferences(
21047 WXS_QNAME_CAST item, pctxt);
21048 }
21049 FIXHFAILURE;
21050 break;
21051 case XML_SCHEMA_TYPE_SEQUENCE:
21052 case XML_SCHEMA_TYPE_CHOICE:
21053 case XML_SCHEMA_TYPE_ALL:
21054 xmlSchemaResolveModelGroupParticleReferences(pctxt,
21055 WXS_MODEL_GROUP_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021056 FIXHFAILURE;
21057 break;
21058 case XML_SCHEMA_TYPE_IDC_KEY:
21059 case XML_SCHEMA_TYPE_IDC_UNIQUE:
21060 case XML_SCHEMA_TYPE_IDC_KEYREF:
21061 xmlSchemaResolveIDCKeyReferences(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021062 (xmlSchemaIDCPtr) item, pctxt);
21063 FIXHFAILURE;
21064 break;
21065 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21066 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021067 * Handle attribute prohibition which had a
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021068 * "ref" attribute.
21069 */
21070 xmlSchemaResolveAttrUseProhibReferences(
21071 WXS_ATTR_PROHIB_CAST item, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021072 FIXHFAILURE;
21073 break;
21074 default:
21075 break;
21076 }
21077 }
21078 if (pctxt->nberrors != 0)
21079 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021080
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021081 /*
21082 * Now that all references are resolved we
21083 * can check for circularity of...
Daniel Veillarddee23482008-04-11 12:58:43 +000021084 * 1. the base axis of type definitions
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021085 * 2. nested model group definitions
21086 * 3. nested attribute group definitions
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021087 * TODO: check for circular substitution groups.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021088 */
21089 for (i = 0; i < nbItems; i++) {
21090 item = items[i];
21091 /*
21092 * Let's better stop on the first error here.
21093 */
21094 switch (item->type) {
21095 case XML_SCHEMA_TYPE_COMPLEX:
21096 case XML_SCHEMA_TYPE_SIMPLE:
21097 xmlSchemaCheckTypeDefCircular(
21098 (xmlSchemaTypePtr) item, pctxt);
21099 FIXHFAILURE;
21100 if (pctxt->nberrors != 0)
21101 goto exit_error;
21102 break;
21103 case XML_SCHEMA_TYPE_GROUP:
21104 xmlSchemaCheckGroupDefCircular(
21105 (xmlSchemaModelGroupDefPtr) item, pctxt);
21106 FIXHFAILURE;
21107 if (pctxt->nberrors != 0)
21108 goto exit_error;
21109 break;
21110 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21111 xmlSchemaCheckAttrGroupCircular(
21112 (xmlSchemaAttributeGroupPtr) item, pctxt);
21113 FIXHFAILURE;
21114 if (pctxt->nberrors != 0)
21115 goto exit_error;
21116 break;
21117 default:
21118 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000021119 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021120 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021121 if (pctxt->nberrors != 0)
21122 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021123 /*
21124 * Model group definition references:
21125 * Such a reference is reflected by a particle at the component
21126 * level. Until now the 'term' of such particles pointed
21127 * to the model group definition; this was done, in order to
21128 * ease circularity checks. Now we need to set the 'term' of
21129 * such particles to the model group of the model group definition.
21130 */
21131 for (i = 0; i < nbItems; i++) {
21132 item = items[i];
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021133 switch (item->type) {
21134 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillarddee23482008-04-11 12:58:43 +000021135 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021136 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21137 WXS_MODEL_GROUP_CAST item);
21138 break;
21139 default:
21140 break;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021141 }
21142 }
21143 if (pctxt->nberrors != 0)
21144 goto exit_error;
21145 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021146 * Expand attribute group references of attribute group definitions.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021147 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021148 for (i = 0; i < nbItems; i++) {
21149 item = items[i];
21150 switch (item->type) {
21151 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21152 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21153 WXS_ATTR_GROUP_HAS_REFS(item))
21154 {
21155 xmlSchemaAttributeGroupExpandRefs(pctxt,
21156 WXS_ATTR_GROUP_CAST item);
21157 FIXHFAILURE;
21158 }
21159 break;
21160 default:
21161 break;
21162 }
21163 }
21164 if (pctxt->nberrors != 0)
21165 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021166 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021167 * First compute the variety of simple types. This is needed as
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021168 * a separate step, since otherwise we won't be able to detect
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021169 * circular union types in all cases.
21170 */
21171 for (i = 0; i < nbItems; i++) {
21172 item = items[i];
21173 switch (item->type) {
21174 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021175 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021176 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21177 (xmlSchemaTypePtr) item);
21178 FIXHFAILURE;
21179 }
21180 break;
21181 default:
21182 break;
21183 }
21184 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021185 if (pctxt->nberrors != 0)
21186 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021187 /*
21188 * Detect circular union types. Note that this needs the variety to
21189 * be already computed.
21190 */
21191 for (i = 0; i < nbItems; i++) {
21192 item = items[i];
21193 switch (item->type) {
21194 case XML_SCHEMA_TYPE_SIMPLE:
21195 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021196 xmlSchemaCheckUnionTypeDefCircular(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021197 (xmlSchemaTypePtr) item);
21198 FIXHFAILURE;
21199 }
21200 break;
21201 default:
21202 break;
21203 }
21204 }
21205 if (pctxt->nberrors != 0)
21206 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021207
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021208 /*
21209 * Do the complete type fixup for simple types.
21210 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021211 for (i = 0; i < nbItems; i++) {
21212 item = items[i];
21213 switch (item->type) {
21214 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021215 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21216 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21217 FIXHFAILURE;
21218 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021219 break;
21220 default:
21221 break;
21222 }
21223 }
21224 if (pctxt->nberrors != 0)
21225 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021226 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021227 * At this point we need build and check all simple types.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021228 */
21229 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021230 * Apply constraints for attribute declarations.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021231 */
21232 for (i = 0; i < nbItems; i++) {
21233 item = items[i];
21234 switch (item->type) {
Daniel Veillarddee23482008-04-11 12:58:43 +000021235 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021236 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21237 FIXHFAILURE;
Daniel Veillarddee23482008-04-11 12:58:43 +000021238 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021239 default:
21240 break;
21241 }
21242 }
21243 if (pctxt->nberrors != 0)
21244 goto exit_error;
21245 /*
21246 * Apply constraints for attribute uses.
Daniel Veillarddee23482008-04-11 12:58:43 +000021247 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021248 for (i = 0; i < nbItems; i++) {
21249 item = items[i];
21250 switch (item->type) {
21251 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21252 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21253 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21254 WXS_ATTR_USE_CAST item);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021255 FIXHFAILURE;
21256 }
21257 break;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021258 default:
21259 break;
21260 }
21261 }
21262 if (pctxt->nberrors != 0)
21263 goto exit_error;
21264
21265 /*
21266 * Apply constraints for attribute group definitions.
21267 */
21268 for (i = 0; i < nbItems; i++) {
21269 item = items[i];
21270 switch (item->type) {
21271 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21272 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21273 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21274 {
21275 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21276 FIXHFAILURE;
21277 }
21278 break;
21279 default:
21280 break;
21281 }
21282 }
21283 if (pctxt->nberrors != 0)
21284 goto exit_error;
21285
21286 /*
21287 * Apply constraints for redefinitions.
21288 */
21289 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21290 xmlSchemaCheckSRCRedefineSecond(pctxt);
21291 if (pctxt->nberrors != 0)
21292 goto exit_error;
21293
Daniel Veillarddee23482008-04-11 12:58:43 +000021294 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021295 * Complex types are built and checked.
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021296 */
21297 for (i = 0; i < nbItems; i++) {
21298 item = con->pending->items[i];
21299 switch (item->type) {
21300 case XML_SCHEMA_TYPE_COMPLEX:
21301 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21302 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21303 FIXHFAILURE;
21304 }
21305 break;
21306 default:
21307 break;
21308 }
21309 }
21310 if (pctxt->nberrors != 0)
21311 goto exit_error;
21312
21313 /*
21314 * The list could have changed, since xmlSchemaFixupComplexType()
21315 * will create particles and model groups in some cases.
21316 */
21317 items = (xmlSchemaTreeItemPtr *) con->pending->items;
Daniel Veillarddee23482008-04-11 12:58:43 +000021318 nbItems = con->pending->nbItems;
21319
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021320 /*
21321 * Apply some constraints for element declarations.
21322 */
21323 for (i = 0; i < nbItems; i++) {
21324 item = items[i];
21325 switch (item->type) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021326 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021327 elemDecl = (xmlSchemaElementPtr) item;
Daniel Veillarddee23482008-04-11 12:58:43 +000021328
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021329 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21330 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021331 xmlSchemaCheckElementDeclComponent(
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021332 (xmlSchemaElementPtr) elemDecl, pctxt);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021333 FIXHFAILURE;
21334 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000021335
21336#ifdef WXS_ELEM_DECL_CONS_ENABLED
21337 /*
21338 * Schema Component Constraint: Element Declarations Consistent
21339 * Apply this constraint to local types of element declarations.
21340 */
21341 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21342 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21343 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21344 {
21345 xmlSchemaCheckElementDeclConsistent(pctxt,
21346 WXS_BASIC_CAST elemDecl,
21347 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21348 NULL, NULL, 0);
21349 }
21350#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021351 break;
21352 default:
21353 break;
21354 }
21355 }
21356 if (pctxt->nberrors != 0)
21357 goto exit_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000021358
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021359 /*
21360 * Finally we can build the automaton from the content model of
21361 * complex types.
21362 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021363
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021364 for (i = 0; i < nbItems; i++) {
21365 item = items[i];
21366 switch (item->type) {
21367 case XML_SCHEMA_TYPE_COMPLEX:
21368 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021369 /* FIXHFAILURE; */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021370 break;
21371 default:
21372 break;
21373 }
21374 }
21375 if (pctxt->nberrors != 0)
21376 goto exit_error;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021377 /*
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021378 * URGENT TODO: cos-element-consistent
Daniel Veillarddee23482008-04-11 12:58:43 +000021379 */
21380 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021381
Daniel Veillarddee23482008-04-11 12:58:43 +000021382exit_error:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021383 ret = pctxt->err;
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021384 goto exit;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021385
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021386exit_failure:
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021387 ret = -1;
21388
21389exit:
21390 /*
21391 * Reset the constructor. This is needed for XSI acquisition, since
21392 * those items will be processed over and over again for every XSI
21393 * if not cleared here.
21394 */
Kasimier T. Buchcik4c0aa162006-02-20 14:47:08 +000021395 con->bucket = oldbucket;
Daniel Veillarddee23482008-04-11 12:58:43 +000021396 con->pending->nbItems = 0;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021397 if (con->substGroups != NULL) {
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010021398 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021399 con->substGroups = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000021400 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021401 if (con->redefs != NULL) {
21402 xmlSchemaRedefListFree(con->redefs);
21403 con->redefs = NULL;
21404 }
21405 return(ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021406}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021407/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021408 * xmlSchemaParse:
21409 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021410 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021411 * parse a schema definition resource and build an internal
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021412 * XML Schema structure which can be used to validate instances.
Daniel Veillard4255d502002-04-16 15:50:10 +000021413 *
21414 * Returns the internal XML Schema structure built from the resource or
21415 * NULL in case of error
21416 */
21417xmlSchemaPtr
21418xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21419{
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021420 xmlSchemaPtr mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021421 xmlSchemaBucketPtr bucket = NULL;
21422 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000021423
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021424 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021425 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021426 * the API; i.e. not automatically by the validated instance document.
21427 */
21428
Daniel Veillard4255d502002-04-16 15:50:10 +000021429 xmlSchemaInitTypes();
21430
Daniel Veillard6045c902002-10-09 21:13:59 +000021431 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000021432 return (NULL);
21433
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021434 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021435 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021436 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021437 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021438
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021439 /* Create the *main* schema. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021440 mainSchema = xmlSchemaNewSchema(ctxt);
21441 if (mainSchema == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021442 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000021443 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021444 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021445 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021446 if (ctxt->constructor == NULL) {
21447 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21448 if (ctxt->constructor == NULL)
21449 return(NULL);
21450 /* Take ownership of the constructor to be able to free it. */
21451 ctxt->ownsConstructor = 1;
21452 }
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021453 ctxt->constructor->mainSchema = mainSchema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021454 /*
21455 * Locate and add the schema document.
21456 */
21457 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21458 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21459 NULL, NULL, &bucket);
21460 if (res == -1)
21461 goto exit_failure;
21462 if (res != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021463 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021464
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021465 if (bucket == NULL) {
21466 /* TODO: Error code, actually we failed to *locate* the schema. */
Daniel Veillarddee23482008-04-11 12:58:43 +000021467 if (ctxt->URL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021468 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21469 NULL, NULL,
21470 "Failed to locate the main schema resource at '%s'",
21471 ctxt->URL, NULL);
21472 else
21473 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21474 NULL, NULL,
21475 "Failed to locate the main schema resource",
21476 NULL, NULL);
21477 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021478 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021479 /* Then do the parsing for good. */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021480 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021481 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000021482 if (ctxt->nberrors != 0)
21483 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000021484
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021485 mainSchema->doc = bucket->doc;
21486 mainSchema->preserve = ctxt->preserve;
Daniel Veillarddee23482008-04-11 12:58:43 +000021487
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021488 ctxt->schema = mainSchema;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021489
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021490 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021491 goto exit_failure;
21492
21493 /*
21494 * TODO: This is not nice, since we cannot distinguish from the
21495 * result if there was an internal error or not.
21496 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021497exit:
21498 if (ctxt->nberrors != 0) {
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021499 if (mainSchema) {
21500 xmlSchemaFree(mainSchema);
21501 mainSchema = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021502 }
21503 if (ctxt->constructor) {
21504 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21505 ctxt->constructor = NULL;
21506 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021507 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021508 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021509 ctxt->schema = NULL;
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021510 return(mainSchema);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021511exit_failure:
Daniel Veillarddee23482008-04-11 12:58:43 +000021512 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021513 * Quite verbose, but should catch internal errors, which were
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021514 * not communicated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021515 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021516 if (mainSchema) {
21517 xmlSchemaFree(mainSchema);
21518 mainSchema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021519 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021520 if (ctxt->constructor) {
21521 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21522 ctxt->constructor = NULL;
21523 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000021524 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021525 PERROR_INT2("xmlSchemaParse",
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020021526 "An internal error occurred");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021527 ctxt->schema = NULL;
21528 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000021529}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021530
Daniel Veillard4255d502002-04-16 15:50:10 +000021531/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000021532 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000021533 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000021534 * @err: the error callback
21535 * @warn: the warning callback
21536 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000021537 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000021538 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021539 */
21540void
21541xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021542 xmlSchemaValidityErrorFunc err,
21543 xmlSchemaValidityWarningFunc warn, void *ctx)
21544{
Daniel Veillard4255d502002-04-16 15:50:10 +000021545 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021546 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021547 ctxt->error = err;
21548 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021549 ctxt->errCtxt = ctx;
21550 if (ctxt->vctxt != NULL)
21551 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21552}
21553
21554/**
21555 * xmlSchemaSetParserStructuredErrors:
21556 * @ctxt: a schema parser context
21557 * @serror: the structured error function
21558 * @ctx: the functions context
21559 *
21560 * Set the structured error callback
21561 */
21562void
21563xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21564 xmlStructuredErrorFunc serror,
21565 void *ctx)
21566{
21567 if (ctxt == NULL)
21568 return;
21569 ctxt->serror = serror;
21570 ctxt->errCtxt = ctx;
21571 if (ctxt->vctxt != NULL)
21572 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021573}
21574
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021575/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021576 * xmlSchemaGetParserErrors:
21577 * @ctxt: a XMl-Schema parser context
21578 * @err: the error callback result
21579 * @warn: the warning callback result
21580 * @ctx: contextual data for the callbacks result
21581 *
21582 * Get the callback information used to handle errors for a parser context
21583 *
21584 * Returns -1 in case of failure, 0 otherwise
21585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021586int
Daniel Veillard259f0df2004-08-18 09:13:18 +000021587xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021588 xmlSchemaValidityErrorFunc * err,
21589 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000021590{
21591 if (ctxt == NULL)
21592 return(-1);
21593 if (err != NULL)
21594 *err = ctxt->error;
21595 if (warn != NULL)
21596 *warn = ctxt->warning;
21597 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000021598 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000021599 return(0);
21600}
21601
21602/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021603 * xmlSchemaFacetTypeToString:
21604 * @type: the facet type
21605 *
21606 * Convert the xmlSchemaTypeType to a char string.
21607 *
21608 * Returns the char string representation of the facet type if the
21609 * type is a facet and an "Internal Error" string otherwise.
21610 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021611static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021612xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21613{
21614 switch (type) {
21615 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021616 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021617 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021618 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021619 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021620 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021621 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021622 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021623 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021624 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021625 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021626 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021627 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021628 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021629 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021630 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021631 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021632 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021633 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021634 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021635 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021636 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021637 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021638 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021639 default:
21640 break;
21641 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021642 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021643}
21644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021645static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000021646xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21647{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021648 /*
21649 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000021650 * from xsd:string.
21651 */
21652 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021653 /*
21654 * Note that we assume a whitespace of preserve for anySimpleType.
21655 */
21656 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21657 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21658 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000021659 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021660 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021661 else {
21662 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010021663 * For all `atomic` datatypes other than string (and types `derived`
21664 * by `restriction` from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000021665 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021666 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021667 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021668 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021669 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021670 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021671 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021672 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021673 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021674 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021675 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021676 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021677 } else if (WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021678 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21679 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21680 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21681 return (XML_SCHEMA_WHITESPACE_REPLACE);
21682 else
21683 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021685 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000021686}
21687
Daniel Veillard4255d502002-04-16 15:50:10 +000021688/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021689 * *
21690 * Simple type validation *
21691 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021692 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000021693
Daniel Veillard4255d502002-04-16 15:50:10 +000021694
21695/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080021696 * *
21697 * DOM Validation code *
21698 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000021699 ************************************************************************/
21700
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021701/**
21702 * xmlSchemaAssembleByLocation:
21703 * @pctxt: a schema parser context
21704 * @vctxt: a schema validation context
21705 * @schema: the existing schema
21706 * @node: the node that fired the assembling
21707 * @nsName: the namespace name of the new schema
21708 * @location: the location of the schema
21709 *
21710 * Expands an existing schema by an additional schema.
21711 *
21712 * Returns 0 if the new schema is correct, a positive error code
21713 * number otherwise and -1 in case of an internal or API error.
21714 */
21715static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021716xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021717 xmlSchemaPtr schema,
21718 xmlNodePtr node,
21719 const xmlChar *nsName,
21720 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021721{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021722 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021723 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021724 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021725
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021726 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021727 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021728
21729 if (vctxt->pctxt == NULL) {
21730 VERROR_INT("xmlSchemaAssembleByLocation",
21731 "no parser context available");
21732 return(-1);
21733 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021734 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021735 if (pctxt->constructor == NULL) {
21736 PERROR_INT("xmlSchemaAssembleByLocation",
21737 "no constructor");
21738 return(-1);
21739 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021740 /*
21741 * Acquire the schema document.
21742 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021743 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21744 location, node);
21745 /*
21746 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21747 * the process will automatically change this to
21748 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21749 */
21750 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
Daniel Veillarddee23482008-04-11 12:58:43 +000021751 location, NULL, NULL, 0, node, NULL, nsName,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021752 &bucket);
21753 if (ret != 0)
Daniel Veillarddee23482008-04-11 12:58:43 +000021754 return(ret);
21755 if (bucket == NULL) {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021756 /*
21757 * Generate a warning that the document could not be located.
21758 */
21759 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760 node, NULL,
21761 "The document at location '%s' could not be acquired",
21762 location, NULL, NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021763 return(ret);
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021764 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021765 /*
21766 * The first located schema will be handled as if all other
21767 * schemas imported by XSI were imported by this first schema.
21768 */
21769 if ((bucket != NULL) &&
21770 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21771 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21772 /*
21773 * TODO: Is this handled like an import? I.e. is it not an error
21774 * if the schema cannot be located?
21775 */
21776 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21777 return(0);
21778 /*
21779 * We will reuse the parser context for every schema imported
21780 * directly via XSI. So reset the context.
21781 */
21782 pctxt->nberrors = 0;
21783 pctxt->err = 0;
21784 pctxt->doc = bucket->doc;
Daniel Veillarddee23482008-04-11 12:58:43 +000021785
21786 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021787 if (ret == -1) {
21788 pctxt->doc = NULL;
21789 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021790 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021791 /* Paranoid error channelling. */
21792 if ((ret == 0) && (pctxt->nberrors != 0))
Daniel Veillarddee23482008-04-11 12:58:43 +000021793 ret = pctxt->err;
21794 if (pctxt->nberrors == 0) {
21795 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021796 * Only bother to fixup pending components, if there was
21797 * no error yet.
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021798 * For every XSI acquired schema (and its sub-schemata) we will
21799 * fixup the components.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021800 */
Kasimier T. Buchcik1869be52006-02-20 13:37:55 +000021801 xmlSchemaFixupComponents(pctxt, bucket);
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000021802 ret = pctxt->err;
21803 /*
21804 * Not nice, but we need somehow to channel the schema parser
21805 * error to the validation context.
21806 */
21807 if ((ret != 0) && (vctxt->err == 0))
21808 vctxt->err = ret;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021809 vctxt->nberrors += pctxt->nberrors;
21810 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000021811 /* Add to validation error sum. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021812 vctxt->nberrors += pctxt->nberrors;
21813 }
21814 pctxt->doc = NULL;
21815 return(ret);
21816exit_failure:
21817 pctxt->doc = NULL;
21818 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021819}
21820
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021821static xmlSchemaAttrInfoPtr
Daniel Veillarddee23482008-04-11 12:58:43 +000021822xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021823 int metaType)
21824{
21825 if (vctxt->nbAttrInfos == 0)
21826 return (NULL);
21827 {
21828 int i;
21829 xmlSchemaAttrInfoPtr iattr;
21830
21831 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21832 iattr = vctxt->attrInfos[i];
21833 if (iattr->metaType == metaType)
21834 return (iattr);
21835 }
21836
21837 }
21838 return (NULL);
21839}
21840
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021841/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021842 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021843 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021844 *
21845 * Expands an existing schema by an additional schema using
21846 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21847 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21848 * must be set to 1.
21849 *
21850 * Returns 0 if the new schema is correct, a positive error code
21851 * number otherwise and -1 in case of an internal or API error.
21852 */
21853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021854xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021855{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021856 const xmlChar *cur, *end;
21857 const xmlChar *nsname = NULL, *location;
21858 int count = 0;
21859 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021860 xmlSchemaAttrInfoPtr iattr;
21861
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021862 /*
21863 * Parse the value; we will assume an even number of values
21864 * to be given (this is how Xerces and XSV work).
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000021865 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000021866 * URGENT TODO: !! This needs to work for both
21867 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21868 * element !!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021869 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021870 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21871 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21872 if (iattr == NULL)
Kasimier T. Buchcik81755ea2005-11-23 16:39:27 +000021873 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021874 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21875 if (iattr == NULL)
21876 return (0);
21877 cur = iattr->value;
21878 do {
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021879 /*
21880 * TODO: Move the string parsing mechanism away from here.
21881 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021882 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021883 /*
21884 * Get the namespace name.
21885 */
21886 while (IS_BLANK_CH(*cur))
21887 cur++;
21888 end = cur;
21889 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21890 end++;
21891 if (end == cur)
21892 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021893 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021894 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021895 cur = end;
21896 }
21897 /*
21898 * Get the URI.
21899 */
21900 while (IS_BLANK_CH(*cur))
21901 cur++;
21902 end = cur;
21903 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21904 end++;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021905 if (end == cur) {
21906 if (iattr->metaType ==
21907 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21908 {
21909 /*
21910 * If using @schemaLocation then tuples are expected.
21911 * I.e. the namespace name *and* the document's URI.
Daniel Veillarddee23482008-04-11 12:58:43 +000021912 */
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021913 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21914 iattr->node, NULL,
21915 "The value must consist of tuples: the target namespace "
21916 "name and the document's URI", NULL, NULL, NULL);
21917 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021918 break;
Kasimier T. Buchcike5f810f2006-05-30 09:41:25 +000021919 }
21920 count++; /* TODO: Don't use the schema's dict. */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021921 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021922 cur = end;
21923 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21924 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021925 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021926 VERROR_INT("xmlSchemaAssembleByXSI",
21927 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021928 return (-1);
21929 }
21930 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021931 return (ret);
21932}
21933
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021934static const xmlChar *
21935xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21936 const xmlChar *prefix)
21937{
21938 if (vctxt->sax != NULL) {
21939 int i, j;
21940 xmlSchemaNodeInfoPtr inode;
Daniel Veillarddee23482008-04-11 12:58:43 +000021941
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021942 for (i = vctxt->depth; i >= 0; i--) {
21943 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21944 inode = vctxt->elemInfos[i];
21945 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21946 if (((prefix == NULL) &&
21947 (inode->nsBindings[j] == NULL)) ||
21948 ((prefix != NULL) && xmlStrEqual(prefix,
21949 inode->nsBindings[j]))) {
21950
21951 /*
21952 * Note that the namespace bindings are already
21953 * in a string dict.
21954 */
Daniel Veillarddee23482008-04-11 12:58:43 +000021955 return (inode->nsBindings[j+1]);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021956 }
21957 }
21958 }
21959 }
21960 return (NULL);
Daniel Veillard438ebbd2008-05-12 12:58:46 +000021961#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021962 } else if (vctxt->reader != NULL) {
21963 xmlChar *nsName;
Daniel Veillarddee23482008-04-11 12:58:43 +000021964
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021965 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21966 if (nsName != NULL) {
21967 const xmlChar *ret;
21968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021969 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21970 xmlFree(nsName);
21971 return (ret);
21972 } else
21973 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000021974#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021975 } else {
21976 xmlNsPtr ns;
21977
21978 if ((vctxt->inode->node == NULL) ||
21979 (vctxt->inode->node->doc == NULL)) {
21980 VERROR_INT("xmlSchemaLookupNamespace",
Haibo Huangcfd91dc2020-07-30 23:01:33 -070021981 "no node or node's doc available");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021982 return (NULL);
21983 }
21984 ns = xmlSearchNs(vctxt->inode->node->doc,
21985 vctxt->inode->node, prefix);
21986 if (ns != NULL)
21987 return (ns->href);
21988 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021989 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021990}
21991
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021992/*
21993* This one works on the schema of the validation context.
21994*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021995static int
Daniel Veillarddee23482008-04-11 12:58:43 +000021996xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021997 xmlSchemaPtr schema,
21998 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000021999 const xmlChar *value,
22000 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022001 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022002{
22003 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022004
22005 if (vctxt && (vctxt->schema == NULL)) {
22006 VERROR_INT("xmlSchemaValidateNotation",
22007 "a schema is needed on the validation context");
22008 return (-1);
22009 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022010 ret = xmlValidateQName(value, 1);
22011 if (ret != 0)
22012 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022013 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022014 xmlChar *localName = NULL;
22015 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022016
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022017 localName = xmlSplitQName2(value, &prefix);
22018 if (prefix != NULL) {
22019 const xmlChar *nsName = NULL;
22020
Daniel Veillarddee23482008-04-11 12:58:43 +000022021 if (vctxt != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022022 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22023 else if (node != NULL) {
22024 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22025 if (ns != NULL)
22026 nsName = ns->href;
22027 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022028 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022029 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022030 return (1);
22031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022032 if (nsName == NULL) {
22033 xmlFree(prefix);
22034 xmlFree(localName);
22035 return (1);
22036 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022037 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Daniel Veillard77fbc3e2008-03-24 14:06:19 +000022038 if ((valNeeded) && (val != NULL)) {
22039 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22040 xmlStrdup(nsName));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022041 if (*val == NULL)
22042 ret = -1;
22043 }
22044 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000022045 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022046 xmlFree(prefix);
22047 xmlFree(localName);
22048 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022049 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022050 if (valNeeded && (val != NULL)) {
22051 (*val) = xmlSchemaNewNOTATIONValue(
22052 BAD_CAST xmlStrdup(value), NULL);
22053 if (*val == NULL)
22054 ret = -1;
22055 }
22056 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022057 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022058 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022059 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022060 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022061}
22062
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000022063static int
22064xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22065 const xmlChar* lname,
22066 const xmlChar* nsname)
22067{
22068 int i;
22069
22070 lname = xmlDictLookup(vctxt->dict, lname, -1);
22071 if (lname == NULL)
22072 return(-1);
22073 if (nsname != NULL) {
22074 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22075 if (nsname == NULL)
22076 return(-1);
22077 }
22078 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22079 if ((vctxt->nodeQNames->items [i] == lname) &&
22080 (vctxt->nodeQNames->items[i +1] == nsname))
22081 /* Already there */
22082 return(i);
22083 }
22084 /* Add new entry. */
22085 i = vctxt->nodeQNames->nbItems;
22086 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22087 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22088 return(i);
22089}
22090
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022091/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080022092 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022093 * Validation of identity-constraints (IDC) *
Daniel Veillardf8e3db02012-09-11 13:26:36 +080022094 * *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022095 ************************************************************************/
22096
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022097/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022098 * xmlSchemaAugmentIDC:
22099 * @idcDef: the IDC definition
22100 *
22101 * Creates an augmented IDC definition item.
22102 *
22103 * Returns the item, or NULL on internal errors.
22104 */
22105static void
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010022106xmlSchemaAugmentIDC(void *payload, void *data,
22107 const xmlChar *name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022108{
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010022109 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22110 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022111 xmlSchemaIDCAugPtr aidc;
22112
22113 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22114 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022115 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022116 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22117 NULL);
22118 return;
22119 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022120 aidc->keyrefDepth = -1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022121 aidc->def = idcDef;
22122 aidc->next = NULL;
22123 if (vctxt->aidcs == NULL)
22124 vctxt->aidcs = aidc;
22125 else {
22126 aidc->next = vctxt->aidcs;
22127 vctxt->aidcs = aidc;
22128 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022129 /*
22130 * Save if we have keyrefs at all.
22131 */
22132 if ((vctxt->hasKeyrefs == 0) &&
22133 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22134 vctxt->hasKeyrefs = 1;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022135}
22136
22137/**
Daniel Veillard3888f472007-08-23 09:29:03 +000022138 * xmlSchemaAugmentImportedIDC:
22139 * @imported: the imported schema
22140 *
22141 * Creates an augmented IDC definition for the imported schema.
22142 */
22143static void
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010022144xmlSchemaAugmentImportedIDC(void *payload, void *data,
22145 const xmlChar *name ATTRIBUTE_UNUSED) {
22146 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22147 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
Daniel Veillard3888f472007-08-23 09:29:03 +000022148 if (imported->schema->idcDef != NULL) {
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010022149 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
Daniel Veillard3888f472007-08-23 09:29:03 +000022150 }
22151}
22152
22153/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022154 * xmlSchemaIDCNewBinding:
22155 * @idcDef: the IDC definition of this binding
22156 *
22157 * Creates a new IDC binding.
22158 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022159 * Returns the new IDC binding, NULL on internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022160 */
22161static xmlSchemaPSVIIDCBindingPtr
22162xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22163{
22164 xmlSchemaPSVIIDCBindingPtr ret;
22165
22166 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22167 sizeof(xmlSchemaPSVIIDCBinding));
22168 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022169 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022170 "allocating a PSVI IDC binding item", NULL);
22171 return (NULL);
22172 }
22173 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22174 ret->definition = idcDef;
22175 return (ret);
22176}
22177
22178/**
22179 * xmlSchemaIDCStoreNodeTableItem:
22180 * @vctxt: the WXS validation context
22181 * @item: the IDC node table item
22182 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022183 * The validation context is used to store IDC node table items.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022184 * They are stored to avoid copying them if IDC node-tables are merged
22185 * with corresponding parent IDC node-tables (bubbling).
22186 *
22187 * Returns 0 if succeeded, -1 on internal errors.
22188 */
22189static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022190xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022191 xmlSchemaPSVIIDCNodePtr item)
22192{
22193 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070022194 * Add to global list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022195 */
22196 if (vctxt->idcNodes == NULL) {
22197 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022198 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22199 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022200 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022201 "allocating the IDC node table item list", NULL);
22202 return (-1);
22203 }
22204 vctxt->sizeIdcNodes = 20;
22205 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22206 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022207 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22208 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022209 sizeof(xmlSchemaPSVIIDCNodePtr));
22210 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022211 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022212 "re-allocating the IDC node table item list", NULL);
22213 return (-1);
22214 }
22215 }
22216 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022217
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022218 return (0);
22219}
22220
22221/**
22222 * xmlSchemaIDCStoreKey:
22223 * @vctxt: the WXS validation context
22224 * @item: the IDC key
22225 *
22226 * The validation context is used to store an IDC key.
22227 *
22228 * Returns 0 if succeeded, -1 on internal errors.
22229 */
22230static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022231xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022232 xmlSchemaPSVIIDCKeyPtr key)
22233{
22234 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070022235 * Add to global list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022236 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022237 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022238 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022239 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22240 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022241 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022242 "allocating the IDC key storage list", NULL);
22243 return (-1);
22244 }
22245 vctxt->sizeIdcKeys = 40;
22246 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22247 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022248 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22249 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022250 sizeof(xmlSchemaPSVIIDCKeyPtr));
22251 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022252 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022253 "re-allocating the IDC key storage list", NULL);
22254 return (-1);
22255 }
22256 }
22257 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022258
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022259 return (0);
22260}
22261
22262/**
22263 * xmlSchemaIDCAppendNodeTableItem:
22264 * @bind: the IDC binding
22265 * @ntItem: the node-table item
22266 *
22267 * Appends the IDC node-table item to the binding.
22268 *
22269 * Returns 0 on success and -1 on internal errors.
22270 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022271static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022272xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22273 xmlSchemaPSVIIDCNodePtr ntItem)
22274{
22275 if (bind->nodeTable == NULL) {
22276 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022277 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022278 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22279 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022280 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022281 "allocating an array of IDC node-table items", NULL);
22282 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022283 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022284 } else if (bind->sizeNodes <= bind->nbNodes) {
22285 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022286 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22287 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022288 sizeof(xmlSchemaPSVIIDCNodePtr));
22289 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022290 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022291 "re-allocating an array of IDC node-table items", NULL);
22292 return(-1);
22293 }
22294 }
22295 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022296 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022297}
22298
22299/**
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022300 * xmlSchemaIDCAcquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022301 * @vctxt: the WXS validation context
22302 * @matcher: the IDC matcher
22303 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022304 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022305 * of the given matcher. If none found, a new one is created
22306 * and added to the IDC table.
22307 *
22308 * Returns an IDC binding or NULL on internal errors.
22309 */
22310static xmlSchemaPSVIIDCBindingPtr
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022311xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022312 xmlSchemaIDCMatcherPtr matcher)
22313{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022314 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022315
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022316 ielem = vctxt->elemInfos[matcher->depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022317
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022318 if (ielem->idcTable == NULL) {
22319 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22320 if (ielem->idcTable == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022321 return (NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022322 return(ielem->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022323 } else {
22324 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022325
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022326 bind = ielem->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022327 do {
22328 if (bind->definition == matcher->aidc->def)
22329 return(bind);
22330 if (bind->next == NULL) {
22331 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22332 if (bind->next == NULL)
22333 return (NULL);
22334 return(bind->next);
22335 }
22336 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022337 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022338 }
22339 return (NULL);
22340}
22341
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022342static xmlSchemaItemListPtr
22343xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22344 xmlSchemaIDCMatcherPtr matcher)
22345{
22346 if (matcher->targets == NULL)
22347 matcher->targets = xmlSchemaItemListCreate();
22348 return(matcher->targets);
22349}
22350
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022351/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022352 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022353 * @key: the IDC key
22354 *
22355 * Frees an IDC key together with its compiled value.
22356 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022357static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022358xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22359{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022360 if (key->val != NULL)
22361 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022362 xmlFree(key);
22363}
22364
22365/**
22366 * xmlSchemaIDCFreeBinding:
22367 *
22368 * Frees an IDC binding. Note that the node table-items
22369 * are not freed.
22370 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022371static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022372xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22373{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022374 if (bind->nodeTable != NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022375 xmlFree(bind->nodeTable);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022376 if (bind->dupls != NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000022377 xmlSchemaItemListFree(bind->dupls);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022378 xmlFree(bind);
22379}
22380
22381/**
22382 * xmlSchemaIDCFreeIDCTable:
22383 * @bind: the first IDC binding in the list
22384 *
22385 * Frees an IDC table, i.e. all the IDC bindings in the list.
22386 */
22387static void
22388xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22389{
22390 xmlSchemaPSVIIDCBindingPtr prev;
22391
22392 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022393 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022394 bind = bind->next;
22395 xmlSchemaIDCFreeBinding(prev);
22396 }
22397}
22398
Haibo Huang3496e1e2020-11-30 18:17:15 -080022399static void
22400xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22401{
22402 xmlIDCHashEntryPtr e = payload, n;
22403 while (e) {
22404 n = e->next;
22405 xmlFree(e);
22406 e = n;
22407 }
22408}
22409
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022410/**
22411 * xmlSchemaIDCFreeMatcherList:
22412 * @matcher: the first IDC matcher in the list
22413 *
22414 * Frees a list of IDC matchers.
22415 */
22416static void
22417xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22418{
22419 xmlSchemaIDCMatcherPtr next;
22420
22421 while (matcher != NULL) {
22422 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022423 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022424 int i;
22425 for (i = 0; i < matcher->sizeKeySeqs; i++)
22426 if (matcher->keySeqs[i] != NULL)
22427 xmlFree(matcher->keySeqs[i]);
Daniel Veillarddee23482008-04-11 12:58:43 +000022428 xmlFree(matcher->keySeqs);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022429 }
22430 if (matcher->targets != NULL) {
22431 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22432 int i;
22433 xmlSchemaPSVIIDCNodePtr idcNode;
22434 /*
22435 * Node-table items for keyrefs are not stored globally
22436 * to the validation context, since they are not bubbled.
22437 * We need to free them here.
22438 */
22439 for (i = 0; i < matcher->targets->nbItems; i++) {
22440 idcNode =
22441 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22442 xmlFree(idcNode->keys);
22443 xmlFree(idcNode);
22444 }
22445 }
22446 xmlSchemaItemListFree(matcher->targets);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022447 }
Haibo Huang3496e1e2020-11-30 18:17:15 -080022448 if (matcher->htab != NULL)
22449 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022450 xmlFree(matcher);
22451 matcher = next;
22452 }
22453}
22454
22455/**
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022456 * xmlSchemaIDCReleaseMatcherList:
22457 * @vctxt: the WXS validation context
22458 * @matcher: the first IDC matcher in the list
22459 *
22460 * Caches a list of IDC matchers for reuse.
22461 */
22462static void
22463xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22464 xmlSchemaIDCMatcherPtr matcher)
22465{
22466 xmlSchemaIDCMatcherPtr next;
22467
22468 while (matcher != NULL) {
22469 next = matcher->next;
Daniel Veillarddee23482008-04-11 12:58:43 +000022470 if (matcher->keySeqs != NULL) {
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022471 int i;
22472 /*
22473 * Don't free the array, but only the content.
22474 */
22475 for (i = 0; i < matcher->sizeKeySeqs; i++)
22476 if (matcher->keySeqs[i] != NULL) {
22477 xmlFree(matcher->keySeqs[i]);
22478 matcher->keySeqs[i] = NULL;
22479 }
22480 }
22481 if (matcher->targets) {
22482 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22483 int i;
22484 xmlSchemaPSVIIDCNodePtr idcNode;
22485 /*
22486 * Node-table items for keyrefs are not stored globally
22487 * to the validation context, since they are not bubbled.
22488 * We need to free them here.
22489 */
22490 for (i = 0; i < matcher->targets->nbItems; i++) {
22491 idcNode =
22492 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22493 xmlFree(idcNode->keys);
22494 xmlFree(idcNode);
22495 }
22496 }
22497 xmlSchemaItemListFree(matcher->targets);
22498 matcher->targets = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022499 }
Haibo Huang3496e1e2020-11-30 18:17:15 -080022500 if (matcher->htab != NULL) {
22501 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22502 matcher->htab = NULL;
22503 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000022504 matcher->next = NULL;
22505 /*
22506 * Cache the matcher.
22507 */
22508 if (vctxt->idcMatcherCache != NULL)
22509 matcher->nextCached = vctxt->idcMatcherCache;
22510 vctxt->idcMatcherCache = matcher;
22511
22512 matcher = next;
22513 }
22514}
22515
22516/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022517 * xmlSchemaIDCAddStateObject:
22518 * @vctxt: the WXS validation context
22519 * @matcher: the IDC matcher
22520 * @sel: the XPath information
22521 * @parent: the parent "selector" state object if any
22522 * @type: "selector" or "field"
22523 *
22524 * Creates/reuses and activates state objects for the given
22525 * XPath information; if the XPath expression consists of unions,
22526 * multiple state objects are created for every unioned expression.
22527 *
22528 * Returns 0 on success and -1 on internal errors.
22529 */
22530static int
22531xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22532 xmlSchemaIDCMatcherPtr matcher,
22533 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022534 int type)
22535{
22536 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022537
22538 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022539 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022540 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022541 if (vctxt->xpathStatePool != NULL) {
22542 sto = vctxt->xpathStatePool;
22543 vctxt->xpathStatePool = sto->next;
22544 sto->next = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022545 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022546 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022547 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022548 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022549 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22550 if (sto == NULL) {
22551 xmlSchemaVErrMemory(NULL,
22552 "allocating an IDC state object", NULL);
22553 return (-1);
22554 }
22555 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
Daniel Veillarddee23482008-04-11 12:58:43 +000022556 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022557 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000022558 * Add to global list.
22559 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022560 if (vctxt->xpathStates != NULL)
22561 sto->next = vctxt->xpathStates;
22562 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022563
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022564 /*
22565 * Free the old xpath validation context.
22566 */
22567 if (sto->xpathCtxt != NULL)
22568 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22569
22570 /*
22571 * Create a new XPath (pattern) validation context.
22572 */
22573 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22574 (xmlPatternPtr) sel->xpathComp);
22575 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022576 VERROR_INT("xmlSchemaIDCAddStateObject",
22577 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022578 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000022579 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022580 sto->type = type;
22581 sto->depth = vctxt->depth;
22582 sto->matcher = matcher;
22583 sto->sel = sel;
22584 sto->nbHistory = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000022585
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022586#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022587 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22588 sto->sel->xpath);
22589#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022590 return (0);
22591}
22592
22593/**
22594 * xmlSchemaXPathEvaluate:
22595 * @vctxt: the WXS validation context
22596 * @nodeType: the nodeType of the current node
22597 *
22598 * Evaluates all active XPath state objects.
22599 *
22600 * Returns the number of IC "field" state objects which resolved to
22601 * this node, 0 if none resolved and -1 on internal errors.
22602 */
22603static int
22604xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022605 xmlElementType nodeType)
22606{
22607 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022608 int res, resolved = 0, depth = vctxt->depth;
Daniel Veillarddee23482008-04-11 12:58:43 +000022609
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022610 if (vctxt->xpathStates == NULL)
22611 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022612
22613 if (nodeType == XML_ATTRIBUTE_NODE)
22614 depth++;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022615#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022616 {
22617 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022618 xmlGenericError(xmlGenericErrorContext,
22619 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022620 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22621 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022622 FREE_AND_NULL(str)
22623 }
22624#endif
22625 /*
22626 * Process all active XPath state objects.
22627 */
22628 first = vctxt->xpathStates;
22629 sto = first;
22630 while (sto != head) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022631#ifdef DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022632 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Daniel Veillarddee23482008-04-11 12:58:43 +000022633 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022634 sto->matcher->aidc->def->name, sto->sel->xpath);
22635 else
Daniel Veillarddee23482008-04-11 12:58:43 +000022636 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022637 sto->matcher->aidc->def->name, sto->sel->xpath);
22638#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022639 if (nodeType == XML_ELEMENT_NODE)
22640 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022641 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022642 else
22643 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022644 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022645
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022646 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022647 VERROR_INT("xmlSchemaXPathEvaluate",
22648 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022649 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022650 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022651 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022652 goto next_sto;
22653 /*
22654 * Full match.
22655 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022656#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022657 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022658 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022659#endif
22660 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022661 * Register a match in the state object history.
22662 */
22663 if (sto->history == NULL) {
22664 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22665 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022666 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022667 "allocating the state object history", NULL);
22668 return(-1);
22669 }
Daniel Veillard6f9b0872006-08-12 14:09:01 +000022670 sto->sizeHistory = 5;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022671 } else if (sto->sizeHistory <= sto->nbHistory) {
22672 sto->sizeHistory *= 2;
22673 sto->history = (int *) xmlRealloc(sto->history,
22674 sto->sizeHistory * sizeof(int));
22675 if (sto->history == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022676 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022677 "re-allocating the state object history", NULL);
22678 return(-1);
22679 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022680 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022681 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022682
22683#ifdef DEBUG_IDC
22684 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22685 vctxt->depth);
22686#endif
22687
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022688 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22689 xmlSchemaIDCSelectPtr sel;
22690 /*
22691 * Activate state objects for the IDC fields of
22692 * the IDC selector.
22693 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022694#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022695 xmlGenericError(xmlGenericErrorContext, "IDC: "
22696 "activating field states\n");
22697#endif
22698 sel = sto->matcher->aidc->def->fields;
22699 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022700 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22701 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22702 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022703 sel = sel->next;
22704 }
22705 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22706 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022707 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022708 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022709#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022710 xmlGenericError(xmlGenericErrorContext,
22711 "IDC: key found\n");
22712#endif
22713 /*
22714 * Notify that the character value of this node is
22715 * needed.
22716 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022717 if (resolved == 0) {
22718 if ((vctxt->inode->flags &
22719 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22720 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22721 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022722 resolved++;
22723 }
22724next_sto:
22725 if (sto->next == NULL) {
22726 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022727 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022728 */
22729 head = first;
22730 sto = vctxt->xpathStates;
22731 } else
22732 sto = sto->next;
22733 }
22734 return (resolved);
22735}
22736
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022737static const xmlChar *
Haibo Huang3496e1e2020-11-30 18:17:15 -080022738xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22739 xmlChar **buf,
22740 xmlSchemaPSVIIDCKeyPtr *seq,
22741 int count, int for_hash)
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022742{
22743 int i, res;
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022744 xmlChar *value = NULL;
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022745
22746 *buf = xmlStrdup(BAD_CAST "[");
22747 for (i = 0; i < count; i++) {
22748 *buf = xmlStrcat(*buf, BAD_CAST "'");
Haibo Huang3496e1e2020-11-30 18:17:15 -080022749 if (!for_hash)
22750 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22751 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22752 &value);
22753 else {
22754 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22755 }
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022756 if (res == 0)
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022757 *buf = xmlStrcat(*buf, BAD_CAST value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022758 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022759 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22760 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022761 *buf = xmlStrcat(*buf, BAD_CAST "???");
22762 }
22763 if (i < count -1)
22764 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22765 else
22766 *buf = xmlStrcat(*buf, BAD_CAST "'");
22767 if (value != NULL) {
Kasimier T. Buchcik77e76822005-11-11 12:52:32 +000022768 xmlFree(value);
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000022769 value = NULL;
22770 }
22771 }
22772 *buf = xmlStrcat(*buf, BAD_CAST "]");
22773
22774 return (BAD_CAST *buf);
22775}
22776
Haibo Huang3496e1e2020-11-30 18:17:15 -080022777static const xmlChar *
22778xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22779 xmlChar **buf,
22780 xmlSchemaPSVIIDCKeyPtr *seq,
22781 int count)
22782{
22783 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22784}
22785
22786static const xmlChar *
22787xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22788 xmlChar **buf,
22789 xmlSchemaPSVIIDCKeyPtr *seq,
22790 int count)
22791{
22792 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22793}
22794
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022795/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022796 * xmlSchemaXPathPop:
22797 * @vctxt: the WXS validation context
22798 *
22799 * Pops all XPath states.
22800 *
22801 * Returns 0 on success and -1 on internal errors.
22802 */
22803static int
22804xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22805{
22806 xmlSchemaIDCStateObjPtr sto;
22807 int res;
22808
22809 if (vctxt->xpathStates == NULL)
22810 return(0);
22811 sto = vctxt->xpathStates;
22812 do {
22813 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22814 if (res == -1)
22815 return (-1);
22816 sto = sto->next;
22817 } while (sto != NULL);
22818 return(0);
22819}
22820
22821/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022822 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022823 * @vctxt: the WXS validation context
22824 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022825 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022826 *
22827 * Processes and pops the history items of the IDC state objects.
22828 * IDC key-sequences are validated/created on IDC bindings.
Daniel Veillarddee23482008-04-11 12:58:43 +000022829 *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022830 * Returns 0 on success and -1 on internal errors.
22831 */
22832static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022833xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022834 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022835{
22836 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022837 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022838 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022839 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022840
22841 if (vctxt->xpathStates == NULL)
22842 return (0);
22843 sto = vctxt->xpathStates;
22844
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022845#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022846 {
22847 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022848 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022849 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022850 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22851 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022852 FREE_AND_NULL(str)
22853 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022854#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022855 /*
22856 * Evaluate the state objects.
22857 */
22858 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000022859 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22860 if (res == -1) {
22861 VERROR_INT("xmlSchemaXPathProcessHistory",
22862 "calling xmlStreamPop()");
22863 return (-1);
22864 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022865#ifdef DEBUG_IDC
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022866 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22867 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022868#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022869 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022870 goto deregister_check;
22871
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022872 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022873
22874 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022875 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022876 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022877 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022878 sto = sto->next;
22879 continue;
Daniel Veillarddee23482008-04-11 12:58:43 +000022880 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022881 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022882 /*
22883 * NOTE: According to
22884 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22885 * ... the simple-content of complex types is also allowed.
22886 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022887
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022888 if (WXS_IS_COMPLEX(type)) {
22889 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22890 /*
22891 * Sanity check for complex types with simple content.
22892 */
22893 simpleType = type->contentTypeDef;
22894 if (simpleType == NULL) {
22895 VERROR_INT("xmlSchemaXPathProcessHistory",
22896 "field resolves to a CT with simple content "
22897 "but the CT is missing the ST definition");
22898 return (-1);
22899 }
22900 } else
22901 simpleType = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022902 } else
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022903 simpleType = type;
22904 if (simpleType == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022905 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000022906
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022907 /*
22908 * Not qualified if the field resolves to a node of non
22909 * simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000022910 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022911 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Daniel Veillarddee23482008-04-11 12:58:43 +000022912 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022913 WXS_BASIC_CAST sto->matcher->aidc->def,
22914 "The XPath '%s' of a field of %s does evaluate to a node of "
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022915 "non-simple type",
22916 sto->sel->xpath,
22917 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22918 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022919 sto->nbHistory--;
22920 goto deregister_check;
22921 }
Daniel Veillarddee23482008-04-11 12:58:43 +000022922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022923 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022924 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022925 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022926 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022927 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022928 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000022929 WXS_BASIC_CAST sto->matcher->aidc->def,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000022930 "Warning: No precomputed value available, the value "
Haibo Huangcfd91dc2020-07-30 23:01:33 -070022931 "was either invalid or something strange happened");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022932 sto->nbHistory--;
22933 goto deregister_check;
22934 } else {
22935 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22936 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022937 int pos, idx;
Daniel Veillarddee23482008-04-11 12:58:43 +000022938
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022939 /*
22940 * The key will be anchored on the matcher's list of
22941 * key-sequences. The position in this list is determined
22942 * by the target node's depth relative to the matcher's
22943 * depth of creation (i.e. the depth of the scope element).
Daniel Veillarddee23482008-04-11 12:58:43 +000022944 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022945 * Element Depth Pos List-entries
22946 * <scope> 0 NULL
22947 * <bar> 1 NULL
22948 * <target/> 2 2 target
22949 * <bar>
22950 * </scope>
22951 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070022952 * The size of the list is only dependent on the depth of
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000022953 * the tree.
22954 * An entry will be NULLed in selector_leave, i.e. when
Daniel Veillarddee23482008-04-11 12:58:43 +000022955 * we hit the target's
22956 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022957 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022958 idx = sto->sel->index;
Daniel Veillarddee23482008-04-11 12:58:43 +000022959
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022960 /*
22961 * Create/grow the array of key-sequences.
22962 */
22963 if (matcher->keySeqs == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000022964 if (pos > 9)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022965 matcher->sizeKeySeqs = pos * 2;
22966 else
22967 matcher->sizeKeySeqs = 10;
Daniel Veillarddee23482008-04-11 12:58:43 +000022968 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022969 xmlMalloc(matcher->sizeKeySeqs *
Daniel Veillarddee23482008-04-11 12:58:43 +000022970 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22971 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022972 xmlSchemaVErrMemory(NULL,
22973 "allocating an array of key-sequences",
22974 NULL);
22975 return(-1);
22976 }
22977 memset(matcher->keySeqs, 0,
22978 matcher->sizeKeySeqs *
22979 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Daniel Veillarddee23482008-04-11 12:58:43 +000022980 } else if (pos >= matcher->sizeKeySeqs) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022981 int i = matcher->sizeKeySeqs;
Daniel Veillarddee23482008-04-11 12:58:43 +000022982
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022983 matcher->sizeKeySeqs *= 2;
22984 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22985 xmlRealloc(matcher->keySeqs,
22986 matcher->sizeKeySeqs *
22987 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022988 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022989 xmlSchemaVErrMemory(NULL,
22990 "reallocating an array of key-sequences",
22991 NULL);
22992 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022993 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022994 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022995 * The array needs to be NULLed.
22996 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022997 */
Daniel Veillarddee23482008-04-11 12:58:43 +000022998 for (; i < matcher->sizeKeySeqs; i++)
22999 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023000 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023001
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023002 /*
23003 * Get/create the key-sequence.
23004 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023005 keySeq = matcher->keySeqs[pos];
23006 if (keySeq == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023007 goto create_sequence;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023008 } else if (keySeq[idx] != NULL) {
23009 xmlChar *str = NULL;
23010 /*
23011 * cvc-identity-constraint:
Jan Pokorný761c9e92013-11-29 23:26:27 +010023012 * 3 For each node in the `target node set` all
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023013 * of the {fields}, with that node as the context
23014 * node, evaluate to either an empty node-set or
23015 * a node-set with exactly one member, which must
23016 * have a simple type.
Daniel Veillarddee23482008-04-11 12:58:43 +000023017 *
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023018 * The key was already set; report an error.
23019 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023020 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023021 XML_SCHEMAV_CVC_IDC, NULL,
23022 WXS_BASIC_CAST matcher->aidc->def,
23023 "The XPath '%s' of a field of %s evaluates to a "
23024 "node-set with more than one member",
23025 sto->sel->xpath,
23026 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23027 FREE_AND_NULL(str);
23028 sto->nbHistory--;
23029 goto deregister_check;
23030 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000023031 goto create_key;
23032
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023033create_sequence:
23034 /*
23035 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023036 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023037 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
Daniel Veillarddee23482008-04-11 12:58:43 +000023038 matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023039 sizeof(xmlSchemaPSVIIDCKeyPtr));
23040 if (keySeq == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023041 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023042 "allocating an IDC key-sequence", NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000023043 return(-1);
23044 }
23045 memset(keySeq, 0, matcher->aidc->def->nbFields *
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023046 sizeof(xmlSchemaPSVIIDCKeyPtr));
23047 matcher->keySeqs[pos] = keySeq;
23048create_key:
23049 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023050 * Create a key once per node only.
Daniel Veillarddee23482008-04-11 12:58:43 +000023051 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023052 if (key == NULL) {
23053 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23054 sizeof(xmlSchemaPSVIIDCKey));
23055 if (key == NULL) {
23056 xmlSchemaVErrMemory(NULL,
23057 "allocating a IDC key", NULL);
23058 xmlFree(keySeq);
23059 matcher->keySeqs[pos] = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023060 return(-1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023061 }
23062 /*
23063 * Consume the compiled value.
23064 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023065 key->type = simpleType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023066 key->val = vctxt->inode->val;
23067 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023068 /*
23069 * Store the key in a global list.
23070 */
23071 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23072 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023073 return (-1);
23074 }
23075 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023076 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023077 }
23078 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023079
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023080 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023081 /* xmlSchemaPSVIIDCBindingPtr bind; */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023082 xmlSchemaPSVIIDCNodePtr ntItem;
23083 xmlSchemaIDCMatcherPtr matcher;
23084 xmlSchemaIDCPtr idc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023085 xmlSchemaItemListPtr targets;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023086 int pos, i, j, nbKeys;
23087 /*
23088 * Here we have the following scenario:
23089 * An IDC 'selector' state object resolved to a target node,
Daniel Veillarddee23482008-04-11 12:58:43 +000023090 * during the time this target node was in the
23091 * ancestor-or-self axis, the 'field' state object(s) looked
23092 * out for matching nodes to create a key-sequence for this
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023093 * target node. Now we are back to this target node and need
Daniel Veillarddee23482008-04-11 12:58:43 +000023094 * to put the key-sequence, together with the target node
23095 * itself, into the node-table of the corresponding IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023096 * binding.
23097 */
23098 matcher = sto->matcher;
23099 idc = matcher->aidc->def;
23100 nbKeys = idc->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000023101 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023102 /*
23103 * Check if the matcher has any key-sequences at all, plus
23104 * if it has a key-sequence for the current target node.
Daniel Veillarddee23482008-04-11 12:58:43 +000023105 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023106 if ((matcher->keySeqs == NULL) ||
23107 (matcher->sizeKeySeqs <= pos)) {
23108 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23109 goto selector_key_error;
23110 else
23111 goto selector_leave;
23112 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023113
23114 keySeq = &(matcher->keySeqs[pos]);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023115 if (*keySeq == NULL) {
23116 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23117 goto selector_key_error;
23118 else
23119 goto selector_leave;
23120 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023121
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023122 for (i = 0; i < nbKeys; i++) {
23123 if ((*keySeq)[i] == NULL) {
23124 /*
23125 * Not qualified, if not all fields did resolve.
23126 */
23127 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23128 /*
23129 * All fields of a "key" IDC must resolve.
23130 */
23131 goto selector_key_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023132 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023133 goto selector_leave;
23134 }
23135 }
23136 /*
23137 * All fields did resolve.
23138 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023139
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023140 /*
23141 * 4.1 If the {identity-constraint category} is unique(/key),
Jan Pokorný761c9e92013-11-29 23:26:27 +010023142 * then no two members of the `qualified node set` have
23143 * `key-sequences` whose members are pairwise equal, as
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023144 * defined by Equal in [XML Schemas: Datatypes].
23145 *
23146 * Get the IDC binding from the matcher and check for
23147 * duplicate key-sequences.
23148 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023149#if 0
23150 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23151#endif
23152 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
Daniel Veillarddee23482008-04-11 12:58:43 +000023153 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023154 (targets->nbItems != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023155 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Haibo Huang3496e1e2020-11-30 18:17:15 -080023156 xmlIDCHashEntryPtr e;
Daniel Veillarddee23482008-04-11 12:58:43 +000023157
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023158 res = 0;
Haibo Huang3496e1e2020-11-30 18:17:15 -080023159
23160 if (!matcher->htab)
23161 e = NULL;
23162 else {
23163 xmlChar *value = NULL;
23164 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23165 e = xmlHashLookup(matcher->htab, value);
23166 FREE_AND_NULL(value);
23167 }
23168
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023169 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023170 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023171 */
Haibo Huang3496e1e2020-11-30 18:17:15 -080023172 for (;e; e = e->next) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023173 bkeySeq =
Haibo Huang3496e1e2020-11-30 18:17:15 -080023174 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023175 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023176 ckey = (*keySeq)[j];
Daniel Veillarddee23482008-04-11 12:58:43 +000023177 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023178 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023179 if (res == -1) {
23180 return (-1);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023181 } else if (res == 0) {
23182 /*
23183 * One of the keys differs, so the key-sequence
23184 * won't be equal; get out.
23185 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023186 break;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023187 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023188 }
23189 if (res == 1) {
23190 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023191 * Duplicate key-sequence found.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023192 */
23193 break;
23194 }
Haibo Huang3496e1e2020-11-30 18:17:15 -080023195 }
23196 if (e) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023197 xmlChar *str = NULL, *strB = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023198 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023199 * TODO: Try to report the key-sequence.
23200 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023201 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023202 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023203 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023204 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000023205 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023206 (*keySeq), nbKeys),
23207 xmlSchemaGetIDCDesignation(&strB, idc));
23208 FREE_AND_NULL(str);
23209 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023210 goto selector_leave;
23211 }
23212 }
23213 /*
23214 * Add a node-table item to the IDC binding.
23215 */
23216 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23217 sizeof(xmlSchemaPSVIIDCNode));
23218 if (ntItem == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023219 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023220 "allocating an IDC node-table item", NULL);
23221 xmlFree(*keySeq);
23222 *keySeq = NULL;
23223 return(-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023224 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023225 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Daniel Veillarddee23482008-04-11 12:58:43 +000023226
23227 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023228 * Store the node-table item in a global list.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023229 */
23230 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23231 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23232 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023233 xmlFree(*keySeq);
23234 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023235 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023236 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023237 ntItem->nodeQNameID = -1;
23238 } else {
23239 /*
23240 * Save a cached QName for this node on the IDC node, to be
23241 * able to report it, even if the node is not saved.
23242 */
23243 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23244 vctxt->inode->localName, vctxt->inode->nsName);
23245 if (ntItem->nodeQNameID == -1) {
23246 xmlFree(ntItem);
23247 xmlFree(*keySeq);
23248 *keySeq = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023249 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023250 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023251 }
23252 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023253 * Init the node-table item: Save the node, position and
23254 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023255 */
23256 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023257 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023258 ntItem->keys = *keySeq;
23259 *keySeq = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023260#if 0
Daniel Veillarddee23482008-04-11 12:58:43 +000023261 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023262#endif
23263 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023264 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023265 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023266 * Free the item, since keyref items won't be
23267 * put on a global list.
23268 */
23269 xmlFree(ntItem->keys);
23270 xmlFree(ntItem);
23271 }
23272 return (-1);
23273 }
Haibo Huang3496e1e2020-11-30 18:17:15 -080023274 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23275 xmlChar *value = NULL;
23276 xmlIDCHashEntryPtr r, e;
23277 if (!matcher->htab)
23278 matcher->htab = xmlHashCreate(4);
23279 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23280 e = xmlMalloc(sizeof *e);
23281 e->index = targets->nbItems - 1;
23282 r = xmlHashLookup(matcher->htab, value);
23283 if (r) {
23284 e->next = r->next;
23285 r->next = e;
23286 } else {
23287 e->next = NULL;
23288 xmlHashAddEntry(matcher->htab, value, e);
23289 }
23290 FREE_AND_NULL(value);
23291 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023292
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023293 goto selector_leave;
23294selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023295 {
23296 xmlChar *str = NULL;
23297 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010023298 * 4.2.1 (KEY) The `target node set` and the
23299 * `qualified node set` are equal, that is, every
23300 * member of the `target node set` is also a member
23301 * of the `qualified node set` and vice versa.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023302 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023303 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023304 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000023305 WXS_BASIC_CAST idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023306 "Not all fields of %s evaluate to a node",
23307 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23308 FREE_AND_NULL(str);
23309 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023310selector_leave:
23311 /*
23312 * Free the key-sequence if not added to the IDC table.
23313 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023314 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023315 xmlFree(*keySeq);
23316 *keySeq = NULL;
23317 }
23318 } /* if selector */
Daniel Veillarddee23482008-04-11 12:58:43 +000023319
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023320 sto->nbHistory--;
23321
23322deregister_check:
23323 /*
23324 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023325 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023326 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023327#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023328 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23329 sto->sel->xpath);
23330#endif
23331 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023332 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023333 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023334 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023335 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023336 nextsto = sto->next;
23337 /*
23338 * Unlink from the list of active XPath state objects.
23339 */
23340 vctxt->xpathStates = sto->next;
23341 sto->next = vctxt->xpathStatePool;
23342 /*
23343 * Link it to the pool of reusable state objects.
23344 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023345 vctxt->xpathStatePool = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023346 sto = nextsto;
23347 } else
23348 sto = sto->next;
23349 } /* while (sto != NULL) */
23350 return (0);
23351}
23352
23353/**
23354 * xmlSchemaIDCRegisterMatchers:
23355 * @vctxt: the WXS validation context
23356 * @elemDecl: the element declaration
23357 *
23358 * Creates helper objects to evaluate IDC selectors/fields
23359 * successively.
23360 *
23361 * Returns 0 if OK and -1 on internal errors.
23362 */
23363static int
23364xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23365 xmlSchemaElementPtr elemDecl)
23366{
23367 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23368 xmlSchemaIDCPtr idc, refIdc;
23369 xmlSchemaIDCAugPtr aidc;
Daniel Veillarddee23482008-04-11 12:58:43 +000023370
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023371 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23372 if (idc == NULL)
23373 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000023374
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023375#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023376 {
23377 xmlChar *str = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023378 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023379 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023380 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23381 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023382 FREE_AND_NULL(str)
23383 }
23384#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023385 if (vctxt->inode->idcMatchers != NULL) {
23386 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23387 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023388 return (-1);
23389 }
23390 do {
23391 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23392 /*
23393 * Since IDCs bubbles are expensive we need to know the
23394 * depth at which the bubbles should stop; this will be
23395 * the depth of the top-most keyref IDC. If no keyref
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023396 * references a key/unique IDC, the keyrefDepth will
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023397 * be -1, indicating that no bubbles are needed.
23398 */
23399 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23400 if (refIdc != NULL) {
23401 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023402 * Remember that we have keyrefs on this node.
23403 */
23404 vctxt->inode->hasKeyrefs = 1;
23405 /*
23406 * Lookup the referenced augmented IDC info.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023407 */
23408 aidc = vctxt->aidcs;
23409 while (aidc != NULL) {
23410 if (aidc->def == refIdc)
23411 break;
23412 aidc = aidc->next;
23413 }
23414 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023415 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023416 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023417 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023418 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000023419 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023420 if ((aidc->keyrefDepth == -1) ||
23421 (vctxt->depth < aidc->keyrefDepth))
23422 aidc->keyrefDepth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023423 }
23424 }
23425 /*
23426 * Lookup the augmented IDC item for the IDC definition.
23427 */
23428 aidc = vctxt->aidcs;
23429 while (aidc != NULL) {
23430 if (aidc->def == idc)
23431 break;
23432 aidc = aidc->next;
23433 }
23434 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023435 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23436 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023437 return (-1);
23438 }
23439 /*
23440 * Create an IDC matcher for every IDC definition.
23441 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023442 if (vctxt->idcMatcherCache != NULL) {
23443 /*
23444 * Reuse a cached matcher.
23445 */
23446 matcher = vctxt->idcMatcherCache;
23447 vctxt->idcMatcherCache = matcher->nextCached;
23448 matcher->nextCached = NULL;
23449 } else {
Daniel Veillarddee23482008-04-11 12:58:43 +000023450 matcher = (xmlSchemaIDCMatcherPtr)
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023451 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23452 if (matcher == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023453 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000023454 "allocating an IDC matcher", NULL);
23455 return (-1);
23456 }
23457 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023458 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023459 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023460 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023461 else
23462 last->next = matcher;
23463 last = matcher;
23464
23465 matcher->type = IDC_MATCHER;
Daniel Veillarddee23482008-04-11 12:58:43 +000023466 matcher->depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023467 matcher->aidc = aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023468 matcher->idcType = aidc->def->type;
Daniel Veillarddee23482008-04-11 12:58:43 +000023469#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023470 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
Daniel Veillarddee23482008-04-11 12:58:43 +000023471#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023472 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023473 * Init the automaton state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023474 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023475 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023476 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023477 return (-1);
23478
23479 idc = idc->next;
23480 } while (idc != NULL);
23481 return (0);
23482}
23483
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023484static int
23485xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23486 xmlSchemaNodeInfoPtr ielem)
23487{
23488 xmlSchemaPSVIIDCBindingPtr bind;
23489 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23490 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23491 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023492
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023493 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23494 /* vctxt->createIDCNodeTables */
23495 while (matcher != NULL) {
23496 /*
23497 * Skip keyref IDCs and empty IDC target-lists.
23498 */
23499 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23500 WXS_ILIST_IS_EMPTY(matcher->targets))
23501 {
23502 matcher = matcher->next;
23503 continue;
23504 }
23505 /*
23506 * If we _want_ the IDC node-table to be created in any case
23507 * then do so. Otherwise create them only if keyrefs need them.
23508 */
23509 if ((! vctxt->createIDCNodeTables) &&
23510 ((matcher->aidc->keyrefDepth == -1) ||
23511 (matcher->aidc->keyrefDepth > vctxt->depth)))
23512 {
23513 matcher = matcher->next;
23514 continue;
23515 }
23516 /*
23517 * Get/create the IDC binding on this element for the IDC definition.
23518 */
23519 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
Haibo Huangcfd91dc2020-07-30 23:01:33 -070023520 if (bind == NULL)
23521 goto internal_error;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023522
23523 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23524 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23525 nbDupls = bind->dupls->nbItems;
23526 } else {
23527 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023528 nbDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023529 }
23530 if (bind->nodeTable != NULL) {
23531 nbNodeTable = bind->nbNodes;
23532 } else {
23533 nbNodeTable = 0;
23534 }
23535
23536 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23537 /*
23538 * Transfer all IDC target-nodes to the IDC node-table.
23539 */
23540 bind->nodeTable =
Daniel Veillarddee23482008-04-11 12:58:43 +000023541 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023542 bind->sizeNodes = matcher->targets->sizeItems;
23543 bind->nbNodes = matcher->targets->nbItems;
23544
23545 matcher->targets->items = NULL;
23546 matcher->targets->sizeItems = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023547 matcher->targets->nbItems = 0;
Haibo Huang3496e1e2020-11-30 18:17:15 -080023548 if (matcher->htab) {
23549 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23550 matcher->htab = NULL;
23551 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023552 } else {
23553 /*
23554 * Compare the key-sequences and add to the IDC node-table.
23555 */
23556 nbTargets = matcher->targets->nbItems;
Daniel Veillarddee23482008-04-11 12:58:43 +000023557 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023558 nbFields = matcher->aidc->def->nbFields;
23559 i = 0;
23560 do {
23561 keys = targets[i]->keys;
Daniel Veillarddee23482008-04-11 12:58:43 +000023562 if (nbDupls) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023563 /*
23564 * Search in already found duplicates first.
23565 */
23566 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023567 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023568 if (nbFields == 1) {
23569 res = xmlSchemaAreValuesEqual(keys[0]->val,
23570 dupls[j]->keys[0]->val);
23571 if (res == -1)
23572 goto internal_error;
23573 if (res == 1) {
23574 /*
23575 * Equal key-sequence.
23576 */
23577 goto next_target;
23578 }
23579 } else {
23580 res = 0;
23581 ntkeys = dupls[j]->keys;
23582 for (k = 0; k < nbFields; k++) {
23583 res = xmlSchemaAreValuesEqual(keys[k]->val,
23584 ntkeys[k]->val);
23585 if (res == -1)
23586 goto internal_error;
23587 if (res == 0) {
23588 /*
23589 * One of the keys differs.
23590 */
23591 break;
23592 }
23593 }
23594 if (res == 1) {
23595 /*
23596 * Equal key-sequence found.
23597 */
23598 goto next_target;
23599 }
23600 }
23601 j++;
Daniel Veillarddee23482008-04-11 12:58:43 +000023602 } while (j < nbDupls);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023603 }
23604 if (nbNodeTable) {
23605 j = 0;
Daniel Veillarddee23482008-04-11 12:58:43 +000023606 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023607 if (nbFields == 1) {
23608 res = xmlSchemaAreValuesEqual(keys[0]->val,
23609 bind->nodeTable[j]->keys[0]->val);
23610 if (res == -1)
23611 goto internal_error;
23612 if (res == 0) {
23613 /*
23614 * The key-sequence differs.
23615 */
23616 goto next_node_table_entry;
23617 }
23618 } else {
23619 res = 0;
23620 ntkeys = bind->nodeTable[j]->keys;
23621 for (k = 0; k < nbFields; k++) {
23622 res = xmlSchemaAreValuesEqual(keys[k]->val,
23623 ntkeys[k]->val);
23624 if (res == -1)
23625 goto internal_error;
23626 if (res == 0) {
23627 /*
23628 * One of the keys differs.
23629 */
23630 goto next_node_table_entry;
23631 }
23632 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023633 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023634 /*
23635 * Add the duplicate to the list of duplicates.
23636 */
23637 if (bind->dupls == NULL) {
23638 bind->dupls = xmlSchemaItemListCreate();
23639 if (bind->dupls == NULL)
23640 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023641 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023642 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23643 goto internal_error;
23644 /*
23645 * Remove the duplicate entry from the IDC node-table.
23646 */
23647 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23648 bind->nbNodes--;
23649
23650 goto next_target;
23651
23652next_node_table_entry:
23653 j++;
23654 } while (j < nbNodeTable);
23655 }
23656 /*
23657 * If everything is fine, then add the IDC target-node to
23658 * the IDC node-table.
23659 */
23660 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23661 goto internal_error;
23662
23663next_target:
23664 i++;
23665 } while (i < nbTargets);
23666 }
23667 matcher = matcher->next;
23668 }
23669 return(0);
23670
23671internal_error:
23672 return(-1);
23673}
23674
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023675/**
Daniel Veillarddee23482008-04-11 12:58:43 +000023676 * xmlSchemaBubbleIDCNodeTables:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023677 * @depth: the current tree depth
23678 *
Daniel Veillarddee23482008-04-11 12:58:43 +000023679 * Merges IDC bindings of an element at @depth into the corresponding IDC
23680 * bindings of its parent element. If a duplicate note-table entry is found,
23681 * both, the parent node-table entry and child entry are discarded from the
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023682 * node-table of the parent.
23683 *
23684 * Returns 0 if OK and -1 on internal errors.
23685 */
23686static int
23687xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23688{
23689 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023690 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23691 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023692 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023693 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023694
Daniel Veillarddee23482008-04-11 12:58:43 +000023695 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023696 if (bind == NULL) {
23697 /* Fine, no table, no bubbles. */
23698 return (0);
23699 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023700
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023701 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23702 /*
23703 * Walk all bindings; create new or add to existing bindings.
23704 * Remove duplicate key-sequences.
23705 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023706 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023707
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023708 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23709 goto next_binding;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023710 /*
23711 * Check if the key/unique IDC table needs to be bubbled.
23712 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023713 if (! vctxt->createIDCNodeTables) {
23714 aidc = vctxt->aidcs;
23715 do {
23716 if (aidc->def == bind->definition) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023717 if ((aidc->keyrefDepth == -1) ||
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023718 (aidc->keyrefDepth >= vctxt->depth)) {
23719 goto next_binding;
23720 }
23721 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023722 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023723 aidc = aidc->next;
23724 } while (aidc != NULL);
23725 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000023726
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023727 if (parTable != NULL)
23728 parBind = *parTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023729 /*
23730 * Search a matching parent binding for the
23731 * IDC definition.
23732 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023733 while (parBind != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023734 if (parBind->definition == bind->definition)
23735 break;
23736 parBind = parBind->next;
23737 }
23738
23739 if (parBind != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023740 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023741 * Compare every node-table entry of the child node,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023742 * i.e. the key-sequence within, ...
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023743 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023744 oldNum = parBind->nbNodes; /* Skip newly added items. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023745
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023746 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23747 oldDupls = parBind->dupls->nbItems;
23748 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23749 } else {
23750 dupls = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000023751 oldDupls = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023752 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023753
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023754 parNodes = parBind->nodeTable;
23755 nbFields = bind->definition->nbFields;
Daniel Veillarddee23482008-04-11 12:58:43 +000023756
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023757 for (i = 0; i < bind->nbNodes; i++) {
23758 node = bind->nodeTable[i];
23759 if (node == NULL)
23760 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023761 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023762 * ...with every key-sequence of the parent node, already
23763 * evaluated to be a duplicate key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023764 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023765 if (oldDupls) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023766 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023767 while (j < oldDupls) {
23768 if (nbFields == 1) {
23769 ret = xmlSchemaAreValuesEqual(
23770 node->keys[0]->val,
23771 dupls[j]->keys[0]->val);
23772 if (ret == -1)
23773 goto internal_error;
23774 if (ret == 0) {
23775 j++;
23776 continue;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023777 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023778 } else {
23779 parNode = dupls[j];
23780 for (k = 0; k < nbFields; k++) {
23781 ret = xmlSchemaAreValuesEqual(
23782 node->keys[k]->val,
23783 parNode->keys[k]->val);
23784 if (ret == -1)
23785 goto internal_error;
23786 if (ret == 0)
23787 break;
23788 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023789 }
23790 if (ret == 1)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023791 /* Duplicate found. */
23792 break;
23793 j++;
23794 }
23795 if (j != oldDupls) {
23796 /* Duplicate found. Skip this entry. */
23797 continue;
23798 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023799 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023800 /*
23801 * ... and with every key-sequence of the parent node.
23802 */
23803 if (oldNum) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023804 j = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023805 while (j < oldNum) {
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023806 parNode = parNodes[j];
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023807 if (nbFields == 1) {
23808 ret = xmlSchemaAreValuesEqual(
23809 node->keys[0]->val,
Kasimier T. Buchcikf39e8d12005-11-30 11:03:24 +000023810 parNode->keys[0]->val);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023811 if (ret == -1)
23812 goto internal_error;
23813 if (ret == 0) {
23814 j++;
23815 continue;
23816 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023817 } else {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023818 for (k = 0; k < nbFields; k++) {
23819 ret = xmlSchemaAreValuesEqual(
23820 node->keys[k]->val,
23821 parNode->keys[k]->val);
23822 if (ret == -1)
23823 goto internal_error;
23824 if (ret == 0)
23825 break;
23826 }
23827 }
23828 if (ret == 1)
23829 /* Duplicate found. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023830 break;
23831 j++;
23832 }
23833 if (j != oldNum) {
23834 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023835 * Handle duplicates. Move the duplicate in
23836 * the parent's node-table to the list of
23837 * duplicates.
Daniel Veillarddee23482008-04-11 12:58:43 +000023838 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023839 oldNum--;
23840 parBind->nbNodes--;
23841 /*
23842 * Move last old item to pos of duplicate.
23843 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023844 parNodes[j] = parNodes[oldNum];
Daniel Veillarddee23482008-04-11 12:58:43 +000023845
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023846 if (parBind->nbNodes != oldNum) {
23847 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023848 * If new items exist, move last new item to
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023849 * last of old items.
23850 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023851 parNodes[oldNum] =
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023852 parNodes[parBind->nbNodes];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023853 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023854 if (parBind->dupls == NULL) {
23855 parBind->dupls = xmlSchemaItemListCreate();
23856 if (parBind->dupls == NULL)
23857 goto internal_error;
23858 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023859 xmlSchemaItemListAdd(parBind->dupls, parNode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023860 } else {
23861 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000023862 * Add the node-table entry (node and key-sequence) of
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023863 * the child node to the node table of the parent node.
23864 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023865 if (parBind->nodeTable == NULL) {
23866 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023867 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023868 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023869 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023870 "allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023871 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023872 }
23873 parBind->sizeNodes = 1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023874 } else if (parBind->nbNodes >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000023875 parBind->sizeNodes *= 2;
Daniel Veillarddee23482008-04-11 12:58:43 +000023876 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23877 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023878 sizeof(xmlSchemaPSVIIDCNodePtr));
23879 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023880 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023881 "re-allocating IDC list of node-table items", NULL);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023882 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023883 }
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023884 }
23885 parNodes = parBind->nodeTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023886 /*
23887 * Append the new node-table entry to the 'new node-table
23888 * entries' section.
23889 */
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000023890 parNodes[parBind->nbNodes++] = node;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023891 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023892
Daniel Veillarddee23482008-04-11 12:58:43 +000023893 }
23894
23895 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023896 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023897 /*
23898 * No binding for the IDC was found: create a new one and
23899 * copy all node-tables.
23900 */
23901 parBind = xmlSchemaIDCNewBinding(bind->definition);
23902 if (parBind == NULL)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023903 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000023904
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023905 /*
23906 * TODO: Hmm, how to optimize the initial number of
23907 * allocated entries?
23908 */
23909 if (bind->nbNodes != 0) {
23910 /*
23911 * Add all IDC node-table entries.
23912 */
23913 if (! vctxt->psviExposeIDCNodeTables) {
23914 /*
23915 * Just move the entries.
23916 * NOTE: this is quite save here, since
23917 * all the keyref lookups have already been
23918 * performed.
23919 */
23920 parBind->nodeTable = bind->nodeTable;
23921 bind->nodeTable = NULL;
23922 parBind->sizeNodes = bind->sizeNodes;
23923 bind->sizeNodes = 0;
23924 parBind->nbNodes = bind->nbNodes;
23925 bind->nbNodes = 0;
23926 } else {
23927 /*
23928 * Copy the entries.
23929 */
Daniel Veillarddee23482008-04-11 12:58:43 +000023930 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023931 xmlMalloc(bind->nbNodes *
23932 sizeof(xmlSchemaPSVIIDCNodePtr));
23933 if (parBind->nodeTable == NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000023934 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023935 "allocating an array of IDC node-table "
23936 "items", NULL);
23937 xmlSchemaIDCFreeBinding(parBind);
23938 goto internal_error;
23939 }
23940 parBind->sizeNodes = bind->nbNodes;
23941 parBind->nbNodes = bind->nbNodes;
23942 memcpy(parBind->nodeTable, bind->nodeTable,
23943 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23944 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023945 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023946 if (bind->dupls) {
23947 /*
23948 * Move the duplicates.
23949 */
23950 if (parBind->dupls != NULL)
23951 xmlSchemaItemListFree(parBind->dupls);
23952 parBind->dupls = bind->dupls;
Daniel Veillarddee23482008-04-11 12:58:43 +000023953 bind->dupls = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023954 }
Daniel Veillard76d36452009-09-07 11:19:33 +020023955 if (parTable != NULL) {
23956 if (*parTable == NULL)
23957 *parTable = parBind;
23958 else {
23959 parBind->next = *parTable;
23960 *parTable = parBind;
23961 }
23962 }
Daniel Veillarddee23482008-04-11 12:58:43 +000023963 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023964
23965next_binding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023966 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023967 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023968 return (0);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023969
23970internal_error:
23971 return(-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023972}
23973
23974/**
23975 * xmlSchemaCheckCVCIDCKeyRef:
23976 * @vctxt: the WXS validation context
23977 * @elemDecl: the element declaration
23978 *
23979 * Check the cvc-idc-keyref constraints.
23980 */
23981static int
23982xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23983{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023984 xmlSchemaIDCMatcherPtr matcher;
23985 xmlSchemaPSVIIDCBindingPtr bind;
Daniel Veillarddee23482008-04-11 12:58:43 +000023986
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023987 matcher = vctxt->inode->idcMatchers;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023988 /*
23989 * Find a keyref.
23990 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000023991 while (matcher != NULL) {
23992 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23993 matcher->targets &&
23994 matcher->targets->nbItems)
23995 {
23996 int i, j, k, res, nbFields, hasDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023997 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023998 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Haibo Huang3496e1e2020-11-30 18:17:15 -080023999 xmlHashTablePtr table = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024000
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024001 nbFields = matcher->aidc->def->nbFields;
24002
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024003 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024004 * Find the IDC node-table for the referenced IDC key/unique.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024005 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024006 bind = vctxt->inode->idcTable;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024007 while (bind != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024008 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024009 bind->definition)
24010 break;
24011 bind = bind->next;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024012 }
24013 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024014 /*
24015 * Search for a matching key-sequences.
24016 */
Haibo Huang3496e1e2020-11-30 18:17:15 -080024017 if (bind) {
24018 table = xmlHashCreate(bind->nbNodes * 2);
24019 for (j = 0; j < bind->nbNodes; j++) {
24020 xmlChar *value;
24021 xmlIDCHashEntryPtr r, e;
24022 keys = bind->nodeTable[j]->keys;
24023 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24024 e = xmlMalloc(sizeof *e);
24025 e->index = j;
24026 r = xmlHashLookup(table, value);
24027 if (r) {
24028 e->next = r->next;
24029 r->next = e;
24030 } else {
24031 e->next = NULL;
24032 xmlHashAddEntry(table, value, e);
24033 }
24034 FREE_AND_NULL(value);
24035 }
24036 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024037 for (i = 0; i < matcher->targets->nbItems; i++) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024038 res = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024039 refNode = matcher->targets->items[i];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024040 if (bind != NULL) {
Haibo Huang3496e1e2020-11-30 18:17:15 -080024041 xmlChar *value;
24042 xmlIDCHashEntryPtr e;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024043 refKeys = refNode->keys;
Haibo Huang3496e1e2020-11-30 18:17:15 -080024044 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24045 e = xmlHashLookup(table, value);
24046 FREE_AND_NULL(value);
24047 res = 0;
24048 for (;e; e = e->next) {
24049 keys = bind->nodeTable[e->index]->keys;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024050 for (k = 0; k < nbFields; k++) {
24051 res = xmlSchemaAreValuesEqual(keys[k]->val,
Haibo Huang3496e1e2020-11-30 18:17:15 -080024052 refKeys[k]->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024053 if (res == 0)
Haibo Huang3496e1e2020-11-30 18:17:15 -080024054 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024055 else if (res == -1) {
24056 return (-1);
24057 }
24058 }
24059 if (res == 1) {
24060 /*
Haibo Huang3496e1e2020-11-30 18:17:15 -080024061 * Match found.
24062 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024063 break;
24064 }
24065 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024066 if ((res == 0) && hasDupls) {
24067 /*
24068 * Search in duplicates
24069 */
24070 for (j = 0; j < bind->dupls->nbItems; j++) {
24071 keys = ((xmlSchemaPSVIIDCNodePtr)
24072 bind->dupls->items[j])->keys;
24073 for (k = 0; k < nbFields; k++) {
24074 res = xmlSchemaAreValuesEqual(keys[k]->val,
24075 refKeys[k]->val);
24076 if (res == 0)
24077 break;
24078 else if (res == -1) {
24079 return (-1);
24080 }
24081 }
24082 if (res == 1) {
24083 /*
24084 * Match in duplicates found.
24085 */
24086 xmlChar *str = NULL, *strB = NULL;
24087 xmlSchemaKeyrefErr(vctxt,
24088 XML_SCHEMAV_CVC_IDC, refNode,
24089 (xmlSchemaTypePtr) matcher->aidc->def,
24090 "More than one match found for "
24091 "key-sequence %s of keyref '%s'",
24092 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24093 refNode->keys, nbFields),
24094 xmlSchemaGetComponentQName(&strB,
24095 matcher->aidc->def));
24096 FREE_AND_NULL(str);
24097 FREE_AND_NULL(strB);
24098 break;
24099 }
24100 }
24101 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024102 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024103
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024104 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024105 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024106 xmlSchemaKeyrefErr(vctxt,
24107 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024108 (xmlSchemaTypePtr) matcher->aidc->def,
24109 "No match found for key-sequence %s of keyref '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000024110 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024111 refNode->keys, nbFields),
24112 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024113 FREE_AND_NULL(str);
24114 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024115 }
24116 }
Haibo Huang3496e1e2020-11-30 18:17:15 -080024117 if (table) {
24118 xmlHashFree(table, xmlFreeIDCHashEntry);
24119 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024120 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024121 matcher = matcher->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024122 }
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024123 /* TODO: Return an error if any error encountered. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024124 return (0);
24125}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024126
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024127/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080024128 * *
24129 * XML Reader validation code *
24130 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024131 ************************************************************************/
24132
24133static xmlSchemaAttrInfoPtr
24134xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024135{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024136 xmlSchemaAttrInfoPtr iattr;
24137 /*
24138 * Grow/create list of attribute infos.
24139 */
24140 if (vctxt->attrInfos == NULL) {
24141 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24142 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24143 vctxt->sizeAttrInfos = 1;
24144 if (vctxt->attrInfos == NULL) {
24145 xmlSchemaVErrMemory(vctxt,
24146 "allocating attribute info list", NULL);
24147 return (NULL);
24148 }
24149 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24150 vctxt->sizeAttrInfos++;
24151 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24152 xmlRealloc(vctxt->attrInfos,
24153 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24154 if (vctxt->attrInfos == NULL) {
24155 xmlSchemaVErrMemory(vctxt,
24156 "re-allocating attribute info list", NULL);
24157 return (NULL);
24158 }
24159 } else {
24160 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24161 if (iattr->localName != NULL) {
24162 VERROR_INT("xmlSchemaGetFreshAttrInfo",
24163 "attr info not cleared");
24164 return (NULL);
24165 }
24166 iattr->nodeType = XML_ATTRIBUTE_NODE;
24167 return (iattr);
24168 }
24169 /*
24170 * Create an attribute info.
24171 */
24172 iattr = (xmlSchemaAttrInfoPtr)
24173 xmlMalloc(sizeof(xmlSchemaAttrInfo));
24174 if (iattr == NULL) {
24175 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24176 return (NULL);
24177 }
24178 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24179 iattr->nodeType = XML_ATTRIBUTE_NODE;
24180 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24181
24182 return (iattr);
24183}
24184
24185static int
24186xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24187 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024188 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024189 const xmlChar *localName,
Daniel Veillarddee23482008-04-11 12:58:43 +000024190 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024191 int ownedNames,
24192 xmlChar *value,
24193 int ownedValue)
24194{
24195 xmlSchemaAttrInfoPtr attr;
24196
24197 attr = xmlSchemaGetFreshAttrInfo(vctxt);
24198 if (attr == NULL) {
24199 VERROR_INT("xmlSchemaPushAttribute",
24200 "calling xmlSchemaGetFreshAttrInfo()");
24201 return (-1);
24202 }
24203 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024204 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024205 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24206 attr->localName = localName;
24207 attr->nsName = nsName;
24208 if (ownedNames)
24209 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24210 /*
24211 * Evaluate if it's an XSI attribute.
24212 */
24213 if (nsName != NULL) {
24214 if (xmlStrEqual(localName, BAD_CAST "nil")) {
24215 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024216 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024217 }
24218 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24219 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24220 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24221 }
24222 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24223 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24224 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24225 }
24226 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24227 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24228 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24229 }
24230 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24231 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24232 }
24233 }
24234 attr->value = value;
24235 if (ownedValue)
24236 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24237 if (attr->metaType != 0)
24238 attr->state = XML_SCHEMAS_ATTR_META;
24239 return (0);
24240}
24241
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024242/**
24243 * xmlSchemaClearElemInfo:
24244 * @vctxt: the WXS validation context
24245 * @ielem: the element information item
24246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024247static void
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024248xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24249 xmlSchemaNodeInfoPtr ielem)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024250{
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024251 ielem->hasKeyrefs = 0;
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000024252 ielem->appliedXPath = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024253 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24254 FREE_AND_NULL(ielem->localName);
24255 FREE_AND_NULL(ielem->nsName);
24256 } else {
24257 ielem->localName = NULL;
24258 ielem->nsName = NULL;
24259 }
24260 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24261 FREE_AND_NULL(ielem->value);
24262 } else {
24263 ielem->value = NULL;
24264 }
24265 if (ielem->val != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024266 /*
24267 * PSVI TODO: Be careful not to free it when the value is
24268 * exposed via PSVI.
24269 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024270 xmlSchemaFreeValue(ielem->val);
24271 ielem->val = NULL;
24272 }
24273 if (ielem->idcMatchers != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024274 /*
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024275 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24276 * Does it work?
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024277 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024278 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24279#if 0
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024280 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000024281#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024282 ielem->idcMatchers = NULL;
24283 }
24284 if (ielem->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024285 /*
24286 * OPTIMIZE TODO: Use a pool of IDC tables??.
24287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024288 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24289 ielem->idcTable = NULL;
24290 }
24291 if (ielem->regexCtxt != NULL) {
24292 xmlRegFreeExecCtxt(ielem->regexCtxt);
24293 ielem->regexCtxt = NULL;
24294 }
24295 if (ielem->nsBindings != NULL) {
24296 xmlFree((xmlChar **)ielem->nsBindings);
24297 ielem->nsBindings = NULL;
24298 ielem->nbNsBindings = 0;
24299 ielem->sizeNsBindings = 0;
24300 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024301}
24302
24303/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024304 * xmlSchemaGetFreshElemInfo:
24305 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024306 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024307 * Creates/reuses and initializes the element info item for
Haibo Huangcfd91dc2020-07-30 23:01:33 -070024308 * the current tree depth.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024309 *
24310 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024311 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024312static xmlSchemaNodeInfoPtr
24313xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024314{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024315 xmlSchemaNodeInfoPtr info = NULL;
24316
24317 if (vctxt->depth > vctxt->sizeElemInfos) {
24318 VERROR_INT("xmlSchemaGetFreshElemInfo",
24319 "inconsistent depth encountered");
24320 return (NULL);
24321 }
24322 if (vctxt->elemInfos == NULL) {
24323 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24324 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24325 if (vctxt->elemInfos == NULL) {
24326 xmlSchemaVErrMemory(vctxt,
24327 "allocating the element info array", NULL);
24328 return (NULL);
24329 }
24330 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24331 vctxt->sizeElemInfos = 10;
24332 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24333 int i = vctxt->sizeElemInfos;
24334
24335 vctxt->sizeElemInfos *= 2;
24336 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24337 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24338 sizeof(xmlSchemaNodeInfoPtr));
24339 if (vctxt->elemInfos == NULL) {
24340 xmlSchemaVErrMemory(vctxt,
24341 "re-allocating the element info array", NULL);
24342 return (NULL);
24343 }
24344 /*
24345 * We need the new memory to be NULLed.
24346 * TODO: Use memset instead?
24347 */
24348 for (; i < vctxt->sizeElemInfos; i++)
24349 vctxt->elemInfos[i] = NULL;
24350 } else
24351 info = vctxt->elemInfos[vctxt->depth];
24352
24353 if (info == NULL) {
24354 info = (xmlSchemaNodeInfoPtr)
24355 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24356 if (info == NULL) {
24357 xmlSchemaVErrMemory(vctxt,
24358 "allocating an element info", NULL);
24359 return (NULL);
24360 }
24361 vctxt->elemInfos[vctxt->depth] = info;
24362 } else {
24363 if (info->localName != NULL) {
24364 VERROR_INT("xmlSchemaGetFreshElemInfo",
24365 "elem info has not been cleared");
24366 return (NULL);
24367 }
24368 }
24369 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24370 info->nodeType = XML_ELEMENT_NODE;
24371 info->depth = vctxt->depth;
24372
24373 return (info);
24374}
24375
24376#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24377#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24378#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24379
24380static int
24381xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24382 xmlNodePtr node,
24383 xmlSchemaTypePtr type,
24384 xmlSchemaValType valType,
24385 const xmlChar * value,
24386 xmlSchemaValPtr val,
24387 unsigned long length,
24388 int fireErrors)
24389{
Haibo Huangcfd91dc2020-07-30 23:01:33 -070024390 int ret, error = 0, found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024391
24392 xmlSchemaTypePtr tmpType;
24393 xmlSchemaFacetLinkPtr facetLink;
24394 xmlSchemaFacetPtr facet;
24395 unsigned long len = 0;
24396 xmlSchemaWhitespaceValueType ws;
24397
24398 /*
24399 * In Libxml2, derived built-in types have currently no explicit facets.
24400 */
24401 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024402 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024403
24404 /*
24405 * NOTE: Do not jump away, if the facetSet of the given type is
24406 * empty: until now, "pattern" and "enumeration" facets of the
24407 * *base types* need to be checked as well.
24408 */
24409 if (type->facetSet == NULL)
24410 goto pattern_and_enum;
24411
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024412 if (! WXS_IS_ATOMIC(type)) {
24413 if (WXS_IS_LIST(type))
24414 goto WXS_IS_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024415 else
24416 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024417 }
Scott Graham58b84e12015-06-30 10:47:16 +080024418
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024419 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024420 * Whitespace handling is only of importance for string-based
24421 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024422 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024423 tmpType = xmlSchemaGetPrimitiveType(type);
24424 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024425 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024426 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24427 } else
24428 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
Scott Graham58b84e12015-06-30 10:47:16 +080024429
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024430 /*
24431 * If the value was not computed (for string or
24432 * anySimpleType based types), then use the provided
24433 * type.
24434 */
Scott Graham58b84e12015-06-30 10:47:16 +080024435 if (val != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024436 valType = xmlSchemaGetValType(val);
Daniel Veillarddee23482008-04-11 12:58:43 +000024437
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024438 ret = 0;
24439 for (facetLink = type->facetSet; facetLink != NULL;
24440 facetLink = facetLink->next) {
24441 /*
24442 * Skip the pattern "whiteSpace": it is used to
24443 * format the character content beforehand.
24444 */
24445 switch (facetLink->facet->type) {
24446 case XML_SCHEMA_FACET_WHITESPACE:
24447 case XML_SCHEMA_FACET_PATTERN:
24448 case XML_SCHEMA_FACET_ENUMERATION:
24449 continue;
24450 case XML_SCHEMA_FACET_LENGTH:
24451 case XML_SCHEMA_FACET_MINLENGTH:
24452 case XML_SCHEMA_FACET_MAXLENGTH:
24453 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24454 valType, value, val, &len, ws);
24455 break;
24456 default:
24457 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24458 valType, value, val, ws);
24459 break;
24460 }
24461 if (ret < 0) {
24462 AERROR_INT("xmlSchemaValidateFacets",
24463 "validating against a atomic type facet");
24464 return (-1);
24465 } else if (ret > 0) {
24466 if (fireErrors)
24467 xmlSchemaFacetErr(actxt, ret, node,
24468 value, len, type, facetLink->facet, NULL, NULL, NULL);
24469 else
24470 return (ret);
24471 if (error == 0)
24472 error = ret;
24473 }
24474 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024475 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024476
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024477WXS_IS_LIST:
24478 if (! WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024479 goto pattern_and_enum;
24480 /*
24481 * "length", "minLength" and "maxLength" of list types.
24482 */
24483 ret = 0;
24484 for (facetLink = type->facetSet; facetLink != NULL;
24485 facetLink = facetLink->next) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024486
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024487 switch (facetLink->facet->type) {
24488 case XML_SCHEMA_FACET_LENGTH:
24489 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillarddee23482008-04-11 12:58:43 +000024490 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024491 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24492 value, length, NULL);
24493 break;
24494 default:
24495 continue;
24496 }
24497 if (ret < 0) {
24498 AERROR_INT("xmlSchemaValidateFacets",
24499 "validating against a list type facet");
24500 return (-1);
24501 } else if (ret > 0) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024502 if (fireErrors)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024503 xmlSchemaFacetErr(actxt, ret, node,
24504 value, length, type, facetLink->facet, NULL, NULL, NULL);
24505 else
24506 return (ret);
24507 if (error == 0)
24508 error = ret;
24509 }
24510 ret = 0;
24511 }
24512
24513pattern_and_enum:
Haibo Huangcfd91dc2020-07-30 23:01:33 -070024514 found = 0;
24515 /*
24516 * Process enumerations. Facet values are in the value space
24517 * of the defining type's base type. This seems to be a bug in the
24518 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24519 * Only the first set of enumerations in the ancestor-or-self axis
24520 * is used for validation.
24521 */
24522 ret = 0;
24523 tmpType = type;
24524 do {
24525 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24526 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24527 continue;
24528 found = 1;
24529 ret = xmlSchemaAreValuesEqual(facet->val, val);
24530 if (ret == 1)
24531 break;
24532 else if (ret < 0) {
24533 AERROR_INT("xmlSchemaValidateFacets",
24534 "validating against an enumeration facet");
24535 return (-1);
24536 }
24537 }
24538 if (ret != 0)
24539 break;
24540 /*
24541 * Break on the first set of enumerations. Any additional
24542 * enumerations which might be existent on the ancestors
24543 * of the current type are restricted by this set; thus
24544 * *must* *not* be taken into account.
24545 */
24546 if (found)
24547 break;
24548 tmpType = tmpType->baseType;
24549 } while ((tmpType != NULL) &&
24550 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24551 if (found && (ret == 0)) {
24552 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24553 if (fireErrors) {
24554 xmlSchemaFacetErr(actxt, ret, node,
24555 value, 0, type, NULL, NULL, NULL, NULL);
24556 } else
24557 return (ret);
24558 if (error == 0)
24559 error = ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024560 }
24561
Haibo Huangcfd91dc2020-07-30 23:01:33 -070024562 /*
24563 * Process patters. Pattern facets are ORed at type level
24564 * and ANDed if derived. Walk the base type axis.
24565 */
24566 tmpType = type;
24567 facet = NULL;
24568 do {
24569 found = 0;
24570 for (facetLink = tmpType->facetSet; facetLink != NULL;
24571 facetLink = facetLink->next) {
24572 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24573 continue;
24574 found = 1;
24575 /*
24576 * NOTE that for patterns, @value needs to be the
24577 * normalized value.
24578 */
24579 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24580 if (ret == 1)
24581 break;
24582 else if (ret < 0) {
24583 AERROR_INT("xmlSchemaValidateFacets",
24584 "validating against a pattern facet");
24585 return (-1);
24586 } else {
24587 /*
24588 * Save the last non-validating facet.
24589 */
24590 facet = facetLink->facet;
24591 }
24592 }
24593 if (found && (ret != 1)) {
24594 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24595 if (fireErrors) {
24596 xmlSchemaFacetErr(actxt, ret, node,
24597 value, 0, type, facet, NULL, NULL, NULL);
24598 } else
24599 return (ret);
24600 if (error == 0)
24601 error = ret;
24602 break;
24603 }
24604 tmpType = tmpType->baseType;
24605 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024606
24607 return (error);
24608}
Daniel Veillarddee23482008-04-11 12:58:43 +000024609
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024610static xmlChar *
24611xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24612 const xmlChar *value)
24613{
Daniel Veillarddee23482008-04-11 12:58:43 +000024614 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024615 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24616 return (xmlSchemaCollapseString(value));
24617 case XML_SCHEMA_WHITESPACE_REPLACE:
24618 return (xmlSchemaWhiteSpaceReplace(value));
24619 default:
24620 return (NULL);
24621 }
24622}
24623
24624static int
24625xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24626 const xmlChar *value,
24627 xmlSchemaValPtr *val,
24628 int valNeeded)
24629{
24630 int ret;
24631 const xmlChar *nsName;
24632 xmlChar *local, *prefix = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000024633
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024634 ret = xmlValidateQName(value, 1);
24635 if (ret != 0) {
24636 if (ret == -1) {
24637 VERROR_INT("xmlSchemaValidateQName",
24638 "calling xmlValidateQName()");
24639 return (-1);
24640 }
24641 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24642 }
24643 /*
24644 * NOTE: xmlSplitQName2 will always return a duplicated
24645 * strings.
24646 */
24647 local = xmlSplitQName2(value, &prefix);
24648 if (local == NULL)
24649 local = xmlStrdup(value);
24650 /*
24651 * OPTIMIZE TODO: Use flags for:
24652 * - is there any namespace binding?
24653 * - is there a default namespace?
24654 */
24655 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
Daniel Veillarddee23482008-04-11 12:58:43 +000024656
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024657 if (prefix != NULL) {
24658 xmlFree(prefix);
24659 /*
24660 * A namespace must be found if the prefix is
24661 * NOT NULL.
24662 */
24663 if (nsName == NULL) {
24664 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024665 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024666 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024667 "The QName value '%s' has no "
24668 "corresponding namespace declaration in "
24669 "scope", value, NULL);
24670 if (local != NULL)
24671 xmlFree(local);
24672 return (ret);
24673 }
24674 }
24675 if (valNeeded && val) {
24676 if (nsName != NULL)
24677 *val = xmlSchemaNewQNameValue(
24678 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24679 else
24680 *val = xmlSchemaNewQNameValue(NULL,
24681 BAD_CAST local);
24682 } else
24683 xmlFree(local);
24684 return (0);
24685}
24686
24687/*
24688* cvc-simple-type
24689*/
24690static int
24691xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24692 xmlNodePtr node,
24693 xmlSchemaTypePtr type,
24694 const xmlChar *value,
24695 xmlSchemaValPtr *retVal,
24696 int fireErrors,
24697 int normalize,
24698 int isNormalized)
24699{
24700 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24701 xmlSchemaValPtr val = NULL;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024702 /* xmlSchemaWhitespaceValueType ws; */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024703 xmlChar *normValue = NULL;
24704
24705#define NORMALIZE(atype) \
24706 if ((! isNormalized) && \
24707 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24708 normValue = xmlSchemaNormalizeValue(atype, value); \
24709 if (normValue != NULL) \
24710 value = normValue; \
24711 isNormalized = 1; \
24712 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024713
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024714 if ((retVal != NULL) && (*retVal != NULL)) {
24715 xmlSchemaFreeValue(*retVal);
24716 *retVal = NULL;
24717 }
24718 /*
24719 * 3.14.4 Simple Type Definition Validation Rules
24720 * Validation Rule: String Valid
24721 */
24722 /*
24723 * 1 It is schema-valid with respect to that definition as defined
24724 * by Datatype Valid in [XML Schemas: Datatypes].
24725 */
24726 /*
24727 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
Jan Pokorný761c9e92013-11-29 23:26:27 +010024728 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24729 * the string must be a `declared entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024730 */
24731 /*
24732 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
Jan Pokorný761c9e92013-11-29 23:26:27 +010024733 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24734 * then every whitespace-delimited substring of the string must be a `declared
24735 * entity name`.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024736 */
24737 /*
24738 * 2.3 otherwise no further condition applies.
24739 */
24740 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24741 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000024742 if (value == NULL)
24743 value = BAD_CAST "";
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024744 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024745 xmlSchemaTypePtr biType; /* The built-in type. */
24746 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024747 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24748 * a literal in the `lexical space` of {base type definition}"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024749 */
24750 /*
24751 * Whitespace-normalize.
24752 */
24753 NORMALIZE(type);
24754 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24755 /*
24756 * Get the built-in type.
24757 */
24758 biType = type->baseType;
24759 while ((biType != NULL) &&
24760 (biType->type != XML_SCHEMA_TYPE_BASIC))
24761 biType = biType->baseType;
24762
24763 if (biType == NULL) {
24764 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24765 "could not get the built-in type");
24766 goto internal_error;
24767 }
24768 } else
24769 biType = type;
24770 /*
24771 * NOTATIONs need to be processed here, since they need
24772 * to lookup in the hashtable of NOTATION declarations of the schema.
24773 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024774 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24775 switch (biType->builtInType) {
24776 case XML_SCHEMAS_NOTATION:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024777 ret = xmlSchemaValidateNotation(
24778 (xmlSchemaValidCtxtPtr) actxt,
24779 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24780 NULL, value, &val, valNeeded);
24781 break;
24782 case XML_SCHEMAS_QNAME:
24783 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24784 value, &val, valNeeded);
24785 break;
24786 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024787 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024788 if (valNeeded)
24789 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024790 value, &val, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024791 else
24792 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
Wayne Jensen99f7ac72009-08-07 21:27:44 +020024793 value, NULL, node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024794 break;
24795 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024796 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24797 switch (biType->builtInType) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024798 case XML_SCHEMAS_NOTATION:
24799 ret = xmlSchemaValidateNotation(NULL,
24800 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24801 value, &val, valNeeded);
24802 break;
24803 default:
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000024804 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024805 if (valNeeded)
24806 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24807 value, &val, node);
24808 else
24809 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24810 value, NULL, node);
24811 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024812 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024813 } else {
24814 /*
24815 * Validation via a public API is not implemented yet.
24816 */
24817 TODO
24818 goto internal_error;
24819 }
24820 if (ret != 0) {
24821 if (ret < 0) {
24822 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24823 "validating against a built-in type");
24824 goto internal_error;
24825 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024826 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024827 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24828 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024829 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024830 }
24831 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24832 /*
24833 * Check facets.
24834 */
24835 ret = xmlSchemaValidateFacets(actxt, node, type,
24836 (xmlSchemaValType) biType->builtInType, value, val,
24837 0, fireErrors);
24838 if (ret != 0) {
24839 if (ret < 0) {
24840 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24841 "validating facets of atomic simple type");
24842 goto internal_error;
24843 }
Daniel Veillarddee23482008-04-11 12:58:43 +000024844 if (WXS_IS_LIST(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024845 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24846 else
Daniel Veillarddee23482008-04-11 12:58:43 +000024847 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024848 }
24849 }
Haibo Huangcfd91dc2020-07-30 23:01:33 -070024850 else if (fireErrors && (ret > 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024851 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024852 } else if (WXS_IS_LIST(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024853
24854 xmlSchemaTypePtr itemType;
24855 const xmlChar *cur, *end;
24856 xmlChar *tmpValue = NULL;
24857 unsigned long len = 0;
24858 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
Jan Pokorný761c9e92013-11-29 23:26:27 +010024859 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24860 * of white space separated tokens, each of which `match`es a literal
24861 * in the `lexical space` of {item type definition}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024862 */
24863 /*
24864 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24865 * the list type has an enum or pattern facet.
24866 */
24867 NORMALIZE(type);
24868 /*
24869 * VAL TODO: Optimize validation of empty values.
24870 * VAL TODO: We do not have computed values for lists.
24871 */
Daniel Veillarddee23482008-04-11 12:58:43 +000024872 itemType = WXS_LIST_ITEMTYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024873 cur = value;
24874 do {
24875 while (IS_BLANK_CH(*cur))
24876 cur++;
24877 end = cur;
24878 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24879 end++;
24880 if (end == cur)
24881 break;
24882 tmpValue = xmlStrndup(cur, end - cur);
24883 len++;
24884
24885 if (valNeeded)
24886 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24887 tmpValue, &curVal, fireErrors, 0, 1);
24888 else
24889 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24890 tmpValue, NULL, fireErrors, 0, 1);
24891 FREE_AND_NULL(tmpValue);
24892 if (curVal != NULL) {
24893 /*
24894 * Add to list of computed values.
24895 */
24896 if (val == NULL)
24897 val = curVal;
24898 else
24899 xmlSchemaValueAppend(prevVal, curVal);
24900 prevVal = curVal;
24901 curVal = NULL;
24902 }
24903 if (ret != 0) {
24904 if (ret < 0) {
24905 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24906 "validating an item of list simple type");
24907 goto internal_error;
24908 }
24909 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24910 break;
Daniel Veillarddee23482008-04-11 12:58:43 +000024911 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024912 cur = end;
24913 } while (*cur != 0);
24914 FREE_AND_NULL(tmpValue);
24915 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24916 /*
24917 * Apply facets (pattern, enumeration).
24918 */
24919 ret = xmlSchemaValidateFacets(actxt, node, type,
24920 XML_SCHEMAS_UNKNOWN, value, val,
24921 len, fireErrors);
24922 if (ret != 0) {
24923 if (ret < 0) {
24924 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24925 "validating facets of list simple type");
24926 goto internal_error;
24927 }
24928 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24929 }
24930 }
24931 if (fireErrors && (ret > 0)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024932 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024933 * Report the normalized value.
24934 */
24935 normalize = 1;
24936 NORMALIZE(type);
24937 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24938 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000024939 } else if (WXS_IS_UNION(type)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024940 xmlSchemaTypeLinkPtr memberLink;
24941 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024942 * TODO: For all datatypes `derived` by `union` whiteSpace does
24943 * not apply directly; however, the normalization behavior of `union`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024944 * types is controlled by the value of whiteSpace on that one of the
Jan Pokorný761c9e92013-11-29 23:26:27 +010024945 * `memberTypes` against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024946 *
24947 * This means that the value is normalized by the first validating
24948 * member type, then the facets of the union type are applied. This
24949 * needs changing of the value!
24950 */
24951
24952 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024953 * 1.2.3 if {variety} is `union` then the string must `match` a
24954 * literal in the `lexical space` of at least one member of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024955 * {member type definitions}
24956 */
24957 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24958 if (memberLink == NULL) {
24959 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24960 "union simple type has no member types");
24961 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000024962 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024963 /*
24964 * Always normalize union type values, since we currently
24965 * cannot store the whitespace information with the value
24966 * itself; otherwise a later value-comparison would be
24967 * not possible.
24968 */
24969 while (memberLink != NULL) {
Daniel Veillarddee23482008-04-11 12:58:43 +000024970 if (valNeeded)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024971 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24972 memberLink->type, value, &val, 0, 1, 0);
24973 else
24974 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24975 memberLink->type, value, NULL, 0, 1, 0);
24976 if (ret <= 0)
24977 break;
24978 memberLink = memberLink->next;
24979 }
24980 if (ret != 0) {
24981 if (ret < 0) {
24982 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24983 "validating members of union simple type");
24984 goto internal_error;
24985 }
24986 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24987 }
24988 /*
24989 * Apply facets (pattern, enumeration).
24990 */
24991 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24992 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010024993 * The normalization behavior of `union` types is controlled by
24994 * the value of whiteSpace on that one of the `memberTypes`
24995 * against which the `union` is successfully validated.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024996 */
24997 NORMALIZE(memberLink->type);
24998 ret = xmlSchemaValidateFacets(actxt, node, type,
24999 XML_SCHEMAS_UNKNOWN, value, val,
25000 0, fireErrors);
25001 if (ret != 0) {
25002 if (ret < 0) {
25003 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25004 "validating facets of union simple type");
25005 goto internal_error;
25006 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025007 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025008 }
25009 }
25010 if (fireErrors && (ret > 0))
25011 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25012 }
25013
25014 if (normValue != NULL)
25015 xmlFree(normValue);
25016 if (ret == 0) {
25017 if (retVal != NULL)
25018 *retVal = val;
25019 else if (val != NULL)
25020 xmlSchemaFreeValue(val);
25021 } else if (val != NULL)
25022 xmlSchemaFreeValue(val);
25023 return (ret);
25024internal_error:
25025 if (normValue != NULL)
25026 xmlFree(normValue);
25027 if (val != NULL)
25028 xmlSchemaFreeValue(val);
25029 return (-1);
25030}
25031
25032static int
25033xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25034 const xmlChar *value,
25035 const xmlChar **nsName,
25036 const xmlChar **localName)
25037{
25038 int ret = 0;
25039
25040 if ((nsName == NULL) || (localName == NULL))
25041 return (-1);
25042 *nsName = NULL;
25043 *localName = NULL;
25044
25045 ret = xmlValidateQName(value, 1);
25046 if (ret == -1)
25047 return (-1);
25048 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025049 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025050 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25051 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25052 return (1);
25053 }
25054 {
25055 xmlChar *local = NULL;
25056 xmlChar *prefix;
25057
25058 /*
25059 * NOTE: xmlSplitQName2 will return a duplicated
25060 * string.
25061 */
25062 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025063 if (local == NULL)
25064 *localName = xmlDictLookup(vctxt->dict, value, -1);
25065 else {
25066 *localName = xmlDictLookup(vctxt->dict, local, -1);
25067 xmlFree(local);
25068 }
25069
25070 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25071
25072 if (prefix != NULL) {
25073 xmlFree(prefix);
25074 /*
25075 * A namespace must be found if the prefix is NOT NULL.
25076 */
25077 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025078 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025079 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025080 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025081 "The QName value '%s' has no "
25082 "corresponding namespace declaration in scope",
25083 value, NULL);
25084 return (2);
25085 }
25086 }
25087 }
25088 return (0);
25089}
25090
25091static int
25092xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25093 xmlSchemaAttrInfoPtr iattr,
25094 xmlSchemaTypePtr *localType,
25095 xmlSchemaElementPtr elemDecl)
25096{
25097 int ret = 0;
25098 /*
25099 * cvc-elt (3.3.4) : (4)
25100 * AND
25101 * Schema-Validity Assessment (Element) (cvc-assess-elt)
25102 * (1.2.1.2.1) - (1.2.1.2.4)
25103 * Handle 'xsi:type'.
25104 */
25105 if (localType == NULL)
25106 return (-1);
25107 *localType = NULL;
25108 if (iattr == NULL)
25109 return (0);
25110 else {
25111 const xmlChar *nsName = NULL, *local = NULL;
25112 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070025113 * TODO: We should report a *warning* that the type was overridden
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025114 * by the instance.
25115 */
25116 ACTIVATE_ATTRIBUTE(iattr);
25117 /*
25118 * (cvc-elt) (3.3.4) : (4.1)
25119 * (cvc-assess-elt) (1.2.1.2.2)
25120 */
25121 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25122 &nsName, &local);
25123 if (ret != 0) {
25124 if (ret < 0) {
25125 VERROR_INT("xmlSchemaValidateElementByDeclaration",
25126 "calling xmlSchemaQNameExpand() to validate the "
25127 "attribute 'xsi:type'");
25128 goto internal_error;
25129 }
25130 goto exit;
25131 }
25132 /*
25133 * (cvc-elt) (3.3.4) : (4.2)
25134 * (cvc-assess-elt) (1.2.1.2.3)
25135 */
25136 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25137 if (*localType == NULL) {
25138 xmlChar *str = NULL;
25139
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025140 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025141 XML_SCHEMAV_CVC_ELT_4_2, NULL,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025142 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025143 "The QName value '%s' of the xsi:type attribute does not "
25144 "resolve to a type definition",
25145 xmlSchemaFormatQName(&str, nsName, local), NULL);
25146 FREE_AND_NULL(str);
25147 ret = vctxt->err;
25148 goto exit;
25149 }
25150 if (elemDecl != NULL) {
25151 int set = 0;
25152
25153 /*
25154 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025155 * "The `local type definition` must be validly
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025156 * derived from the {type definition} given the union of
25157 * the {disallowed substitutions} and the {type definition}'s
25158 * {prohibited substitutions}, as defined in
Jan Pokorný761c9e92013-11-29 23:26:27 +010025159 * Type Derivation OK (Complex) ($3.4.6)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025160 * (if it is a complex type definition),
25161 * or given {disallowed substitutions} as defined in Type
Jan Pokorný761c9e92013-11-29 23:26:27 +010025162 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025163 * definition)."
25164 *
25165 * {disallowed substitutions}: the "block" on the element decl.
25166 * {prohibited substitutions}: the "block" on the type def.
25167 */
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000025168 /*
25169 * OPTIMIZE TODO: We could map types already evaluated
25170 * to be validly derived from other types to avoid checking
25171 * this over and over for the same types.
25172 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025173 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25174 (elemDecl->subtypes->flags &
25175 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25176 set |= SUBSET_EXTENSION;
25177
25178 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25179 (elemDecl->subtypes->flags &
25180 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25181 set |= SUBSET_RESTRICTION;
25182
Kasimier T. Buchcikf326e772005-10-20 11:06:00 +000025183 /*
25184 * REMOVED and CHANGED since this produced a parser context
25185 * which adds to the string dict of the schema. So this would
25186 * change the schema and we don't want this. We don't need
25187 * the parser context anymore.
25188 *
25189 * if ((vctxt->pctxt == NULL) &&
25190 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25191 * return (-1);
25192 */
25193
25194 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025195 elemDecl->subtypes, set) != 0) {
25196 xmlChar *str = NULL;
25197
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025198 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025199 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25200 "The type definition '%s', specified by xsi:type, is "
25201 "blocked or not validly derived from the type definition "
25202 "of the element declaration",
25203 xmlSchemaFormatQName(&str,
25204 (*localType)->targetNamespace,
25205 (*localType)->name),
25206 NULL);
25207 FREE_AND_NULL(str);
25208 ret = vctxt->err;
25209 *localType = NULL;
25210 }
25211 }
25212 }
25213exit:
25214 ACTIVATE_ELEM;
25215 return (ret);
25216internal_error:
25217 ACTIVATE_ELEM;
25218 return (-1);
25219}
25220
25221static int
25222xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25223{
25224 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
Daniel Veillard14b56432006-03-09 18:41:40 +000025225 xmlSchemaTypePtr actualType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025226
25227 /*
25228 * cvc-elt (3.3.4) : 1
25229 */
25230 if (elemDecl == NULL) {
25231 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25232 "No matching declaration available");
25233 return (vctxt->err);
25234 }
Daniel Veillard14b56432006-03-09 18:41:40 +000025235 actualType = WXS_ELEM_TYPEDEF(elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025236 /*
25237 * cvc-elt (3.3.4) : 2
25238 */
25239 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25240 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25241 "The element declaration is abstract");
25242 return (vctxt->err);
25243 }
25244 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025245 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25246 "The type definition is absent");
25247 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025248 }
25249 if (vctxt->nbAttrInfos != 0) {
25250 int ret;
25251 xmlSchemaAttrInfoPtr iattr;
25252 /*
25253 * cvc-elt (3.3.4) : 3
25254 * Handle 'xsi:nil'.
25255 */
25256 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25257 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25258 if (iattr) {
25259 ACTIVATE_ATTRIBUTE(iattr);
25260 /*
25261 * Validate the value.
25262 */
25263 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025264 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025265 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25266 iattr->value, &(iattr->val), 1, 0, 0);
25267 ACTIVATE_ELEM;
25268 if (ret < 0) {
25269 VERROR_INT("xmlSchemaValidateElemDecl",
25270 "calling xmlSchemaVCheckCVCSimpleType() to "
25271 "validate the attribute 'xsi:nil'");
25272 return (-1);
25273 }
25274 if (ret == 0) {
25275 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25276 /*
25277 * cvc-elt (3.3.4) : 3.1
25278 */
25279 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25280 "The element is not 'nillable'");
25281 /* Does not return an error on purpose. */
25282 } else {
25283 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25284 /*
25285 * cvc-elt (3.3.4) : 3.2.2
25286 */
25287 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25288 (elemDecl->value != NULL)) {
25289 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25290 "The element cannot be 'nilled' because "
25291 "there is a fixed value constraint defined "
25292 "for it");
25293 /* Does not return an error on purpose. */
25294 } else
25295 vctxt->inode->flags |=
25296 XML_SCHEMA_ELEM_INFO_NILLED;
25297 }
25298 }
25299 }
25300 }
25301 /*
25302 * cvc-elt (3.3.4) : 4
25303 * Handle 'xsi:type'.
25304 */
25305 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25306 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25307 if (iattr) {
25308 xmlSchemaTypePtr localType = NULL;
25309
25310 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25311 elemDecl);
25312 if (ret != 0) {
25313 if (ret == -1) {
25314 VERROR_INT("xmlSchemaValidateElemDecl",
25315 "calling xmlSchemaProcessXSIType() to "
25316 "process the attribute 'xsi:type'");
25317 return (-1);
25318 }
25319 /* Does not return an error on purpose. */
25320 }
25321 if (localType != NULL) {
25322 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25323 actualType = localType;
25324 }
25325 }
25326 }
25327 /*
25328 * IDC: Register identity-constraint XPath matchers.
25329 */
25330 if ((elemDecl->idcs != NULL) &&
25331 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25332 return (-1);
25333 /*
25334 * No actual type definition.
25335 */
25336 if (actualType == NULL) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +080025337 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25338 "The type definition is absent");
25339 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025340 }
25341 /*
25342 * Remember the actual type definition.
25343 */
25344 vctxt->inode->typeDef = actualType;
25345
25346 return (0);
25347}
25348
25349static int
25350xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25351{
25352 xmlSchemaAttrInfoPtr iattr;
25353 int ret = 0, i;
25354
25355 /*
25356 * SPEC cvc-type (3.1.1)
25357 * "The attributes of must be empty, excepting those whose namespace
25358 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25359 * whose local name is one of type, nil, schemaLocation or
25360 * noNamespaceSchemaLocation."
25361 */
25362 if (vctxt->nbAttrInfos == 0)
25363 return (0);
25364 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25365 iattr = vctxt->attrInfos[i];
25366 if (! iattr->metaType) {
25367 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025368 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025369 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25370 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25371 }
25372 }
25373 ACTIVATE_ELEM
25374 return (ret);
25375}
25376
25377/*
25378* Cleanup currently used attribute infos.
25379*/
25380static void
25381xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25382{
25383 int i;
25384 xmlSchemaAttrInfoPtr attr;
25385
25386 if (vctxt->nbAttrInfos == 0)
25387 return;
25388 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25389 attr = vctxt->attrInfos[i];
25390 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25391 if (attr->localName != NULL)
25392 xmlFree((xmlChar *) attr->localName);
25393 if (attr->nsName != NULL)
25394 xmlFree((xmlChar *) attr->nsName);
25395 }
25396 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25397 if (attr->value != NULL)
25398 xmlFree((xmlChar *) attr->value);
25399 }
25400 if (attr->val != NULL) {
25401 xmlSchemaFreeValue(attr->val);
25402 attr->val = NULL;
25403 }
25404 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25405 }
25406 vctxt->nbAttrInfos = 0;
25407}
25408
25409/*
25410* 3.4.4 Complex Type Definition Validation Rules
25411* Element Locally Valid (Complex Type) (cvc-complex-type)
25412* 3.2.4 Attribute Declaration Validation Rules
25413* Validation Rule: Attribute Locally Valid (cvc-attribute)
25414* Attribute Locally Valid (Use) (cvc-au)
25415*
25416* Only "assessed" attribute information items will be visible to
25417* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25418*/
25419static int
25420xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25421{
Daniel Veillarddee23482008-04-11 12:58:43 +000025422 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025423 xmlSchemaItemListPtr attrUseList;
25424 xmlSchemaAttributeUsePtr attrUse = NULL;
25425 xmlSchemaAttributePtr attrDecl = NULL;
Daniel Veillarddee23482008-04-11 12:58:43 +000025426 xmlSchemaAttrInfoPtr iattr, tmpiattr;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025427 int i, j, found, nbAttrs, nbUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025428 int xpathRes = 0, res, wildIDs = 0, fixed;
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025429 xmlNodePtr defAttrOwnerElem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025430
25431 /*
25432 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025433 * (1) "The declaration must not be `absent` (see Missing
25434 * Sub-components ($5.3) for how this can fail to be
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025435 * the case)."
25436 * (2) "Its {type definition} must not be absent."
25437 *
25438 * NOTE (1) + (2): This is not handled here, since we currently do not
25439 * allow validation against schemas which have missing sub-components.
25440 *
25441 * SPEC (cvc-complex-type)
25442 * (3) "For each attribute information item in the element information
25443 * item's [attributes] excepting those whose [namespace name] is
25444 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25445 * [local name] is one of type, nil, schemaLocation or
25446 * noNamespaceSchemaLocation, the appropriate case among the following
25447 * must be true:
25448 *
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025449 */
25450 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25451 /*
25452 * @nbAttrs is the number of attributes present in the instance.
25453 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025454 nbAttrs = vctxt->nbAttrInfos;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025455 if (attrUseList != NULL)
25456 nbUses = attrUseList->nbItems;
25457 else
25458 nbUses = 0;
25459 for (i = 0; i < nbUses; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025460 found = 0;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025461 attrUse = attrUseList->items[i];
25462 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25463 for (j = 0; j < nbAttrs; j++) {
25464 iattr = vctxt->attrInfos[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025465 /*
25466 * SPEC (cvc-complex-type) (3)
25467 * Skip meta attributes.
25468 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025469 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025470 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025471 if (iattr->localName[0] != attrDecl->name[0])
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025472 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025473 if (!xmlStrEqual(iattr->localName, attrDecl->name))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025474 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025475 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025476 continue;
25477 found = 1;
25478 /*
25479 * SPEC (cvc-complex-type)
25480 * (3.1) "If there is among the {attribute uses} an attribute
25481 * use with an {attribute declaration} whose {name} matches
25482 * the attribute information item's [local name] and whose
25483 * {target namespace} is identical to the attribute information
Jan Pokorný761c9e92013-11-29 23:26:27 +010025484 * item's [namespace name] (where an `absent` {target namespace}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025485 * is taken to be identical to a [namespace name] with no value),
Jan Pokorný761c9e92013-11-29 23:26:27 +010025486 * then the attribute information must be `valid` with respect
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025487 * to that attribute use as per Attribute Locally Valid (Use)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025488 * ($3.5.4). In this case the {attribute declaration} of that
25489 * attribute use is the `context-determined declaration` for the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025490 * attribute information item with respect to Schema-Validity
Jan Pokorný761c9e92013-11-29 23:26:27 +010025491 * Assessment (Attribute) ($3.2.4) and
25492 * Assessment Outcome (Attribute) ($3.2.5).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025493 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025494 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25495 iattr->use = attrUse;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025496 /*
25497 * Context-determined declaration.
25498 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025499 iattr->decl = attrDecl;
25500 iattr->typeDef = attrDecl->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025501 break;
25502 }
25503
25504 if (found)
25505 continue;
25506
25507 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25508 /*
25509 * Handle non-existent, required attributes.
25510 *
25511 * SPEC (cvc-complex-type)
25512 * (4) "The {attribute declaration} of each attribute use in
25513 * the {attribute uses} whose {required} is true matches one
25514 * of the attribute information items in the element information
25515 * item's [attributes] as per clause 3.1 above."
25516 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025517 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25518 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025519 VERROR_INT(
25520 "xmlSchemaVAttributesComplex",
25521 "calling xmlSchemaGetFreshAttrInfo()");
25522 return (-1);
25523 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025524 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25525 tmpiattr->use = attrUse;
Daniel Veillarddee23482008-04-11 12:58:43 +000025526 tmpiattr->decl = attrDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025527 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25528 ((attrUse->defValue != NULL) ||
25529 (attrDecl->defValue != NULL))) {
25530 /*
25531 * Handle non-existent, optional, default/fixed attributes.
25532 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025533 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25534 if (tmpiattr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025535 VERROR_INT(
25536 "xmlSchemaVAttributesComplex",
25537 "calling xmlSchemaGetFreshAttrInfo()");
25538 return (-1);
25539 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025540 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25541 tmpiattr->use = attrUse;
25542 tmpiattr->decl = attrDecl;
25543 tmpiattr->typeDef = attrDecl->subtypes;
25544 tmpiattr->localName = attrDecl->name;
25545 tmpiattr->nsName = attrDecl->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025546 }
25547 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025549 if (vctxt->nbAttrInfos == 0)
25550 return (0);
25551 /*
25552 * Validate against the wildcard.
25553 */
25554 if (type->attributeWildcard != NULL) {
25555 /*
25556 * SPEC (cvc-complex-type)
25557 * (3.2.1) "There must be an {attribute wildcard}."
25558 */
25559 for (i = 0; i < nbAttrs; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025560 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025561 /*
25562 * SPEC (cvc-complex-type) (3)
25563 * Skip meta attributes.
25564 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025565 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025566 continue;
25567 /*
25568 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025569 * (3.2.2) "The attribute information item must be `valid` with
25570 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025571 *
25572 * SPEC Item Valid (Wildcard) (cvc-wildcard)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025573 * "... its [namespace name] must be `valid` with respect to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025574 * the wildcard constraint, as defined in Wildcard allows
Jan Pokorný761c9e92013-11-29 23:26:27 +010025575 * Namespace Name ($3.10.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025576 */
25577 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025578 iattr->nsName) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025579 /*
25580 * Handle processContents.
25581 *
25582 * SPEC (cvc-wildcard):
25583 * processContents | context-determined declaration:
25584 * "strict" "mustFind"
25585 * "lax" "none"
25586 * "skip" "skip"
25587 */
25588 if (type->attributeWildcard->processContents ==
25589 XML_SCHEMAS_ANY_SKIP) {
25590 /*
25591 * context-determined declaration = "skip"
25592 *
25593 * SPEC PSVI Assessment Outcome (Attribute)
25594 * [validity] = "notKnown"
25595 * [validation attempted] = "none"
25596 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025597 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025598 continue;
25599 }
25600 /*
25601 * Find an attribute declaration.
25602 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025603 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25604 iattr->localName, iattr->nsName);
25605 if (iattr->decl != NULL) {
25606 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025607 /*
25608 * SPEC (cvc-complex-type)
25609 * (5) "Let [Definition:] the wild IDs be the set of
25610 * all attribute information item to which clause 3.2
Jan Pokorný761c9e92013-11-29 23:26:27 +010025611 * applied and whose `validation` resulted in a
25612 * `context-determined declaration` of mustFind or no
25613 * `context-determined declaration` at all, and whose
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025614 * [local name] and [namespace name] resolve (as
Jan Pokorný761c9e92013-11-29 23:26:27 +010025615 * defined by QName resolution (Instance) ($3.15.4)) to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025616 * an attribute declaration whose {type definition} is
25617 * or is derived from ID. Then all of the following
25618 * must be true:"
25619 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025620 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025621 if (xmlSchemaIsDerivedFromBuiltInType(
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025622 iattr->typeDef, XML_SCHEMAS_ID)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025623 /*
25624 * SPEC (5.1) "There must be no more than one
Jan Pokorný761c9e92013-11-29 23:26:27 +010025625 * item in `wild IDs`."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025626 */
25627 if (wildIDs != 0) {
25628 /* VAL TODO */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025629 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025630 TODO
25631 continue;
25632 }
25633 wildIDs++;
25634 /*
25635 * SPEC (cvc-complex-type)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025636 * (5.2) "If `wild IDs` is non-empty, there must not
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025637 * be any attribute uses among the {attribute uses}
25638 * whose {attribute declaration}'s {type definition}
25639 * is or is derived from ID."
25640 */
Daniel Veillard2cdd17e2009-07-27 21:16:13 +020025641 if (attrUseList != NULL) {
25642 for (j = 0; j < attrUseList->nbItems; j++) {
25643 if (xmlSchemaIsDerivedFromBuiltInType(
25644 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25645 XML_SCHEMAS_ID)) {
25646 /* URGENT VAL TODO: implement */
25647 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25648 TODO
25649 break;
25650 }
25651 }
25652 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025653 }
25654 } else if (type->attributeWildcard->processContents ==
25655 XML_SCHEMAS_ANY_LAX) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025656 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025657 /*
25658 * SPEC PSVI Assessment Outcome (Attribute)
25659 * [validity] = "notKnown"
25660 * [validation attempted] = "none"
25661 */
25662 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025663 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025664 }
25665 }
25666 }
25667 }
25668
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025669 if (vctxt->nbAttrInfos == 0)
25670 return (0);
25671
25672 /*
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025673 * Get the owner element; needed for creation of default attributes.
25674 * This fixes bug #341337, reported by David Grohmann.
25675 */
25676 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25677 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25678 if (ielem && ielem->node && ielem->node->doc)
25679 defAttrOwnerElem = ielem->node;
25680 }
25681 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025682 * Validate values, create default attributes, evaluate IDCs.
25683 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025684 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025685 iattr = vctxt->attrInfos[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025686 /*
25687 * VAL TODO: Note that we won't try to resolve IDCs to
25688 * "lax" and "skip" validated attributes. Check what to
25689 * do in this case.
25690 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025691 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25692 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025693 continue;
25694 /*
25695 * VAL TODO: What to do if the type definition is missing?
25696 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025697 if (iattr->typeDef == NULL) {
25698 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025699 continue;
25700 }
25701
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025702 ACTIVATE_ATTRIBUTE(iattr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000025703 fixed = 0;
25704 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025705
25706 if (vctxt->xpathStates != NULL) {
25707 /*
25708 * Evaluate IDCs.
25709 */
25710 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25711 XML_ATTRIBUTE_NODE);
25712 if (xpathRes == -1) {
25713 VERROR_INT("xmlSchemaVAttributesComplex",
25714 "calling xmlSchemaXPathEvaluate()");
25715 goto internal_error;
25716 }
25717 }
25718
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025719 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025720 /*
25721 * Default/fixed attributes.
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025722 * We need the value only if we need to resolve IDCs or
25723 * will create default attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025724 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025725 if ((xpathRes) || (defAttrOwnerElem)) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025726 if (iattr->use->defValue != NULL) {
25727 iattr->value = (xmlChar *) iattr->use->defValue;
25728 iattr->val = iattr->use->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025729 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025730 iattr->value = (xmlChar *) iattr->decl->defValue;
25731 iattr->val = iattr->decl->defVal;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025732 }
25733 /*
25734 * IDCs will consume the precomputed default value,
25735 * so we need to clone it.
25736 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025737 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025738 VERROR_INT("xmlSchemaVAttributesComplex",
25739 "default/fixed value on an attribute use was "
25740 "not precomputed");
25741 goto internal_error;
25742 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025743 iattr->val = xmlSchemaCopyValue(iattr->val);
25744 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025745 VERROR_INT("xmlSchemaVAttributesComplex",
25746 "calling xmlSchemaCopyValue()");
25747 goto internal_error;
25748 }
25749 }
25750 /*
25751 * PSVI: Add the default attribute to the current element.
25752 * VAL TODO: Should we use the *normalized* value? This currently
25753 * uses the *initial* value.
25754 */
Daniel Veillarddee23482008-04-11 12:58:43 +000025755
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025756 if (defAttrOwnerElem) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025757 xmlChar *normValue;
25758 const xmlChar *value;
25759
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025760 value = iattr->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025761 /*
25762 * Normalize the value.
25763 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025764 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25765 iattr->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025766 if (normValue != NULL)
25767 value = BAD_CAST normValue;
25768
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025769 if (iattr->nsName == NULL) {
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025770 if (xmlNewProp(defAttrOwnerElem,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025771 iattr->localName, value) == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025772 VERROR_INT("xmlSchemaVAttributesComplex",
Alex Henrie73c50802015-10-26 18:33:14 +080025773 "calling xmlNewProp()");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025774 if (normValue != NULL)
25775 xmlFree(normValue);
25776 goto internal_error;
25777 }
25778 } else {
25779 xmlNsPtr ns;
25780
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025781 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25782 defAttrOwnerElem, iattr->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025783 if (ns == NULL) {
25784 xmlChar prefix[12];
25785 int counter = 0;
25786
25787 /*
25788 * Create a namespace declaration on the validation
25789 * root node if no namespace declaration is in scope.
25790 */
25791 do {
25792 snprintf((char *) prefix, 12, "p%d", counter++);
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025793 ns = xmlSearchNs(defAttrOwnerElem->doc,
25794 defAttrOwnerElem, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025795 if (counter > 1000) {
25796 VERROR_INT(
25797 "xmlSchemaVAttributesComplex",
25798 "could not compute a ns prefix for a "
25799 "default/fixed attribute");
25800 if (normValue != NULL)
25801 xmlFree(normValue);
25802 goto internal_error;
25803 }
25804 } while (ns != NULL);
25805 ns = xmlNewNs(vctxt->validationRoot,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025806 iattr->nsName, BAD_CAST prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025807 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025808 /*
25809 * TODO:
25810 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25811 * If we have QNames: do we need to ensure there's a
25812 * prefix defined for the QName?
25813 */
Kasimier T. Buchcik9b02e292006-05-11 16:25:44 +000025814 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025815 }
25816 if (normValue != NULL)
25817 xmlFree(normValue);
25818 }
25819 /*
25820 * Go directly to IDC evaluation.
25821 */
25822 goto eval_idcs;
25823 }
25824 /*
25825 * Validate the value.
25826 */
25827 if (vctxt->value != NULL) {
25828 /*
25829 * Free last computed value; just for safety reasons.
25830 */
25831 xmlSchemaFreeValue(vctxt->value);
25832 vctxt->value = NULL;
25833 }
25834 /*
25835 * Note that the attribute *use* can be unavailable, if
25836 * the attribute was a wild attribute.
25837 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025838 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25839 ((iattr->use != NULL) &&
25840 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025841 fixed = 1;
25842 else
25843 fixed = 0;
25844 /*
25845 * SPEC (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025846 * (3) "The item's `normalized value` must be locally `valid`
Daniel Veillarddee23482008-04-11 12:58:43 +000025847 * with respect to that {type definition} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010025848 * String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025849 *
25850 * VAL TODO: Do we already have the
25851 * "normalized attribute value" here?
25852 */
25853 if (xpathRes || fixed) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025854 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025855 /*
25856 * Request a computed value.
25857 */
25858 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025859 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025860 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025861 1, 1, 0);
25862 } else {
25863 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025864 ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025865 iattr->node, iattr->typeDef, iattr->value, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025866 1, 0, 0);
25867 }
Daniel Veillarddee23482008-04-11 12:58:43 +000025868
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025869 if (res != 0) {
25870 if (res == -1) {
25871 VERROR_INT("xmlSchemaVAttributesComplex",
25872 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25873 goto internal_error;
25874 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025875 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025876 /*
25877 * SPEC PSVI Assessment Outcome (Attribute)
25878 * [validity] = "invalid"
25879 */
25880 goto eval_idcs;
25881 }
25882
Daniel Veillarddee23482008-04-11 12:58:43 +000025883 if (fixed) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025884 /*
25885 * SPEC Attribute Locally Valid (Use) (cvc-au)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025886 * "For an attribute information item to be `valid`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025887 * with respect to an attribute use its *normalized*
Jan Pokorný761c9e92013-11-29 23:26:27 +010025888 * value must match the *canonical* lexical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025889 * representation of the attribute use's {value
25890 * constraint}value, if it is present and fixed."
25891 *
25892 * VAL TODO: The requirement for the *canonical* value
25893 * will be removed in XML Schema 1.1.
25894 */
25895 /*
25896 * SPEC Attribute Locally Valid (cvc-attribute)
Jan Pokorný761c9e92013-11-29 23:26:27 +010025897 * (4) "The item's *actual* value must match the *value* of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025898 * the {value constraint}, if it is present and fixed."
25899 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025900 if (iattr->val == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025901 /* VAL TODO: A value was not precomputed. */
25902 TODO
25903 goto eval_idcs;
25904 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025905 if ((iattr->use != NULL) &&
25906 (iattr->use->defValue != NULL)) {
25907 if (iattr->use->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025908 /* VAL TODO: A default value was not precomputed. */
25909 TODO
25910 goto eval_idcs;
25911 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025912 iattr->vcValue = iattr->use->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025913 /*
25914 if (xmlSchemaCompareValuesWhtsp(attr->val,
25915 (xmlSchemaWhitespaceValueType) ws,
25916 attr->use->defVal,
25917 (xmlSchemaWhitespaceValueType) ws) != 0) {
25918 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025919 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25920 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025921 } else {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025922 if (iattr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025923 /* VAL TODO: A default value was not precomputed. */
25924 TODO
25925 goto eval_idcs;
25926 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025927 iattr->vcValue = iattr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025928 /*
25929 if (xmlSchemaCompareValuesWhtsp(attr->val,
25930 (xmlSchemaWhitespaceValueType) ws,
25931 attrDecl->defVal,
25932 (xmlSchemaWhitespaceValueType) ws) != 0) {
25933 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025934 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25935 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025936 }
25937 /*
25938 * [validity] = "valid"
25939 */
25940 }
25941eval_idcs:
25942 /*
25943 * Evaluate IDCs.
25944 */
25945 if (xpathRes) {
25946 if (xmlSchemaXPathProcessHistory(vctxt,
25947 vctxt->depth +1) == -1) {
25948 VERROR_INT("xmlSchemaVAttributesComplex",
25949 "calling xmlSchemaXPathEvaluate()");
25950 goto internal_error;
25951 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000025952 } else if (vctxt->xpathStates != NULL)
25953 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025954 }
25955
25956 /*
25957 * Report errors.
25958 */
25959 for (i = 0; i < vctxt->nbAttrInfos; i++) {
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025960 iattr = vctxt->attrInfos[i];
25961 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25962 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25963 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25964 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025965 continue;
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025966 ACTIVATE_ATTRIBUTE(iattr);
25967 switch (iattr->state) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025968 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25969 xmlChar *str = NULL;
25970 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025971 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025972 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25973 "The attribute '%s' is required but missing",
25974 xmlSchemaFormatQName(&str,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025975 iattr->decl->targetNamespace,
25976 iattr->decl->name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025977 NULL);
25978 FREE_AND_NULL(str)
25979 break;
25980 }
25981 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25982 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25983 "The type definition is absent");
25984 break;
25985 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025986 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025987 XML_SCHEMAV_CVC_AU, NULL, NULL,
25988 "The value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000025989 "value constraint '%s'",
25990 iattr->value, iattr->vcValue);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025991 break;
25992 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25993 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25994 "No matching global attribute declaration available, but "
25995 "demanded by the strict wildcard");
25996 break;
25997 case XML_SCHEMAS_ATTR_UNKNOWN:
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000025998 if (iattr->metaType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025999 break;
26000 /*
26001 * MAYBE VAL TODO: One might report different error messages
26002 * for the following errors.
26003 */
26004 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026005 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026006 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026007 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026008 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026009 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026010 }
26011 break;
26012 default:
26013 break;
26014 }
26015 }
26016
26017 ACTIVATE_ELEM;
26018 return (0);
26019internal_error:
26020 ACTIVATE_ELEM;
26021 return (-1);
26022}
26023
26024static int
26025xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26026 int *skip)
26027{
26028 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26029 /*
26030 * The namespace of the element was already identified to be
26031 * matching the wildcard.
26032 */
26033 if ((skip == NULL) || (wild == NULL) ||
26034 (wild->type != XML_SCHEMA_TYPE_ANY)) {
26035 VERROR_INT("xmlSchemaValidateElemWildcard",
26036 "bad arguments");
26037 return (-1);
26038 }
26039 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026040 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26041 /*
26042 * URGENT VAL TODO: Either we need to position the stream to the
26043 * next sibling, or walk the whole subtree.
26044 */
26045 *skip = 1;
26046 return (0);
26047 }
26048 {
26049 xmlSchemaElementPtr decl = NULL;
26050
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026051 decl = xmlSchemaGetElem(vctxt->schema,
Daniel Veillarddee23482008-04-11 12:58:43 +000026052 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026053 if (decl != NULL) {
26054 vctxt->inode->decl = decl;
26055 return (0);
26056 }
26057 }
26058 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26059 /* VAL TODO: Change to proper error code. */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026060 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026061 "No matching global element declaration available, but "
26062 "demanded by the strict wildcard");
26063 return (vctxt->err);
26064 }
26065 if (vctxt->nbAttrInfos != 0) {
26066 xmlSchemaAttrInfoPtr iattr;
26067 /*
26068 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26069 * (1.2.1.2.1) - (1.2.1.2.3 )
26070 *
26071 * Use the xsi:type attribute for the type definition.
26072 */
26073 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26074 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26075 if (iattr != NULL) {
26076 if (xmlSchemaProcessXSIType(vctxt, iattr,
26077 &(vctxt->inode->typeDef), NULL) == -1) {
26078 VERROR_INT("xmlSchemaValidateElemWildcard",
26079 "calling xmlSchemaProcessXSIType() to "
26080 "process the attribute 'xsi:nil'");
26081 return (-1);
26082 }
26083 /*
26084 * Don't return an error on purpose.
26085 */
26086 return (0);
26087 }
26088 }
26089 /*
26090 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26091 *
26092 * Fallback to "anyType".
26093 */
26094 vctxt->inode->typeDef =
26095 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26096 return (0);
26097}
26098
26099/*
26100* xmlSchemaCheckCOSValidDefault:
26101*
26102* This will be called if: not nilled, no content and a default/fixed
26103* value is provided.
26104*/
26105
26106static int
26107xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26108 const xmlChar *value,
26109 xmlSchemaValPtr *val)
Daniel Veillarddee23482008-04-11 12:58:43 +000026110{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026111 int ret = 0;
26112 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26113
26114 /*
26115 * cos-valid-default:
26116 * Schema Component Constraint: Element Default Valid (Immediate)
Daniel Veillarddee23482008-04-11 12:58:43 +000026117 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026118 * definition the appropriate case among the following must be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000026119 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026120 if WXS_IS_COMPLEX(inode->typeDef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026121 /*
26122 * Complex type.
26123 *
26124 * SPEC (2.1) "its {content type} must be a simple type definition
26125 * or mixed."
26126 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Jan Pokorný761c9e92013-11-29 23:26:27 +010026127 * type}'s particle must be `emptiable` as defined by
26128 * Particle Emptiable ($3.9.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026129 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026130 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26131 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26132 (! WXS_EMPTIABLE(inode->typeDef)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026133 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26134 /* NOTE that this covers (2.2.2) as well. */
26135 VERROR(ret, NULL,
26136 "For a string to be a valid default, the type definition "
26137 "must be a simple type or a complex type with simple content "
26138 "or mixed content and a particle emptiable");
26139 return(ret);
26140 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026141 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026142 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026143 * 1 If the type definition is a simple type definition, then the string
Jan Pokorný761c9e92013-11-29 23:26:27 +010026144 * must be `valid` with respect to that definition as defined by String
26145 * Valid ($3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026146 *
26147 * AND
26148 *
Daniel Veillarddee23482008-04-11 12:58:43 +000026149 * 2.2.1 If the {content type} is a simple type definition, then the
Jan Pokorný761c9e92013-11-29 23:26:27 +010026150 * string must be `valid` with respect to that simple type definition
26151 * as defined by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026152 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026153 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026154
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026155 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026156 NULL, inode->typeDef, value, val, 1, 1, 0);
26157
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026158 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026159
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026160 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026161 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26162 }
26163 if (ret < 0) {
26164 VERROR_INT("xmlSchemaCheckCOSValidDefault",
26165 "calling xmlSchemaVCheckCVCSimpleType()");
Daniel Veillarddee23482008-04-11 12:58:43 +000026166 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026167 return (ret);
26168}
26169
26170static void
Nick Wellnhofere5f33e52017-11-09 17:29:22 +010026171xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026172 const xmlChar * name ATTRIBUTE_UNUSED,
Nick Wellnhofere5f33e52017-11-09 17:29:22 +010026173 void *transdata, void *inputdata)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026174{
Nick Wellnhofere5f33e52017-11-09 17:29:22 +010026175 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26176 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026177 inode->decl = item;
26178#ifdef DEBUG_CONTENT
26179 {
26180 xmlChar *str = NULL;
26181
26182 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26183 xmlGenericError(xmlGenericErrorContext,
26184 "AUTOMATON callback for '%s' [declaration]\n",
26185 xmlSchemaFormatQName(&str,
26186 inode->localName, inode->nsName));
26187 } else {
26188 xmlGenericError(xmlGenericErrorContext,
26189 "AUTOMATON callback for '%s' [wildcard]\n",
26190 xmlSchemaFormatQName(&str,
26191 inode->localName, inode->nsName));
26192
26193 }
26194 FREE_AND_NULL(str)
26195 }
26196#endif
26197}
26198
26199static int
26200xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Daniel Veillarddee23482008-04-11 12:58:43 +000026201{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026202 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26203 if (vctxt->inode == NULL) {
26204 VERROR_INT("xmlSchemaValidatorPushElem",
26205 "calling xmlSchemaGetFreshElemInfo()");
26206 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000026207 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026208 vctxt->nbAttrInfos = 0;
26209 return (0);
26210}
26211
26212static int
26213xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26214 xmlSchemaNodeInfoPtr inode,
26215 xmlSchemaTypePtr type,
26216 const xmlChar *value)
26217{
26218 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26219 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026220 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026221 type, value, &(inode->val), 1, 1, 0));
26222 else
26223 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026224 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026225 type, value, NULL, 1, 0, 0));
26226}
26227
26228
26229
Daniel Veillarddee23482008-04-11 12:58:43 +000026230/*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026231* Process END of element.
26232*/
26233static int
26234xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26235{
26236 int ret = 0;
26237 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26238
26239 if (vctxt->nbAttrInfos != 0)
26240 xmlSchemaClearAttrInfos(vctxt);
26241 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26242 /*
26243 * This element was not expected;
26244 * we will not validate child elements of broken parents.
26245 * Skip validation of all content of the parent.
26246 */
26247 vctxt->skipDepth = vctxt->depth -1;
26248 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026249 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026250 if ((inode->typeDef == NULL) ||
26251 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26252 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000026253 * 1. the type definition might be missing if the element was
26254 * error prone
26255 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026256 */
26257 goto end_elem;
26258 }
26259 /*
26260 * Check the content model.
26261 */
26262 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26263 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26264
26265 /*
26266 * Workaround for "anyType".
26267 */
26268 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
Daniel Veillarddee23482008-04-11 12:58:43 +000026269 goto character_content;
26270
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026271 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26272 xmlChar *values[10];
26273 int terminal, nbval = 10, nbneg;
26274
26275 if (inode->regexCtxt == NULL) {
26276 /*
26277 * Create the regex context.
26278 */
26279 inode->regexCtxt =
26280 xmlRegNewExecCtxt(inode->typeDef->contModel,
Nick Wellnhofere5f33e52017-11-09 17:29:22 +010026281 xmlSchemaVContentModelCallback, vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026282 if (inode->regexCtxt == NULL) {
26283 VERROR_INT("xmlSchemaValidatorPopElem",
26284 "failed to create a regex context");
26285 goto internal_error;
26286 }
26287#ifdef DEBUG_AUTOMATA
26288 xmlGenericError(xmlGenericErrorContext,
26289 "AUTOMATON create on '%s'\n", inode->localName);
Daniel Veillarddee23482008-04-11 12:58:43 +000026290#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026291 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026292
26293 /*
26294 * Do not check further content if the node has been nilled
26295 */
26296 if (INODE_NILLED(inode)) {
26297 ret = 0;
26298#ifdef DEBUG_AUTOMATA
26299 xmlGenericError(xmlGenericErrorContext,
26300 "AUTOMATON succeeded on nilled '%s'\n",
26301 inode->localName);
26302#endif
26303 goto skip_nilled;
26304 }
26305
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026306 /*
26307 * Get hold of the still expected content, since a further
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020026308 * call to xmlRegExecPushString() will lose this information.
Daniel Veillarddee23482008-04-11 12:58:43 +000026309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026310 xmlRegExecNextValues(inode->regexCtxt,
26311 &nbval, &nbneg, &values[0], &terminal);
26312 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
Daniel Veillard65fcf272007-07-11 17:55:30 +000026313 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026314 /*
26315 * Still missing something.
26316 */
26317 ret = 1;
26318 inode->flags |=
26319 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026320 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026321 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26322 "Missing child element(s)",
26323 nbval, nbneg, values);
26324#ifdef DEBUG_AUTOMATA
26325 xmlGenericError(xmlGenericErrorContext,
26326 "AUTOMATON missing ERROR on '%s'\n",
26327 inode->localName);
26328#endif
26329 } else {
26330 /*
26331 * Content model is satisfied.
26332 */
26333 ret = 0;
26334#ifdef DEBUG_AUTOMATA
26335 xmlGenericError(xmlGenericErrorContext,
26336 "AUTOMATON succeeded on '%s'\n",
26337 inode->localName);
26338#endif
26339 }
26340
26341 }
26342 }
Daniel Veillardc100e692013-02-28 19:02:32 +080026343
26344skip_nilled:
26345
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026346 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26347 goto end_elem;
26348
26349character_content:
26350
26351 if (vctxt->value != NULL) {
26352 xmlSchemaFreeValue(vctxt->value);
26353 vctxt->value = NULL;
26354 }
26355 /*
26356 * Check character content.
26357 */
26358 if (inode->decl == NULL) {
26359 /*
26360 * Speedup if no declaration exists.
26361 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026362 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026363 ret = xmlSchemaVCheckINodeDataType(vctxt,
26364 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026365 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026366 ret = xmlSchemaVCheckINodeDataType(vctxt,
26367 inode, inode->typeDef->contentTypeDef,
26368 inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026370 if (ret < 0) {
26371 VERROR_INT("xmlSchemaValidatorPopElem",
26372 "calling xmlSchemaVCheckCVCSimpleType()");
26373 goto internal_error;
26374 }
26375 goto end_elem;
26376 }
26377 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026378 * cvc-elt (3.3.4) : 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026379 * The appropriate case among the following must be true:
26380 */
26381 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026382 * cvc-elt (3.3.4) : 5.1
26383 * If the declaration has a {value constraint},
26384 * the item has neither element nor character [children] and
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026385 * clause 3.2 has not applied, then all of the following must be true:
26386 */
26387 if ((inode->decl->value != NULL) &&
Daniel Veillarddee23482008-04-11 12:58:43 +000026388 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026389 (! INODE_NILLED(inode))) {
26390 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026391 * cvc-elt (3.3.4) : 5.1.1
Jan Pokorný761c9e92013-11-29 23:26:27 +010026392 * If the `actual type definition` is a `local type definition`
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026393 * then the canonical lexical representation of the {value constraint}
Jan Pokorný761c9e92013-11-29 23:26:27 +010026394 * value must be a valid default for the `actual type definition` as
26395 * defined in Element Default Valid (Immediate) ($3.3.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026396 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026397 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026398 * NOTE: 'local' above means types acquired by xsi:type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026399 * NOTE: Although the *canonical* value is stated, it is not
26400 * relevant if canonical or not. Additionally XML Schema 1.1
26401 * will removed this requirement as well.
26402 */
26403 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26404
26405 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26406 inode->decl->value, &(inode->val));
26407 if (ret != 0) {
26408 if (ret < 0) {
26409 VERROR_INT("xmlSchemaValidatorPopElem",
26410 "calling xmlSchemaCheckCOSValidDefault()");
26411 goto internal_error;
26412 }
26413 goto end_elem;
26414 }
26415 /*
26416 * Stop here, to avoid redundant validation of the value
26417 * (see following).
26418 */
26419 goto default_psvi;
Daniel Veillarddee23482008-04-11 12:58:43 +000026420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026421 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026422 * cvc-elt (3.3.4) : 5.1.2
26423 * The element information item with the canonical lexical
26424 * representation of the {value constraint} value used as its
Jan Pokorný761c9e92013-11-29 23:26:27 +010026425 * `normalized value` must be `valid` with respect to the
26426 * `actual type definition` as defined by Element Locally Valid (Type)
26427 * ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026428 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026429 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026430 ret = xmlSchemaVCheckINodeDataType(vctxt,
26431 inode, inode->typeDef, inode->decl->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026432 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026433 ret = xmlSchemaVCheckINodeDataType(vctxt,
26434 inode, inode->typeDef->contentTypeDef,
Daniel Veillarddee23482008-04-11 12:58:43 +000026435 inode->decl->value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026436 }
26437 if (ret != 0) {
26438 if (ret < 0) {
26439 VERROR_INT("xmlSchemaValidatorPopElem",
26440 "calling xmlSchemaVCheckCVCSimpleType()");
26441 goto internal_error;
26442 }
26443 goto end_elem;
26444 }
26445
26446default_psvi:
26447 /*
26448 * PSVI: Create a text node on the instance element.
26449 */
26450 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26451 (inode->node != NULL)) {
26452 xmlNodePtr textChild;
26453 xmlChar *normValue;
26454 /*
26455 * VAL TODO: Normalize the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000026456 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026457 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26458 inode->decl->value);
26459 if (normValue != NULL) {
26460 textChild = xmlNewText(BAD_CAST normValue);
26461 xmlFree(normValue);
26462 } else
26463 textChild = xmlNewText(inode->decl->value);
26464 if (textChild == NULL) {
26465 VERROR_INT("xmlSchemaValidatorPopElem",
26466 "calling xmlNewText()");
26467 goto internal_error;
26468 } else
Daniel Veillarddee23482008-04-11 12:58:43 +000026469 xmlAddChild(inode->node, textChild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026470 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026471
26472 } else if (! INODE_NILLED(inode)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026473 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026474 * 5.2.1 The element information item must be `valid` with respect
26475 * to the `actual type definition` as defined by Element Locally
26476 * Valid (Type) ($3.3.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026477 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026478 if (WXS_IS_SIMPLE(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026479 /*
26480 * SPEC (cvc-type) (3.1)
26481 * "If the type definition is a simple type definition, ..."
26482 * (3.1.3) "If clause 3.2 of Element Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026483 * (Element) ($3.3.4) did not apply, then the `normalized value`
26484 * must be `valid` with respect to the type definition as defined
26485 * by String Valid ($3.14.4).
Daniel Veillarddee23482008-04-11 12:58:43 +000026486 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026487 ret = xmlSchemaVCheckINodeDataType(vctxt,
26488 inode, inode->typeDef, inode->value);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026489 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026490 /*
26491 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26492 * definition, then the element information item must be
Jan Pokorný761c9e92013-11-29 23:26:27 +010026493 * `valid` with respect to the type definition as per
26494 * Element Locally Valid (Complex Type) ($3.4.4);"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026495 *
26496 * SPEC (cvc-complex-type) (2.2)
Daniel Veillarddee23482008-04-11 12:58:43 +000026497 * "If the {content type} is a simple type definition, ...
Jan Pokorný761c9e92013-11-29 23:26:27 +010026498 * the `normalized value` of the element information item is
26499 * `valid` with respect to that simple type definition as
26500 * defined by String Valid ($3.14.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026501 */
26502 ret = xmlSchemaVCheckINodeDataType(vctxt,
26503 inode, inode->typeDef->contentTypeDef, inode->value);
Daniel Veillarddee23482008-04-11 12:58:43 +000026504 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026505 if (ret != 0) {
26506 if (ret < 0) {
26507 VERROR_INT("xmlSchemaValidatorPopElem",
26508 "calling xmlSchemaVCheckCVCSimpleType()");
26509 goto internal_error;
26510 }
26511 goto end_elem;
26512 }
26513 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026514 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026515 * not applied, all of the following must be true:
26516 */
26517 if ((inode->decl->value != NULL) &&
26518 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26519
26520 /*
26521 * TODO: We will need a computed value, when comparison is
26522 * done on computed values.
26523 */
26524 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026525 * 5.2.2.1 The element information item must have no element
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026526 * information item [children].
26527 */
26528 if (inode->flags &
26529 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26530 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26531 VERROR(ret, NULL,
Haibo Huangcfd91dc2020-07-30 23:01:33 -070026532 "The content must not contain element nodes since "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026533 "there is a fixed value constraint");
26534 goto end_elem;
26535 } else {
26536 /*
Daniel Veillarddee23482008-04-11 12:58:43 +000026537 * 5.2.2.2 The appropriate case among the following must
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026538 * be true:
Daniel Veillarddee23482008-04-11 12:58:43 +000026539 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026540 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026541 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026542 * 5.2.2.2.1 If the {content type} of the `actual type
26543 * definition` is mixed, then the *initial value* of the
Daniel Veillarddee23482008-04-11 12:58:43 +000026544 * item must match the canonical lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026545 * of the {value constraint} value.
26546 *
Daniel Veillarddee23482008-04-11 12:58:43 +000026547 * ... the *initial value* of an element information
26548 * item is the string composed of, in order, the
26549 * [character code] of each character information item in
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026550 * the [children] of that element information item.
Daniel Veillarddee23482008-04-11 12:58:43 +000026551 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026552 if (! xmlStrEqual(inode->value, inode->decl->value)){
Daniel Veillarddee23482008-04-11 12:58:43 +000026553 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026554 * VAL TODO: Report invalid & expected values as well.
26555 * VAL TODO: Implement the canonical stuff.
26556 */
26557 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Daniel Veillarddee23482008-04-11 12:58:43 +000026558 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026559 ret, NULL, NULL,
26560 "The initial value '%s' does not match the fixed "
26561 "value constraint '%s'",
26562 inode->value, inode->decl->value);
26563 goto end_elem;
26564 }
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026565 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026566 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026567 * 5.2.2.2.2 If the {content type} of the `actual type
26568 * definition` is a simple type definition, then the
Daniel Veillarddee23482008-04-11 12:58:43 +000026569 * *actual value* of the item must match the canonical
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026570 * lexical representation of the {value constraint} value.
26571 */
26572 /*
26573 * VAL TODO: *actual value* is the normalized value, impl.
26574 * this.
26575 * VAL TODO: Report invalid & expected values as well.
26576 * VAL TODO: Implement a comparison with the computed values.
26577 */
26578 if (! xmlStrEqual(inode->value,
26579 inode->decl->value)) {
26580 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026581 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026582 ret, NULL, NULL,
26583 "The actual value '%s' does not match the fixed "
Daniel Veillarddee23482008-04-11 12:58:43 +000026584 "value constraint '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026585 inode->value,
26586 inode->decl->value);
26587 goto end_elem;
Daniel Veillarddee23482008-04-11 12:58:43 +000026588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026589 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026591 }
26592 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026593
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026594end_elem:
26595 if (vctxt->depth < 0) {
26596 /* TODO: raise error? */
26597 return (0);
26598 }
26599 if (vctxt->depth == vctxt->skipDepth)
26600 vctxt->skipDepth = -1;
26601 /*
26602 * Evaluate the history of XPath state objects.
Daniel Veillarddee23482008-04-11 12:58:43 +000026603 */
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000026604 if (inode->appliedXPath &&
26605 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026606 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026607 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026608 * MAYBE TODO:
Jan Pokorný761c9e92013-11-29 23:26:27 +010026609 * SPEC (6) "The element information item must be `valid` with
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026610 * respect to each of the {identity-constraint definitions} as per
Jan Pokorný761c9e92013-11-29 23:26:27 +010026611 * Identity-constraint Satisfied ($3.11.4)."
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026612 */
26613 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026614 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26615 * need to be built in any case.
26616 * We will currently build IDC node-tables and bubble them only if
26617 * keyrefs do exist.
26618 */
Daniel Veillarddee23482008-04-11 12:58:43 +000026619
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026620 /*
26621 * Add the current IDC target-nodes to the IDC node-tables.
26622 */
26623 if ((inode->idcMatchers != NULL) &&
26624 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26625 {
26626 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26627 goto internal_error;
26628 }
26629 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026630 * Validate IDC keyrefs.
26631 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026632 if (vctxt->inode->hasKeyrefs)
26633 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26634 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026635 /*
26636 * Merge/free the IDC table.
26637 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026638 if (inode->idcTable != NULL) {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026639#ifdef DEBUG_IDC_NODE_TABLE
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026640 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026641 inode->nsName,
26642 inode->localName,
26643 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026644#endif
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026645 if ((vctxt->depth > 0) &&
26646 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26647 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026648 /*
26649 * Merge the IDC node table with the table of the parent node.
26650 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026651 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26652 goto internal_error;
Daniel Veillarddee23482008-04-11 12:58:43 +000026653 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026654 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026655 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026656 * Clear the current ielem.
26657 * VAL TODO: Don't free the PSVI IDC tables if they are
26658 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026659 */
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000026660 xmlSchemaClearElemInfo(vctxt, inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026661 /*
26662 * Skip further processing if we are on the validation root.
26663 */
26664 if (vctxt->depth == 0) {
26665 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026666 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026667 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026668 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026669 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026670 * Reset the keyrefDepth if needed.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026671 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026672 if (vctxt->aidcs != NULL) {
26673 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26674 do {
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026675 if (aidc->keyrefDepth == vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026676 /*
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026677 * A 'keyrefDepth' of a key/unique IDC matches the current
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026678 * depth, this means that we are leaving the scope of the
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026679 * top-most keyref IDC which refers to this IDC.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026680 */
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000026681 aidc->keyrefDepth = -1;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000026682 }
26683 aidc = aidc->next;
26684 } while (aidc != NULL);
26685 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026686 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026687 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000026688 /*
Jan Pokorný761c9e92013-11-29 23:26:27 +010026689 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26690 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026692 return (ret);
26693
26694internal_error:
26695 vctxt->err = -1;
26696 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000026697}
26698
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026699/*
26700* 3.4.4 Complex Type Definition Validation Rules
26701* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26702*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000026703static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026704xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000026705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026706 xmlSchemaNodeInfoPtr pielem;
26707 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026708 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000026709
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026710 if (vctxt->depth <= 0) {
26711 VERROR_INT("xmlSchemaValidateChildElem",
26712 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026713 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026714 }
26715 pielem = vctxt->elemInfos[vctxt->depth -1];
26716 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26717 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026718 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026719 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026720 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026721 if (INODE_NILLED(pielem)) {
26722 /*
26723 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26724 */
26725 ACTIVATE_PARENT_ELEM;
26726 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26727 VERROR(ret, NULL,
26728 "Neither character nor element content is allowed, "
26729 "because the element was 'nilled'");
26730 ACTIVATE_ELEM;
26731 goto unexpected_elem;
26732 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026733
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026734 ptype = pielem->typeDef;
26735
26736 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26737 /*
26738 * Workaround for "anyType": we have currently no content model
Haibo Huangcfd91dc2020-07-30 23:01:33 -070026739 * assigned for "anyType", so handle it explicitly.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026740 * "anyType" has an unbounded, lax "any" wildcard.
26741 */
26742 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26743 vctxt->inode->localName,
26744 vctxt->inode->nsName);
26745
26746 if (vctxt->inode->decl == NULL) {
26747 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026748 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026749 * Process "xsi:type".
26750 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026751 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026752 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26753 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26754 if (iattr != NULL) {
26755 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26756 &(vctxt->inode->typeDef), NULL);
26757 if (ret != 0) {
26758 if (ret == -1) {
26759 VERROR_INT("xmlSchemaValidateChildElem",
26760 "calling xmlSchemaProcessXSIType() to "
26761 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000026762 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000026763 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026764 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000026765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026766 } else {
26767 /*
26768 * Fallback to "anyType".
26769 *
26770 * SPEC (cvc-assess-elt)
Jan Pokorný761c9e92013-11-29 23:26:27 +010026771 * "If the item cannot be `strictly assessed`, [...]
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026772 * an element information item's schema validity may be laxly
Jan Pokorný761c9e92013-11-29 23:26:27 +010026773 * assessed if its `context-determined declaration` is not
26774 * skip by `validating` with respect to the `ur-type
26775 * definition` as per Element Locally Valid (Type) ($3.3.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026776 */
26777 vctxt->inode->typeDef =
26778 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026779 }
26780 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026781 return (0);
26782 }
26783
26784 switch (ptype->contentType) {
26785 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026786 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026787 * SPEC (2.1) "If the {content type} is empty, then the
26788 * element information item has no character or element
26789 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026790 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026791 ACTIVATE_PARENT_ELEM
26792 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26793 VERROR(ret, NULL,
26794 "Element content is not allowed, "
26795 "because the content type is empty");
26796 ACTIVATE_ELEM
26797 goto unexpected_elem;
26798 break;
26799
26800 case XML_SCHEMA_CONTENT_MIXED:
26801 case XML_SCHEMA_CONTENT_ELEMENTS: {
26802 xmlRegExecCtxtPtr regexCtxt;
26803 xmlChar *values[10];
26804 int terminal, nbval = 10, nbneg;
26805
26806 /* VAL TODO: Optimized "anyType" validation.*/
26807
26808 if (ptype->contModel == NULL) {
26809 VERROR_INT("xmlSchemaValidateChildElem",
26810 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000026811 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000026812 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026813 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -070026814 * Safety belt for evaluation if the cont. model was already
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026815 * examined to be invalid.
26816 */
26817 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26818 VERROR_INT("xmlSchemaValidateChildElem",
26819 "validating elem, but elem content is already invalid");
26820 return (-1);
26821 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000026822
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026823 regexCtxt = pielem->regexCtxt;
26824 if (regexCtxt == NULL) {
26825 /*
26826 * Create the regex context.
26827 */
26828 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
Nick Wellnhofere5f33e52017-11-09 17:29:22 +010026829 xmlSchemaVContentModelCallback, vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026830 if (regexCtxt == NULL) {
26831 VERROR_INT("xmlSchemaValidateChildElem",
26832 "failed to create a regex context");
26833 return (-1);
26834 }
26835 pielem->regexCtxt = regexCtxt;
26836#ifdef DEBUG_AUTOMATA
26837 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26838 pielem->localName);
26839#endif
26840 }
26841
26842 /*
26843 * SPEC (2.4) "If the {content type} is element-only or mixed,
26844 * then the sequence of the element information item's
26845 * element information item [children], if any, taken in
Jan Pokorný761c9e92013-11-29 23:26:27 +010026846 * order, is `valid` with respect to the {content type}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026847 * particle, as defined in Element Sequence Locally Valid
Jan Pokorný761c9e92013-11-29 23:26:27 +010026848 * (Particle) ($3.9.4)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026849 */
26850 ret = xmlRegExecPushString2(regexCtxt,
26851 vctxt->inode->localName,
26852 vctxt->inode->nsName,
26853 vctxt->inode);
26854#ifdef DEBUG_AUTOMATA
26855 if (ret < 0)
26856 xmlGenericError(xmlGenericErrorContext,
26857 "AUTOMATON push ERROR for '%s' on '%s'\n",
26858 vctxt->inode->localName, pielem->localName);
26859 else
26860 xmlGenericError(xmlGenericErrorContext,
26861 "AUTOMATON push OK for '%s' on '%s'\n",
26862 vctxt->inode->localName, pielem->localName);
26863#endif
26864 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26865 VERROR_INT("xmlSchemaValidateChildElem",
26866 "calling xmlRegExecPushString2()");
26867 return (-1);
26868 }
26869 if (ret < 0) {
26870 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26871 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000026872 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026873 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26874 "This element is not expected",
26875 nbval, nbneg, values);
26876 ret = vctxt->err;
26877 goto unexpected_elem;
26878 } else
26879 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000026880 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000026881 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026882 case XML_SCHEMA_CONTENT_SIMPLE:
26883 case XML_SCHEMA_CONTENT_BASIC:
26884 ACTIVATE_PARENT_ELEM
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000026885 if (WXS_IS_COMPLEX(ptype)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026886 /*
26887 * SPEC (cvc-complex-type) (2.2)
26888 * "If the {content type} is a simple type definition, then
26889 * the element information item has no element information
26890 * item [children], ..."
26891 */
26892 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26893 VERROR(ret, NULL, "Element content is not allowed, "
26894 "because the content type is a simple type definition");
26895 } else {
26896 /*
26897 * SPEC (cvc-type) (3.1.2) "The element information item must
26898 * have no element information item [children]."
26899 */
26900 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26901 VERROR(ret, NULL, "Element content is not allowed, "
26902 "because the type definition is simple");
26903 }
26904 ACTIVATE_ELEM
26905 ret = vctxt->err;
26906 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026907 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026908
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026909 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000026910 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026911 }
26912 return (ret);
26913unexpected_elem:
26914 /*
26915 * Pop this element and set the skipDepth to skip
26916 * all further content of the parent element.
26917 */
26918 vctxt->skipDepth = vctxt->depth;
26919 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26920 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26921 return (ret);
26922}
26923
26924#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26925#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26926#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26927
26928static int
26929xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26930 int nodeType, const xmlChar *value, int len,
26931 int mode, int *consumed)
26932{
26933 /*
26934 * Unfortunately we have to duplicate the text sometimes.
26935 * OPTIMIZE: Maybe we could skip it, if:
26936 * 1. content type is simple
26937 * 2. whitespace is "collapse"
26938 * 3. it consists of whitespace only
26939 *
26940 * Process character content.
26941 */
26942 if (consumed != NULL)
26943 *consumed = 0;
26944 if (INODE_NILLED(vctxt->inode)) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026945 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026946 * SPEC cvc-elt (3.3.4 - 3.2.1)
26947 * "The element information item must have no character or
26948 * element information item [children]."
26949 */
26950 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26951 "Neither character nor element content is allowed "
26952 "because the element is 'nilled'");
26953 return (vctxt->err);
26954 }
26955 /*
26956 * SPEC (2.1) "If the {content type} is empty, then the
26957 * element information item has no character or element
26958 * information item [children]."
26959 */
26960 if (vctxt->inode->typeDef->contentType ==
Daniel Veillarddee23482008-04-11 12:58:43 +000026961 XML_SCHEMA_CONTENT_EMPTY) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026962 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26963 "Character content is not allowed, "
26964 "because the content type is empty");
26965 return (vctxt->err);
26966 }
26967
26968 if (vctxt->inode->typeDef->contentType ==
26969 XML_SCHEMA_CONTENT_ELEMENTS) {
26970 if ((nodeType != XML_TEXT_NODE) ||
26971 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
Daniel Veillarddee23482008-04-11 12:58:43 +000026972 /*
26973 * SPEC cvc-complex-type (2.3)
26974 * "If the {content type} is element-only, then the
26975 * element information item has no character information
26976 * item [children] other than those whose [character
26977 * code] is defined as a white space in [XML 1.0 (Second
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026978 * Edition)]."
26979 */
26980 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26981 "Character content other than whitespace is not allowed "
26982 "because the content type is 'element-only'");
26983 return (vctxt->err);
26984 }
26985 return (0);
26986 }
Daniel Veillarddee23482008-04-11 12:58:43 +000026987
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000026988 if ((value == NULL) || (value[0] == 0))
26989 return (0);
26990 /*
26991 * Save the value.
26992 * NOTE that even if the content type is *mixed*, we need the
26993 * *initial value* for default/fixed value constraints.
26994 */
26995 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26996 ((vctxt->inode->decl == NULL) ||
26997 (vctxt->inode->decl->value == NULL)))
26998 return (0);
Daniel Veillarddee23482008-04-11 12:58:43 +000026999
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027000 if (vctxt->inode->value == NULL) {
27001 /*
27002 * Set the value.
27003 */
27004 switch (mode) {
27005 case XML_SCHEMA_PUSH_TEXT_PERSIST:
27006 /*
27007 * When working on a tree.
27008 */
27009 vctxt->inode->value = value;
27010 break;
27011 case XML_SCHEMA_PUSH_TEXT_CREATED:
27012 /*
27013 * When working with the reader.
27014 * The value will be freed by the element info.
27015 */
27016 vctxt->inode->value = value;
27017 if (consumed != NULL)
27018 *consumed = 1;
27019 vctxt->inode->flags |=
27020 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27021 break;
27022 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27023 /*
27024 * When working with SAX.
27025 * The value will be freed by the element info.
27026 */
27027 if (len != -1)
27028 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27029 else
27030 vctxt->inode->value = BAD_CAST xmlStrdup(value);
27031 vctxt->inode->flags |=
27032 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27033 break;
27034 default:
27035 break;
27036 }
Kasimier T. Buchcik5bb0c082005-12-20 10:48:33 +000027037 } else {
27038 if (len < 0)
27039 len = xmlStrlen(value);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027040 /*
27041 * Concat the value.
Daniel Veillarddee23482008-04-11 12:58:43 +000027042 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027043 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000027044 vctxt->inode->value = BAD_CAST xmlStrncat(
27045 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027046 } else {
27047 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027048 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027049 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27050 }
Daniel Veillarddee23482008-04-11 12:58:43 +000027051 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027052
27053 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000027054}
27055
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027056static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027057xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000027058{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027059 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000027060
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027061 if ((vctxt->skipDepth != -1) &&
27062 (vctxt->depth >= vctxt->skipDepth)) {
27063 VERROR_INT("xmlSchemaValidateElem",
27064 "in skip-state");
27065 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000027066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027067 if (vctxt->xsiAssemble) {
Daniel Veillarddee23482008-04-11 12:58:43 +000027068 /*
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000027069 * We will stop validation if there was an error during
27070 * dynamic schema construction.
27071 * Note that we simply set @skipDepth to 0, this could
27072 * mean that a streaming document via SAX would be
27073 * still read to the end but it won't be validated any more.
27074 * TODO: If we are sure how to stop the validation at once
27075 * for all input scenarios, then this should be changed to
27076 * instantly stop the validation.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027077 */
Kasimier T. Buchcik215406f2005-12-07 12:14:09 +000027078 ret = xmlSchemaAssembleByXSI(vctxt);
27079 if (ret != 0) {
27080 if (ret == -1)
27081 goto internal_error;
27082 vctxt->skipDepth = 0;
27083 return(ret);
27084 }
Jim Panettac84e8632010-11-03 21:05:18 +010027085 /*
27086 * Augment the IDC definitions for the main schema and all imported ones
27087 * NOTE: main schema is the first in the imported list
27088 */
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010027089 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27090 vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027091 }
27092 if (vctxt->depth > 0) {
27093 /*
27094 * Validate this element against the content model
27095 * of the parent.
27096 */
27097 ret = xmlSchemaValidateChildElem(vctxt);
27098 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027099 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027100 VERROR_INT("xmlSchemaValidateElem",
27101 "calling xmlSchemaStreamValidateChildElement()");
27102 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027103 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027104 goto exit;
27105 }
27106 if (vctxt->depth == vctxt->skipDepth)
27107 goto exit;
27108 if ((vctxt->inode->decl == NULL) &&
27109 (vctxt->inode->typeDef == NULL)) {
27110 VERROR_INT("xmlSchemaValidateElem",
27111 "the child element was valid but neither the "
27112 "declaration nor the type was set");
27113 goto internal_error;
27114 }
27115 } else {
27116 /*
27117 * Get the declaration of the validation root.
27118 */
27119 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27120 vctxt->inode->localName,
27121 vctxt->inode->nsName);
27122 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000027123 ret = XML_SCHEMAV_CVC_ELT_1;
27124 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027125 "No matching global declaration available "
27126 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027127 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027128 }
27129 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027130
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027131 if (vctxt->inode->decl == NULL)
27132 goto type_validation;
27133
27134 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27135 int skip;
27136 /*
27137 * Wildcards.
27138 */
27139 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27140 if (ret != 0) {
27141 if (ret < 0) {
27142 VERROR_INT("xmlSchemaValidateElem",
27143 "calling xmlSchemaValidateElemWildcard()");
27144 goto internal_error;
27145 }
27146 goto exit;
27147 }
27148 if (skip) {
27149 vctxt->skipDepth = vctxt->depth;
27150 goto exit;
27151 }
27152 /*
27153 * The declaration might be set by the wildcard validation,
27154 * when the processContents is "lax" or "strict".
27155 */
27156 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27157 /*
27158 * Clear the "decl" field to not confuse further processing.
27159 */
27160 vctxt->inode->decl = NULL;
27161 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027162 }
Daniel Veillard4255d502002-04-16 15:50:10 +000027163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027164 /*
27165 * Validate against the declaration.
27166 */
27167 ret = xmlSchemaValidateElemDecl(vctxt);
27168 if (ret != 0) {
27169 if (ret < 0) {
27170 VERROR_INT("xmlSchemaValidateElem",
27171 "calling xmlSchemaValidateElemDecl()");
27172 goto internal_error;
27173 }
27174 goto exit;
27175 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000027176 /*
27177 * Validate against the type definition.
27178 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027179type_validation:
27180
27181 if (vctxt->inode->typeDef == NULL) {
27182 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27183 ret = XML_SCHEMAV_CVC_TYPE_1;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027184 VERROR(ret, NULL,
27185 "The type definition is absent");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027186 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000027187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027188 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27189 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27190 ret = XML_SCHEMAV_CVC_TYPE_2;
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027191 VERROR(ret, NULL,
27192 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027193 goto exit;
27194 }
27195 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000027196 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027197 * during validation against the declaration. This must be done
27198 * _before_ attribute validation.
27199 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027200 if (vctxt->xpathStates != NULL) {
27201 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
Kasimier T. Buchcik65c2f1d2005-10-17 12:39:58 +000027202 vctxt->inode->appliedXPath = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000027203 if (ret == -1) {
27204 VERROR_INT("xmlSchemaValidateElem",
27205 "calling xmlSchemaXPathEvaluate()");
27206 goto internal_error;
27207 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027208 }
27209 /*
27210 * Validate attributes.
27211 */
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027212 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027213 if ((vctxt->nbAttrInfos != 0) ||
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000027214 (vctxt->inode->typeDef->attrUses != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027215
27216 ret = xmlSchemaVAttributesComplex(vctxt);
27217 }
27218 } else if (vctxt->nbAttrInfos != 0) {
27219
27220 ret = xmlSchemaVAttributesSimple(vctxt);
27221 }
27222 /*
27223 * Clear registered attributes.
27224 */
27225 if (vctxt->nbAttrInfos != 0)
27226 xmlSchemaClearAttrInfos(vctxt);
27227 if (ret == -1) {
27228 VERROR_INT("xmlSchemaValidateElem",
27229 "calling attributes validation");
27230 goto internal_error;
27231 }
27232 /*
27233 * Don't return an error if attributes are invalid on purpose.
27234 */
27235 ret = 0;
27236
27237exit:
27238 if (ret != 0)
27239 vctxt->skipDepth = vctxt->depth;
27240 return (ret);
27241internal_error:
27242 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027243}
27244
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027245#ifdef XML_SCHEMA_READER_ENABLED
27246static int
27247xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027248{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027249 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27250 int depth, nodeType, ret = 0, consumed;
27251 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000027252
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027253 vctxt->depth = -1;
27254 ret = xmlTextReaderRead(vctxt->reader);
27255 /*
27256 * Move to the document element.
27257 */
27258 while (ret == 1) {
27259 nodeType = xmlTextReaderNodeType(vctxt->reader);
27260 if (nodeType == XML_ELEMENT_NODE)
27261 goto root_found;
27262 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027263 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027264 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027265
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027266root_found:
27267
27268 do {
27269 depth = xmlTextReaderDepth(vctxt->reader);
27270 nodeType = xmlTextReaderNodeType(vctxt->reader);
27271
27272 if (nodeType == XML_ELEMENT_NODE) {
Daniel Veillarddee23482008-04-11 12:58:43 +000027273
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027274 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027275 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27276 VERROR_INT("xmlSchemaVReaderWalk",
27277 "calling xmlSchemaValidatorPushElem()");
27278 goto internal_error;
27279 }
27280 ielem = vctxt->inode;
27281 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27282 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27283 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27284 /*
27285 * Is the element empty?
27286 */
27287 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27288 if (ret == -1) {
27289 VERROR_INT("xmlSchemaVReaderWalk",
27290 "calling xmlTextReaderIsEmptyElement()");
27291 goto internal_error;
27292 }
27293 if (ret) {
27294 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27295 }
27296 /*
27297 * Register attributes.
27298 */
27299 vctxt->nbAttrInfos = 0;
27300 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27301 if (ret == -1) {
27302 VERROR_INT("xmlSchemaVReaderWalk",
27303 "calling xmlTextReaderMoveToFirstAttribute()");
27304 goto internal_error;
27305 }
27306 if (ret == 1) {
27307 do {
27308 /*
27309 * VAL TODO: How do we know that the reader works on a
27310 * node tree, to be able to pass a node here?
27311 */
27312 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27313 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27314 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27315 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27316
27317 VERROR_INT("xmlSchemaVReaderWalk",
27318 "calling xmlSchemaValidatorPushAttribute()");
27319 goto internal_error;
27320 }
27321 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27322 if (ret == -1) {
27323 VERROR_INT("xmlSchemaVReaderWalk",
27324 "calling xmlTextReaderMoveToFirstAttribute()");
27325 goto internal_error;
27326 }
27327 } while (ret == 1);
27328 /*
27329 * Back to element position.
27330 */
27331 ret = xmlTextReaderMoveToElement(vctxt->reader);
27332 if (ret == -1) {
27333 VERROR_INT("xmlSchemaVReaderWalk",
27334 "calling xmlTextReaderMoveToElement()");
27335 goto internal_error;
27336 }
27337 }
27338 /*
27339 * Validate the element.
27340 */
27341 ret= xmlSchemaValidateElem(vctxt);
27342 if (ret != 0) {
27343 if (ret == -1) {
27344 VERROR_INT("xmlSchemaVReaderWalk",
27345 "calling xmlSchemaValidateElem()");
27346 goto internal_error;
27347 }
27348 goto exit;
27349 }
27350 if (vctxt->depth == vctxt->skipDepth) {
27351 int curDepth;
27352 /*
27353 * Skip all content.
27354 */
27355 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27356 ret = xmlTextReaderRead(vctxt->reader);
27357 curDepth = xmlTextReaderDepth(vctxt->reader);
27358 while ((ret == 1) && (curDepth != depth)) {
27359 ret = xmlTextReaderRead(vctxt->reader);
27360 curDepth = xmlTextReaderDepth(vctxt->reader);
27361 }
27362 if (ret < 0) {
27363 /*
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +020027364 * VAL TODO: A reader error occurred; what to do here?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027365 */
27366 ret = 1;
27367 goto exit;
27368 }
27369 }
27370 goto leave_elem;
27371 }
27372 /*
27373 * READER VAL TODO: Is an END_ELEM really never called
27374 * if the elem is empty?
27375 */
27376 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27377 goto leave_elem;
27378 } else if (nodeType == END_ELEM) {
27379 /*
27380 * Process END of element.
27381 */
27382leave_elem:
27383 ret = xmlSchemaValidatorPopElem(vctxt);
27384 if (ret != 0) {
27385 if (ret < 0) {
27386 VERROR_INT("xmlSchemaVReaderWalk",
27387 "calling xmlSchemaValidatorPopElem()");
27388 goto internal_error;
27389 }
27390 goto exit;
27391 }
27392 if (vctxt->depth >= 0)
27393 ielem = vctxt->inode;
27394 else
27395 ielem = NULL;
27396 } else if ((nodeType == XML_TEXT_NODE) ||
27397 (nodeType == XML_CDATA_SECTION_NODE) ||
27398 (nodeType == WHTSP) ||
27399 (nodeType == SIGN_WHTSP)) {
27400 /*
27401 * Process character content.
27402 */
27403 xmlChar *value;
27404
27405 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27406 nodeType = XML_TEXT_NODE;
27407
27408 value = xmlTextReaderValue(vctxt->reader);
27409 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27410 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27411 if (! consumed)
27412 xmlFree(value);
27413 if (ret == -1) {
27414 VERROR_INT("xmlSchemaVReaderWalk",
27415 "calling xmlSchemaVPushText()");
27416 goto internal_error;
27417 }
27418 } else if ((nodeType == XML_ENTITY_NODE) ||
27419 (nodeType == XML_ENTITY_REF_NODE)) {
27420 /*
27421 * VAL TODO: What to do with entities?
27422 */
27423 TODO
27424 }
27425 /*
27426 * Read next node.
27427 */
27428 ret = xmlTextReaderRead(vctxt->reader);
27429 } while (ret == 1);
27430
27431exit:
27432 return (ret);
27433internal_error:
27434 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000027435}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027436#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000027437
27438/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027439 * *
27440 * SAX validation handlers *
27441 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027442 ************************************************************************/
27443
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027444/*
27445* Process text content.
27446*/
27447static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027448xmlSchemaSAXHandleText(void *ctx,
27449 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027450 int len)
27451{
27452 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27453
27454 if (vctxt->depth < 0)
27455 return;
27456 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27457 return;
27458 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27459 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27460 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27461 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27462 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27463 "calling xmlSchemaVPushText()");
27464 vctxt->err = -1;
27465 xmlStopParser(vctxt->parserCtxt);
27466 }
27467}
27468
27469/*
27470* Process CDATA content.
27471*/
27472static void
Daniel Veillarddee23482008-04-11 12:58:43 +000027473xmlSchemaSAXHandleCDataSection(void *ctx,
27474 const xmlChar * ch,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027475 int len)
Daniel Veillarddee23482008-04-11 12:58:43 +000027476{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027477 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27478
27479 if (vctxt->depth < 0)
27480 return;
27481 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27482 return;
27483 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27484 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27485 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27486 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27487 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27488 "calling xmlSchemaVPushText()");
27489 vctxt->err = -1;
27490 xmlStopParser(vctxt->parserCtxt);
27491 }
27492}
27493
27494static void
27495xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27496 const xmlChar * name ATTRIBUTE_UNUSED)
27497{
27498 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27499
27500 if (vctxt->depth < 0)
27501 return;
27502 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27503 return;
27504 /* SAX VAL TODO: What to do here? */
27505 TODO
27506}
27507
27508static void
27509xmlSchemaSAXHandleStartElementNs(void *ctx,
Daniel Veillarddee23482008-04-11 12:58:43 +000027510 const xmlChar * localname,
27511 const xmlChar * prefix ATTRIBUTE_UNUSED,
27512 const xmlChar * URI,
27513 int nb_namespaces,
27514 const xmlChar ** namespaces,
27515 int nb_attributes,
27516 int nb_defaulted ATTRIBUTE_UNUSED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027517 const xmlChar ** attributes)
Daniel Veillarddee23482008-04-11 12:58:43 +000027518{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027519 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27520 int ret;
27521 xmlSchemaNodeInfoPtr ielem;
27522 int i, j;
Daniel Veillarddee23482008-04-11 12:58:43 +000027523
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027524 /*
27525 * SAX VAL TODO: What to do with nb_defaulted?
27526 */
27527 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027528 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027529 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027530 vctxt->depth++;
27531 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027532 return;
27533 /*
27534 * Push the element.
27535 */
27536 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27537 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27538 "calling xmlSchemaValidatorPushElem()");
27539 goto internal_error;
27540 }
27541 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027542 /*
27543 * TODO: Is this OK?
27544 */
27545 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027546 ielem->localName = localname;
27547 ielem->nsName = URI;
27548 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27549 /*
27550 * Register namespaces on the elem info.
Daniel Veillarddee23482008-04-11 12:58:43 +000027551 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027552 if (nb_namespaces != 0) {
27553 /*
27554 * Although the parser builds its own namespace list,
27555 * we have no access to it, so we'll use an own one.
27556 */
Daniel Veillarddee23482008-04-11 12:58:43 +000027557 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027558 /*
27559 * Store prefix and namespace name.
Daniel Veillarddee23482008-04-11 12:58:43 +000027560 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027561 if (ielem->nsBindings == NULL) {
27562 ielem->nsBindings =
27563 (const xmlChar **) xmlMalloc(10 *
27564 sizeof(const xmlChar *));
27565 if (ielem->nsBindings == NULL) {
27566 xmlSchemaVErrMemory(vctxt,
27567 "allocating namespace bindings for SAX validation",
27568 NULL);
27569 goto internal_error;
27570 }
27571 ielem->nbNsBindings = 0;
27572 ielem->sizeNsBindings = 5;
27573 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27574 ielem->sizeNsBindings *= 2;
27575 ielem->nsBindings =
27576 (const xmlChar **) xmlRealloc(
27577 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027578 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027579 if (ielem->nsBindings == NULL) {
27580 xmlSchemaVErrMemory(vctxt,
27581 "re-allocating namespace bindings for SAX validation",
27582 NULL);
27583 goto internal_error;
27584 }
27585 }
27586
27587 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27588 if (namespaces[j+1][0] == 0) {
27589 /*
27590 * Handle xmlns="".
27591 */
27592 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27593 } else
27594 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27595 namespaces[j+1];
Daniel Veillarddee23482008-04-11 12:58:43 +000027596 ielem->nbNsBindings++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027597 }
27598 }
27599 /*
27600 * Register attributes.
27601 * SAX VAL TODO: We are not adding namespace declaration
27602 * attributes yet.
27603 */
27604 if (nb_attributes != 0) {
Alex Henrie31696022016-05-26 17:38:35 -060027605 int valueLen, k, l;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027606 xmlChar *value;
27607
27608 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27609 /*
Alex Henrief6599c52016-05-02 22:29:59 -060027610 * Duplicate the value, changing any &#38; to a literal ampersand.
27611 *
27612 * libxml2 differs from normal SAX here in that it escapes all ampersands
27613 * as &#38; instead of delivering the raw converted string. Changing the
27614 * behavior at this point would break applications that use this API, so
Alex Henrie31696022016-05-26 17:38:35 -060027615 * we are forced to work around it.
Daniel Veillarddee23482008-04-11 12:58:43 +000027616 */
Alex Henrie31696022016-05-26 17:38:35 -060027617 valueLen = attributes[j+4] - attributes[j+3];
27618 value = xmlMallocAtomic(valueLen + 1);
27619 if (value == NULL) {
27620 xmlSchemaVErrMemory(vctxt,
27621 "allocating string for decoded attribute",
27622 NULL);
27623 goto internal_error;
27624 }
27625 for (k = 0, l = 0; k < valueLen; l++) {
27626 if (k < valueLen - 4 &&
27627 attributes[j+3][k+0] == '&' &&
27628 attributes[j+3][k+1] == '#' &&
27629 attributes[j+3][k+2] == '3' &&
27630 attributes[j+3][k+3] == '8' &&
27631 attributes[j+3][k+4] == ';') {
27632 value[l] = '&';
27633 k += 5;
27634 } else {
27635 value[l] = attributes[j+3][k];
27636 k++;
27637 }
27638 }
27639 value[l] = '\0';
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027640 /*
27641 * TODO: Set the node line.
27642 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027643 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027644 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027645 value, 1);
27646 if (ret == -1) {
27647 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27648 "calling xmlSchemaValidatorPushAttribute()");
27649 goto internal_error;
27650 }
27651 }
27652 }
27653 /*
27654 * Validate the element.
27655 */
27656 ret = xmlSchemaValidateElem(vctxt);
27657 if (ret != 0) {
27658 if (ret == -1) {
27659 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27660 "calling xmlSchemaValidateElem()");
27661 goto internal_error;
27662 }
27663 goto exit;
Daniel Veillarddee23482008-04-11 12:58:43 +000027664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027665
27666exit:
27667 return;
27668internal_error:
27669 vctxt->err = -1;
27670 xmlStopParser(vctxt->parserCtxt);
27671 return;
27672}
27673
27674static void
27675xmlSchemaSAXHandleEndElementNs(void *ctx,
27676 const xmlChar * localname ATTRIBUTE_UNUSED,
27677 const xmlChar * prefix ATTRIBUTE_UNUSED,
27678 const xmlChar * URI ATTRIBUTE_UNUSED)
27679{
27680 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27681 int res;
27682
27683 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000027684 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027685 */
27686 if (vctxt->skipDepth != -1) {
27687 if (vctxt->depth > vctxt->skipDepth) {
27688 vctxt->depth--;
27689 return;
27690 } else
27691 vctxt->skipDepth = -1;
27692 }
27693 /*
27694 * SAX VAL TODO: Just a temporary check.
27695 */
27696 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27697 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27698 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27699 "elem pop mismatch");
27700 }
27701 res = xmlSchemaValidatorPopElem(vctxt);
27702 if (res != 0) {
27703 if (res < 0) {
27704 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27705 "calling xmlSchemaValidatorPopElem()");
27706 goto internal_error;
27707 }
27708 goto exit;
27709 }
27710exit:
27711 return;
27712internal_error:
27713 vctxt->err = -1;
27714 xmlStopParser(vctxt->parserCtxt);
27715 return;
27716}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027717
Daniel Veillard4255d502002-04-16 15:50:10 +000027718/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080027719 * *
27720 * Validation interfaces *
27721 * *
Daniel Veillard4255d502002-04-16 15:50:10 +000027722 ************************************************************************/
27723
27724/**
27725 * xmlSchemaNewValidCtxt:
27726 * @schema: a precompiled XML Schemas
27727 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027728 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000027729 *
27730 * Returns the validation context or NULL in case of error
27731 */
27732xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027733xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27734{
Daniel Veillard4255d502002-04-16 15:50:10 +000027735 xmlSchemaValidCtxtPtr ret;
27736
27737 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27738 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027739 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000027740 return (NULL);
27741 }
27742 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027743 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027744 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027745 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027746 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000027747 return (ret);
27748}
27749
27750/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027751 * xmlSchemaValidateSetFilename:
Daniel Veillardef4526a2012-08-15 09:14:31 +080027752 * @vctxt: the schema validation context
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027753 * @filename: the file name
27754 *
27755 * Workaround to provide file error reporting information when this is
27756 * not provided by current APIs
27757 */
27758void
27759xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27760 if (vctxt == NULL)
27761 return;
27762 if (vctxt->filename != NULL)
27763 xmlFree(vctxt->filename);
27764 if (filename != NULL)
27765 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27766 else
27767 vctxt->filename = NULL;
27768}
27769
27770/**
27771 * xmlSchemaClearValidCtxt:
27772 * @vctxt: the schema validation context
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027773 *
27774 * Free the resources associated to the schema validation context;
27775 * leaves some fields alive intended for reuse of the context.
27776 */
27777static void
27778xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27779{
27780 if (vctxt == NULL)
27781 return;
27782
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027783 /*
27784 * TODO: Should we clear the flags?
27785 * Might be problematic if one reuses the context
27786 * and assumes that the options remain the same.
27787 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000027788 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027789 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027790 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027791#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027792 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000027793#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000027794 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027795
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027796 if (vctxt->value != NULL) {
27797 xmlSchemaFreeValue(vctxt->value);
27798 vctxt->value = NULL;
27799 }
27800 /*
27801 * Augmented IDC information.
27802 */
27803 if (vctxt->aidcs != NULL) {
27804 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27805 do {
27806 next = cur->next;
27807 xmlFree(cur);
27808 cur = next;
27809 } while (cur != NULL);
27810 vctxt->aidcs = NULL;
27811 }
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027812 if (vctxt->idcMatcherCache != NULL) {
27813 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27814
27815 while (matcher) {
27816 tmp = matcher;
27817 matcher = matcher->nextCached;
27818 xmlSchemaIDCFreeMatcherList(tmp);
27819 }
27820 vctxt->idcMatcherCache = NULL;
27821 }
27822
27823
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027824 if (vctxt->idcNodes != NULL) {
27825 int i;
27826 xmlSchemaPSVIIDCNodePtr item;
27827
27828 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027829 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027830 xmlFree(item->keys);
27831 xmlFree(item);
27832 }
27833 xmlFree(vctxt->idcNodes);
27834 vctxt->idcNodes = NULL;
Daniel Veillard1131e112006-08-07 11:02:54 +000027835 vctxt->nbIdcNodes = 0;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027836 vctxt->sizeIdcNodes = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027837 }
Elliott Hughes7fbecab2019-01-10 16:42:03 -080027838
27839 if (vctxt->idcKeys != NULL) {
27840 int i;
27841 for (i = 0; i < vctxt->nbIdcKeys; i++)
27842 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27843 xmlFree(vctxt->idcKeys);
27844 vctxt->idcKeys = NULL;
27845 vctxt->nbIdcKeys = 0;
27846 vctxt->sizeIdcKeys = 0;
27847 }
27848
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027849 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027850 * Note that we won't delete the XPath state pool here.
27851 */
27852 if (vctxt->xpathStates != NULL) {
27853 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27854 vctxt->xpathStates = NULL;
27855 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027856 /*
27857 * Attribute info.
27858 */
27859 if (vctxt->nbAttrInfos != 0) {
27860 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027862 /*
27863 * Element info.
27864 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027865 if (vctxt->elemInfos != NULL) {
27866 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027867 xmlSchemaNodeInfoPtr ei;
27868
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027869 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027870 ei = vctxt->elemInfos[i];
27871 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027872 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027873 xmlSchemaClearElemInfo(vctxt, ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027874 }
Daniel Veillarddee23482008-04-11 12:58:43 +000027875 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027876 xmlSchemaItemListClear(vctxt->nodeQNames);
27877 /* Recreate the dict. */
27878 xmlDictFree(vctxt->dict);
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000027879 /*
27880 * TODO: Is is save to recreate it? Do we have a scenario
27881 * where the user provides the dict?
27882 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027883 vctxt->dict = xmlDictCreate();
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027884
27885 if (vctxt->filename != NULL) {
27886 xmlFree(vctxt->filename);
27887 vctxt->filename = NULL;
27888 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027889}
27890
27891/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027892 * xmlSchemaFreeValidCtxt:
27893 * @ctxt: the schema validation context
27894 *
27895 * Free the resources associated to the schema validation context
27896 */
27897void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027898xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27899{
Daniel Veillard4255d502002-04-16 15:50:10 +000027900 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027901 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000027902 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000027903 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027904 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000027905 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027906 if (ctxt->idcNodes != NULL) {
27907 int i;
27908 xmlSchemaPSVIIDCNodePtr item;
27909
27910 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027911 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027912 xmlFree(item->keys);
27913 xmlFree(item);
27914 }
27915 xmlFree(ctxt->idcNodes);
27916 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027917 if (ctxt->idcKeys != NULL) {
27918 int i;
27919 for (i = 0; i < ctxt->nbIdcKeys; i++)
27920 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27921 xmlFree(ctxt->idcKeys);
27922 }
27923
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027924 if (ctxt->xpathStates != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027925 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027926 ctxt->xpathStates = NULL;
27927 }
27928 if (ctxt->xpathStatePool != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027929 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027930 ctxt->xpathStatePool = NULL;
27931 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027932
27933 /*
27934 * Augmented IDC information.
27935 */
27936 if (ctxt->aidcs != NULL) {
27937 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27938 do {
27939 next = cur->next;
27940 xmlFree(cur);
27941 cur = next;
27942 } while (cur != NULL);
27943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027944 if (ctxt->attrInfos != NULL) {
27945 int i;
27946 xmlSchemaAttrInfoPtr attr;
27947
27948 /* Just a paranoid call to the cleanup. */
27949 if (ctxt->nbAttrInfos != 0)
27950 xmlSchemaClearAttrInfos(ctxt);
27951 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27952 attr = ctxt->attrInfos[i];
27953 xmlFree(attr);
27954 }
27955 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000027956 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027957 if (ctxt->elemInfos != NULL) {
27958 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027959 xmlSchemaNodeInfoPtr ei;
27960
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027961 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027962 ei = ctxt->elemInfos[i];
27963 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000027964 break;
Kasimier T. Buchcikdeb58712006-08-15 12:52:30 +000027965 xmlSchemaClearElemInfo(ctxt, ei);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027966 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000027967 }
27968 xmlFree(ctxt->elemInfos);
27969 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000027970 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000027971 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000027972 if (ctxt->dict != NULL)
27973 xmlDictFree(ctxt->dict);
Daniel Veillard97fa5b32012-08-14 11:01:07 +080027974 if (ctxt->filename != NULL)
27975 xmlFree(ctxt->filename);
Daniel Veillard4255d502002-04-16 15:50:10 +000027976 xmlFree(ctxt);
27977}
27978
27979/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000027980 * xmlSchemaIsValid:
27981 * @ctxt: the schema validation context
27982 *
27983 * Check if any error was detected during validation.
Daniel Veillarddee23482008-04-11 12:58:43 +000027984 *
Daniel Veillardf10ae122005-07-10 19:03:16 +000027985 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27986 * of internal error.
27987 */
27988int
27989xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27990{
27991 if (ctxt == NULL)
27992 return(-1);
27993 return(ctxt->err == 0);
27994}
27995
27996/**
Daniel Veillard4255d502002-04-16 15:50:10 +000027997 * xmlSchemaSetValidErrors:
27998 * @ctxt: a schema validation context
27999 * @err: the error function
28000 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000028001 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000028002 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070028003 * Set the error and warning callback information
Daniel Veillard4255d502002-04-16 15:50:10 +000028004 */
28005void
28006xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028007 xmlSchemaValidityErrorFunc err,
28008 xmlSchemaValidityWarningFunc warn, void *ctx)
28009{
Daniel Veillard4255d502002-04-16 15:50:10 +000028010 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028011 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000028012 ctxt->error = err;
28013 ctxt->warning = warn;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000028014 ctxt->errCtxt = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028015 if (ctxt->pctxt != NULL)
28016 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000028017}
28018
28019/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000028020 * xmlSchemaSetValidStructuredErrors:
28021 * @ctxt: a schema validation context
28022 * @serror: the structured error function
28023 * @ctx: the functions context
28024 *
28025 * Set the structured error callback
28026 */
28027void
28028xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000028029 xmlStructuredErrorFunc serror, void *ctx)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000028030{
28031 if (ctxt == NULL)
28032 return;
Nick Wellnhofer359e7502017-11-13 21:13:46 +010028033 ctxt->serror = serror;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000028034 ctxt->error = NULL;
28035 ctxt->warning = NULL;
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000028036 ctxt->errCtxt = ctx;
28037 if (ctxt->pctxt != NULL)
28038 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000028039}
28040
28041/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000028042 * xmlSchemaGetValidErrors:
Daniel Veillarddee23482008-04-11 12:58:43 +000028043 * @ctxt: a XML-Schema validation context
Daniel Veillard259f0df2004-08-18 09:13:18 +000028044 * @err: the error function result
28045 * @warn: the warning function result
28046 * @ctx: the functions context result
28047 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070028048 * Get the error and warning callback information
Daniel Veillard259f0df2004-08-18 09:13:18 +000028049 *
28050 * Returns -1 in case of error and 0 otherwise
28051 */
28052int
28053xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000028054 xmlSchemaValidityErrorFunc * err,
28055 xmlSchemaValidityWarningFunc * warn, void **ctx)
Daniel Veillard259f0df2004-08-18 09:13:18 +000028056{
28057 if (ctxt == NULL)
28058 return (-1);
28059 if (err != NULL)
28060 *err = ctxt->error;
28061 if (warn != NULL)
28062 *warn = ctxt->warning;
28063 if (ctx != NULL)
Kasimier T. Buchcik90b5ebc2005-11-18 17:18:27 +000028064 *ctx = ctxt->errCtxt;
Daniel Veillard259f0df2004-08-18 09:13:18 +000028065 return (0);
28066}
28067
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028068
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028069/**
Daniel Veillard6927b102004-10-27 17:29:04 +000028070 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028071 * @ctxt: a schema validation context
28072 * @options: a combination of xmlSchemaValidOption
28073 *
28074 * Sets the options to be used during the validation.
28075 *
28076 * Returns 0 in case of success, -1 in case of an
28077 * API error.
28078 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028079int
28080xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28081 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028082
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028083{
28084 int i;
28085
28086 if (ctxt == NULL)
28087 return (-1);
28088 /*
28089 * WARNING: Change the start value if adding to the
28090 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028091 * TODO: Is there an other, more easy to maintain,
28092 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028093 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028094 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028095 if (options & 1<<i)
28096 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028097 }
28098 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028099 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028100}
28101
28102/**
Daniel Veillard6927b102004-10-27 17:29:04 +000028103 * xmlSchemaValidCtxtGetOptions:
Daniel Veillarddee23482008-04-11 12:58:43 +000028104 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028105 *
William M. Brack21e4ef22005-01-02 09:53:13 +000028106 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028107 *
William M. Brack21e4ef22005-01-02 09:53:13 +000028108 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028109 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028110int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028111xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028112
28113{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028114 if (ctxt == NULL)
28115 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028116 else
28117 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028118}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000028119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028120static int
28121xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28122{
28123 xmlAttrPtr attr;
28124 int ret = 0;
28125 xmlSchemaNodeInfoPtr ielem = NULL;
28126 xmlNodePtr node, valRoot;
28127 const xmlChar *nsName;
28128
28129 /* DOC VAL TODO: Move this to the start function. */
Csaba László1f6c42c2013-03-18 15:30:00 +080028130 if (vctxt->validationRoot != NULL)
28131 valRoot = vctxt->validationRoot;
28132 else
28133 valRoot = xmlDocGetRootElement(vctxt->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028134 if (valRoot == NULL) {
28135 /* VAL TODO: Error code? */
28136 VERROR(1, NULL, "The document has no document element");
28137 return (1);
28138 }
Haibo Huangcfd91dc2020-07-30 23:01:33 -070028139 for (node = valRoot->next; node != NULL; node = node->next) {
28140 if (node->type == XML_ELEMENT_NODE)
28141 VERROR(1, NULL, "The document has more than one top element");
28142 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028143 vctxt->depth = -1;
28144 vctxt->validationRoot = valRoot;
28145 node = valRoot;
28146 while (node != NULL) {
28147 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28148 goto next_sibling;
28149 if (node->type == XML_ELEMENT_NODE) {
28150
28151 /*
28152 * Init the node-info.
28153 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000028154 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028155 if (xmlSchemaValidatorPushElem(vctxt) == -1)
28156 goto internal_error;
28157 ielem = vctxt->inode;
28158 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000028159 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028160 ielem->localName = node->name;
28161 if (node->ns != NULL)
28162 ielem->nsName = node->ns->href;
28163 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28164 /*
28165 * Register attributes.
28166 * DOC VAL TODO: We do not register namespace declaration
28167 * attributes yet.
28168 */
28169 vctxt->nbAttrInfos = 0;
28170 if (node->properties != NULL) {
28171 attr = node->properties;
28172 do {
28173 if (attr->ns != NULL)
28174 nsName = attr->ns->href;
28175 else
28176 nsName = NULL;
28177 ret = xmlSchemaValidatorPushAttribute(vctxt,
28178 (xmlNodePtr) attr,
Daniel Veillarddee23482008-04-11 12:58:43 +000028179 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000028180 * Note that we give it the line number of the
28181 * parent element.
28182 */
28183 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028184 attr->name, nsName, 0,
28185 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28186 if (ret == -1) {
28187 VERROR_INT("xmlSchemaDocWalk",
28188 "calling xmlSchemaValidatorPushAttribute()");
28189 goto internal_error;
28190 }
28191 attr = attr->next;
28192 } while (attr);
28193 }
28194 /*
28195 * Validate the element.
28196 */
28197 ret = xmlSchemaValidateElem(vctxt);
28198 if (ret != 0) {
28199 if (ret == -1) {
28200 VERROR_INT("xmlSchemaDocWalk",
28201 "calling xmlSchemaValidateElem()");
28202 goto internal_error;
28203 }
28204 /*
28205 * Don't stop validation; just skip the content
28206 * of this element.
28207 */
28208 goto leave_node;
28209 }
28210 if ((vctxt->skipDepth != -1) &&
28211 (vctxt->depth >= vctxt->skipDepth))
28212 goto leave_node;
28213 } else if ((node->type == XML_TEXT_NODE) ||
28214 (node->type == XML_CDATA_SECTION_NODE)) {
28215 /*
28216 * Process character content.
28217 */
Daniel Veillard14b56432006-03-09 18:41:40 +000028218 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028219 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28220 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28221 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28222 if (ret < 0) {
28223 VERROR_INT("xmlSchemaVDocWalk",
28224 "calling xmlSchemaVPushText()");
28225 goto internal_error;
28226 }
28227 /*
28228 * DOC VAL TODO: Should we skip further validation of the
28229 * element content here?
28230 */
28231 } else if ((node->type == XML_ENTITY_NODE) ||
28232 (node->type == XML_ENTITY_REF_NODE)) {
28233 /*
28234 * DOC VAL TODO: What to do with entities?
Daniel Veillarddee23482008-04-11 12:58:43 +000028235 */
Kasimier T. Buchcik146a9822006-05-04 17:19:07 +000028236 VERROR_INT("xmlSchemaVDocWalk",
28237 "there is at least one entity reference in the node-tree "
28238 "currently being validated. Processing of entities with "
28239 "this XML Schema processor is not supported (yet). Please "
28240 "substitute entities before validation.");
28241 goto internal_error;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028242 } else {
28243 goto leave_node;
28244 /*
28245 * DOC VAL TODO: XInclude nodes, etc.
28246 */
28247 }
28248 /*
28249 * Walk the doc.
28250 */
28251 if (node->children != NULL) {
28252 node = node->children;
28253 continue;
28254 }
28255leave_node:
28256 if (node->type == XML_ELEMENT_NODE) {
28257 /*
28258 * Leaving the scope of an element.
28259 */
28260 if (node != vctxt->inode->node) {
28261 VERROR_INT("xmlSchemaVDocWalk",
28262 "element position mismatch");
28263 goto internal_error;
28264 }
28265 ret = xmlSchemaValidatorPopElem(vctxt);
28266 if (ret != 0) {
28267 if (ret < 0) {
28268 VERROR_INT("xmlSchemaVDocWalk",
28269 "calling xmlSchemaValidatorPopElem()");
28270 goto internal_error;
28271 }
28272 }
28273 if (node == valRoot)
28274 goto exit;
28275 }
28276next_sibling:
28277 if (node->next != NULL)
28278 node = node->next;
28279 else {
28280 node = node->parent;
28281 goto leave_node;
28282 }
28283 }
28284
28285exit:
28286 return (ret);
28287internal_error:
28288 return (-1);
28289}
28290
28291static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000028292xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028293 /*
28294 * Some initialization.
Daniel Veillarddee23482008-04-11 12:58:43 +000028295 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028296 vctxt->err = 0;
28297 vctxt->nberrors = 0;
28298 vctxt->depth = -1;
28299 vctxt->skipDepth = -1;
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028300 vctxt->hasKeyrefs = 0;
Kasimier T. Buchcik132ba5f2005-11-28 12:32:24 +000028301#ifdef ENABLE_IDC_NODE_TABLES_TEST
Kasimier T. Buchcik27820272005-10-14 14:33:48 +000028302 vctxt->createIDCNodeTables = 1;
28303#else
28304 vctxt->createIDCNodeTables = 0;
28305#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028306 /*
28307 * Create a schema + parser if necessary.
28308 */
28309 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028310 xmlSchemaParserCtxtPtr pctxt;
Daniel Veillarddee23482008-04-11 12:58:43 +000028311
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028312 vctxt->xsiAssemble = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028313 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028314 * If not schema was given then we will create a schema
28315 * dynamically using XSI schema locations.
28316 *
28317 * Create the schema parser context.
28318 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028319 if ((vctxt->pctxt == NULL) &&
28320 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28321 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028322 pctxt = vctxt->pctxt;
28323 pctxt->xsiAssemble = 1;
28324 /*
28325 * Create the schema.
28326 */
28327 vctxt->schema = xmlSchemaNewSchema(pctxt);
28328 if (vctxt->schema == NULL)
Daniel Veillarddee23482008-04-11 12:58:43 +000028329 return (-1);
28330 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028331 * Create the schema construction context.
28332 */
28333 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28334 if (pctxt->constructor == NULL)
28335 return(-1);
Kasimier T. Buchcik570faa52005-10-10 13:18:40 +000028336 pctxt->constructor->mainSchema = vctxt->schema;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028337 /*
28338 * Take ownership of the constructor to be able to free it.
28339 */
28340 pctxt->ownsConstructor = 1;
Daniel Veillarddee23482008-04-11 12:58:43 +000028341 }
28342 /*
28343 * Augment the IDC definitions for the main schema and all imported ones
Daniel Veillard3888f472007-08-23 09:29:03 +000028344 * NOTE: main schema if the first in the imported list
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028345 */
Nick Wellnhofere03f0a12017-11-09 16:42:47 +010028346 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28347 vctxt);
Daniel Veillarddee23482008-04-11 12:58:43 +000028348
Daniel Veillardf10ae122005-07-10 19:03:16 +000028349 return(0);
28350}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028351
Daniel Veillardf10ae122005-07-10 19:03:16 +000028352static void
28353xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028354 if (vctxt->xsiAssemble) {
28355 if (vctxt->schema != NULL) {
28356 xmlSchemaFree(vctxt->schema);
28357 vctxt->schema = NULL;
28358 }
28359 }
28360 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028361}
28362
28363static int
28364xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28365{
28366 int ret = 0;
28367
28368 if (xmlSchemaPreRun(vctxt) < 0)
28369 return(-1);
28370
28371 if (vctxt->doc != NULL) {
28372 /*
28373 * Tree validation.
28374 */
28375 ret = xmlSchemaVDocWalk(vctxt);
28376#ifdef LIBXML_READER_ENABLED
28377 } else if (vctxt->reader != NULL) {
28378 /*
28379 * XML Reader validation.
28380 */
28381#ifdef XML_SCHEMA_READER_ENABLED
28382 ret = xmlSchemaVReaderWalk(vctxt);
28383#endif
28384#endif
28385 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28386 /*
28387 * SAX validation.
28388 */
28389 ret = xmlParseDocument(vctxt->parserCtxt);
28390 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028391 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000028392 "no instance to validate");
28393 ret = -1;
28394 }
28395
28396 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028397 if (ret == 0)
28398 ret = vctxt->err;
28399 return (ret);
28400}
28401
28402/**
28403 * xmlSchemaValidateOneElement:
28404 * @ctxt: a schema validation context
28405 * @elem: an element node
28406 *
28407 * Validate a branch of a tree, starting with the given @elem.
28408 *
28409 * Returns 0 if the element and its subtree is valid, a positive error
28410 * code number otherwise and -1 in case of an internal or API error.
28411 */
28412int
28413xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28414{
28415 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28416 return (-1);
28417
28418 if (ctxt->schema == NULL)
28419 return (-1);
28420
28421 ctxt->doc = elem->doc;
28422 ctxt->node = elem;
28423 ctxt->validationRoot = elem;
28424 return(xmlSchemaVStart(ctxt));
28425}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000028426
Daniel Veillard259f0df2004-08-18 09:13:18 +000028427/**
Daniel Veillard4255d502002-04-16 15:50:10 +000028428 * xmlSchemaValidateDoc:
28429 * @ctxt: a schema validation context
28430 * @doc: a parsed document tree
28431 *
28432 * Validate a document tree in memory.
28433 *
28434 * Returns 0 if the document is schemas valid, a positive error code
28435 * number otherwise and -1 in case of internal or API error.
28436 */
28437int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028438xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28439{
Daniel Veillard4255d502002-04-16 15:50:10 +000028440 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000028441 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000028442
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028443 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028444 ctxt->node = xmlDocGetRootElement(doc);
28445 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000028446 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028447 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28448 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028449 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028450 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028451 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000028452 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000028453 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000028454}
28455
Daniel Veillardcdc82732005-07-08 15:04:06 +000028456
28457/************************************************************************
Daniel Veillardf8e3db02012-09-11 13:26:36 +080028458 * *
28459 * Function and data for SAX streaming API *
28460 * *
Daniel Veillardcdc82732005-07-08 15:04:06 +000028461 ************************************************************************/
28462typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28463typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28464
28465struct _xmlSchemaSplitSAXData {
28466 xmlSAXHandlerPtr user_sax;
28467 void *user_data;
28468 xmlSchemaValidCtxtPtr ctxt;
28469 xmlSAXHandlerPtr schemas_sax;
28470};
28471
Daniel Veillard971771e2005-07-09 17:32:57 +000028472#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28473
28474struct _xmlSchemaSAXPlug {
28475 unsigned int magic;
28476
Haibo Huangcfd91dc2020-07-30 23:01:33 -070028477 /* the original callbacks information */
Daniel Veillard971771e2005-07-09 17:32:57 +000028478 xmlSAXHandlerPtr *user_sax_ptr;
28479 xmlSAXHandlerPtr user_sax;
28480 void **user_data_ptr;
28481 void *user_data;
28482
Haibo Huangcfd91dc2020-07-30 23:01:33 -070028483 /* the block plugged back and validation information */
Daniel Veillard971771e2005-07-09 17:32:57 +000028484 xmlSAXHandler schemas_sax;
28485 xmlSchemaValidCtxtPtr ctxt;
28486};
28487
Daniel Veillardcdc82732005-07-08 15:04:06 +000028488/* All those functions just bounces to the user provided SAX handlers */
28489static void
28490internalSubsetSplit(void *ctx, const xmlChar *name,
28491 const xmlChar *ExternalID, const xmlChar *SystemID)
28492{
Daniel Veillard971771e2005-07-09 17:32:57 +000028493 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028494 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28495 (ctxt->user_sax->internalSubset != NULL))
28496 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28497 SystemID);
28498}
28499
28500static int
28501isStandaloneSplit(void *ctx)
28502{
Daniel Veillard971771e2005-07-09 17:32:57 +000028503 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028504 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28505 (ctxt->user_sax->isStandalone != NULL))
28506 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28507 return(0);
28508}
28509
28510static int
28511hasInternalSubsetSplit(void *ctx)
28512{
Daniel Veillard971771e2005-07-09 17:32:57 +000028513 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028514 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28515 (ctxt->user_sax->hasInternalSubset != NULL))
28516 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28517 return(0);
28518}
28519
28520static int
28521hasExternalSubsetSplit(void *ctx)
28522{
Daniel Veillard971771e2005-07-09 17:32:57 +000028523 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028524 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28525 (ctxt->user_sax->hasExternalSubset != NULL))
28526 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28527 return(0);
28528}
28529
28530static void
28531externalSubsetSplit(void *ctx, const xmlChar *name,
28532 const xmlChar *ExternalID, const xmlChar *SystemID)
28533{
Daniel Veillard971771e2005-07-09 17:32:57 +000028534 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028535 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
Daniel Veillardb3e45362008-03-26 13:39:31 +000028536 (ctxt->user_sax->externalSubset != NULL))
28537 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028538 SystemID);
28539}
28540
28541static xmlParserInputPtr
28542resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28543{
Daniel Veillard971771e2005-07-09 17:32:57 +000028544 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028545 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28546 (ctxt->user_sax->resolveEntity != NULL))
28547 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28548 systemId));
28549 return(NULL);
28550}
28551
28552static xmlEntityPtr
28553getEntitySplit(void *ctx, const xmlChar *name)
28554{
Daniel Veillard971771e2005-07-09 17:32:57 +000028555 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028556 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28557 (ctxt->user_sax->getEntity != NULL))
28558 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28559 return(NULL);
28560}
28561
28562static xmlEntityPtr
28563getParameterEntitySplit(void *ctx, const xmlChar *name)
28564{
Daniel Veillard971771e2005-07-09 17:32:57 +000028565 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028566 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28567 (ctxt->user_sax->getParameterEntity != NULL))
28568 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28569 return(NULL);
28570}
28571
28572
28573static void
28574entityDeclSplit(void *ctx, const xmlChar *name, int type,
28575 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28576{
Daniel Veillard971771e2005-07-09 17:32:57 +000028577 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028578 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28579 (ctxt->user_sax->entityDecl != NULL))
28580 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28581 systemId, content);
28582}
28583
28584static void
28585attributeDeclSplit(void *ctx, const xmlChar * elem,
28586 const xmlChar * name, int type, int def,
28587 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28588{
Daniel Veillard971771e2005-07-09 17:32:57 +000028589 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028590 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28591 (ctxt->user_sax->attributeDecl != NULL)) {
28592 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28593 def, defaultValue, tree);
28594 } else {
28595 xmlFreeEnumeration(tree);
28596 }
28597}
28598
28599static void
28600elementDeclSplit(void *ctx, const xmlChar *name, int type,
28601 xmlElementContentPtr content)
28602{
Daniel Veillard971771e2005-07-09 17:32:57 +000028603 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028604 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28605 (ctxt->user_sax->elementDecl != NULL))
28606 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28607}
28608
28609static void
28610notationDeclSplit(void *ctx, const xmlChar *name,
28611 const xmlChar *publicId, const xmlChar *systemId)
28612{
Daniel Veillard971771e2005-07-09 17:32:57 +000028613 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028614 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28615 (ctxt->user_sax->notationDecl != NULL))
28616 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28617 systemId);
28618}
28619
28620static void
28621unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28622 const xmlChar *publicId, const xmlChar *systemId,
28623 const xmlChar *notationName)
28624{
Daniel Veillard971771e2005-07-09 17:32:57 +000028625 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028626 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28627 (ctxt->user_sax->unparsedEntityDecl != NULL))
28628 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28629 systemId, notationName);
28630}
28631
28632static void
28633setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28634{
Daniel Veillard971771e2005-07-09 17:32:57 +000028635 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028636 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28637 (ctxt->user_sax->setDocumentLocator != NULL))
28638 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28639}
28640
28641static void
28642startDocumentSplit(void *ctx)
28643{
Daniel Veillard971771e2005-07-09 17:32:57 +000028644 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028645 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28646 (ctxt->user_sax->startDocument != NULL))
28647 ctxt->user_sax->startDocument(ctxt->user_data);
28648}
28649
28650static void
28651endDocumentSplit(void *ctx)
28652{
Daniel Veillard971771e2005-07-09 17:32:57 +000028653 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028654 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28655 (ctxt->user_sax->endDocument != NULL))
28656 ctxt->user_sax->endDocument(ctxt->user_data);
28657}
28658
28659static void
28660processingInstructionSplit(void *ctx, const xmlChar *target,
28661 const xmlChar *data)
28662{
Daniel Veillard971771e2005-07-09 17:32:57 +000028663 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028664 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28665 (ctxt->user_sax->processingInstruction != NULL))
28666 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28667}
28668
28669static void
28670commentSplit(void *ctx, const xmlChar *value)
28671{
Daniel Veillard971771e2005-07-09 17:32:57 +000028672 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028673 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28674 (ctxt->user_sax->comment != NULL))
28675 ctxt->user_sax->comment(ctxt->user_data, value);
28676}
28677
28678/*
28679 * Varargs error callbacks to the user application, harder ...
28680 */
28681
Daniel Veillardffa3c742005-07-21 13:24:09 +000028682static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028683warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028684 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028685 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28686 (ctxt->user_sax->warning != NULL)) {
28687 TODO
28688 }
28689}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028690static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028691errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028692 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028693 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28694 (ctxt->user_sax->error != NULL)) {
28695 TODO
28696 }
28697}
Daniel Veillardffa3c742005-07-21 13:24:09 +000028698static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000028699fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028700 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028701 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28702 (ctxt->user_sax->fatalError != NULL)) {
28703 TODO
28704 }
28705}
28706
28707/*
28708 * Those are function where both the user handler and the schemas handler
28709 * need to be called.
28710 */
28711static void
28712charactersSplit(void *ctx, const xmlChar *ch, int len)
28713{
Daniel Veillard971771e2005-07-09 17:32:57 +000028714 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028715 if (ctxt == NULL)
28716 return;
28717 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28718 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28719 if (ctxt->ctxt != NULL)
28720 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28721}
28722
28723static void
28724ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28725{
Daniel Veillard971771e2005-07-09 17:32:57 +000028726 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028727 if (ctxt == NULL)
28728 return;
28729 if ((ctxt->user_sax != NULL) &&
28730 (ctxt->user_sax->ignorableWhitespace != NULL))
28731 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28732 if (ctxt->ctxt != NULL)
28733 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28734}
28735
28736static void
28737cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28738{
Daniel Veillard971771e2005-07-09 17:32:57 +000028739 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028740 if (ctxt == NULL)
28741 return;
28742 if ((ctxt->user_sax != NULL) &&
Daniel Veillard7d0ca5e2008-02-05 08:43:52 +000028743 (ctxt->user_sax->cdataBlock != NULL))
28744 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
Daniel Veillardcdc82732005-07-08 15:04:06 +000028745 if (ctxt->ctxt != NULL)
28746 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28747}
28748
28749static void
28750referenceSplit(void *ctx, const xmlChar *name)
28751{
Daniel Veillard971771e2005-07-09 17:32:57 +000028752 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillard14b56432006-03-09 18:41:40 +000028753 if (ctxt == NULL)
28754 return;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028755 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28756 (ctxt->user_sax->reference != NULL))
28757 ctxt->user_sax->reference(ctxt->user_data, name);
28758 if (ctxt->ctxt != NULL)
28759 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28760}
28761
28762static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028763startElementNsSplit(void *ctx, const xmlChar * localname,
28764 const xmlChar * prefix, const xmlChar * URI,
28765 int nb_namespaces, const xmlChar ** namespaces,
28766 int nb_attributes, int nb_defaulted,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028767 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028768 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028769 if (ctxt == NULL)
28770 return;
28771 if ((ctxt->user_sax != NULL) &&
28772 (ctxt->user_sax->startElementNs != NULL))
28773 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28774 URI, nb_namespaces, namespaces,
28775 nb_attributes, nb_defaulted,
28776 attributes);
28777 if (ctxt->ctxt != NULL)
28778 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28779 URI, nb_namespaces, namespaces,
28780 nb_attributes, nb_defaulted,
28781 attributes);
28782}
28783
28784static void
Daniel Veillarddee23482008-04-11 12:58:43 +000028785endElementNsSplit(void *ctx, const xmlChar * localname,
Daniel Veillardcdc82732005-07-08 15:04:06 +000028786 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028787 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000028788 if (ctxt == NULL)
28789 return;
28790 if ((ctxt->user_sax != NULL) &&
28791 (ctxt->user_sax->endElementNs != NULL))
28792 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28793 if (ctxt->ctxt != NULL)
28794 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28795}
28796
Daniel Veillard4255d502002-04-16 15:50:10 +000028797/**
Daniel Veillard971771e2005-07-09 17:32:57 +000028798 * xmlSchemaSAXPlug:
28799 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000028800 * @sax: a pointer to the original xmlSAXHandlerPtr
28801 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000028802 *
28803 * Plug a SAX based validation layer in a SAX parsing event flow.
28804 * The original @saxptr and @dataptr data are replaced by new pointers
28805 * but the calls to the original will be maintained.
28806 *
28807 * Returns a pointer to a data structure needed to unplug the validation layer
28808 * or NULL in case of errors.
28809 */
28810xmlSchemaSAXPlugPtr
28811xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28812 xmlSAXHandlerPtr *sax, void **user_data)
28813{
28814 xmlSchemaSAXPlugPtr ret;
28815 xmlSAXHandlerPtr old_sax;
28816
28817 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28818 return(NULL);
28819
28820 /*
28821 * We only allow to plug into SAX2 event streams
28822 */
28823 old_sax = *sax;
28824 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28825 return(NULL);
Daniel Veillarddee23482008-04-11 12:58:43 +000028826 if ((old_sax != NULL) &&
Daniel Veillard971771e2005-07-09 17:32:57 +000028827 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28828 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28829 return(NULL);
28830
28831 /*
28832 * everything seems right allocate the local data needed for that layer
28833 */
28834 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28835 if (ret == NULL) {
28836 return(NULL);
28837 }
28838 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28839 ret->magic = XML_SAX_PLUG_MAGIC;
28840 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28841 ret->ctxt = ctxt;
28842 ret->user_sax_ptr = sax;
28843 ret->user_sax = old_sax;
Daniel Veillarddee23482008-04-11 12:58:43 +000028844 if (old_sax == NULL) {
Daniel Veillard971771e2005-07-09 17:32:57 +000028845 /*
28846 * go direct, no need for the split block and functions.
28847 */
28848 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28849 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28850 /*
28851 * Note that we use the same text-function for both, to prevent
28852 * the parser from testing for ignorable whitespace.
28853 */
28854 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28855 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28856
28857 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28858 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28859
28860 ret->user_data = ctxt;
28861 *user_data = ctxt;
28862 } else {
28863 /*
28864 * for each callback unused by Schemas initialize it to the Split
Daniel Veillarddee23482008-04-11 12:58:43 +000028865 * routine only if non NULL in the user block, this can speed up
Daniel Veillard971771e2005-07-09 17:32:57 +000028866 * things at the SAX level.
28867 */
28868 if (old_sax->internalSubset != NULL)
28869 ret->schemas_sax.internalSubset = internalSubsetSplit;
28870 if (old_sax->isStandalone != NULL)
28871 ret->schemas_sax.isStandalone = isStandaloneSplit;
28872 if (old_sax->hasInternalSubset != NULL)
28873 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28874 if (old_sax->hasExternalSubset != NULL)
28875 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28876 if (old_sax->resolveEntity != NULL)
28877 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28878 if (old_sax->getEntity != NULL)
28879 ret->schemas_sax.getEntity = getEntitySplit;
28880 if (old_sax->entityDecl != NULL)
28881 ret->schemas_sax.entityDecl = entityDeclSplit;
28882 if (old_sax->notationDecl != NULL)
28883 ret->schemas_sax.notationDecl = notationDeclSplit;
28884 if (old_sax->attributeDecl != NULL)
28885 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28886 if (old_sax->elementDecl != NULL)
28887 ret->schemas_sax.elementDecl = elementDeclSplit;
28888 if (old_sax->unparsedEntityDecl != NULL)
28889 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28890 if (old_sax->setDocumentLocator != NULL)
28891 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28892 if (old_sax->startDocument != NULL)
28893 ret->schemas_sax.startDocument = startDocumentSplit;
28894 if (old_sax->endDocument != NULL)
28895 ret->schemas_sax.endDocument = endDocumentSplit;
28896 if (old_sax->processingInstruction != NULL)
28897 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28898 if (old_sax->comment != NULL)
28899 ret->schemas_sax.comment = commentSplit;
28900 if (old_sax->warning != NULL)
28901 ret->schemas_sax.warning = warningSplit;
28902 if (old_sax->error != NULL)
28903 ret->schemas_sax.error = errorSplit;
28904 if (old_sax->fatalError != NULL)
28905 ret->schemas_sax.fatalError = fatalErrorSplit;
28906 if (old_sax->getParameterEntity != NULL)
28907 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28908 if (old_sax->externalSubset != NULL)
28909 ret->schemas_sax.externalSubset = externalSubsetSplit;
28910
28911 /*
28912 * the 6 schemas callback have to go to the splitter functions
28913 * Note that we use the same text-function for ignorableWhitespace
28914 * if possible, to prevent the parser from testing for ignorable
28915 * whitespace.
28916 */
28917 ret->schemas_sax.characters = charactersSplit;
28918 if ((old_sax->ignorableWhitespace != NULL) &&
28919 (old_sax->ignorableWhitespace != old_sax->characters))
28920 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28921 else
28922 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28923 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28924 ret->schemas_sax.reference = referenceSplit;
28925 ret->schemas_sax.startElementNs = startElementNsSplit;
28926 ret->schemas_sax.endElementNs = endElementNsSplit;
28927
28928 ret->user_data_ptr = user_data;
28929 ret->user_data = *user_data;
28930 *user_data = ret;
28931 }
28932
28933 /*
28934 * plug the pointers back.
28935 */
28936 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000028937 ctxt->sax = *sax;
28938 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28939 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028940 return(ret);
28941}
28942
28943/**
28944 * xmlSchemaSAXUnplug:
28945 * @plug: a data structure returned by xmlSchemaSAXPlug
28946 *
28947 * Unplug a SAX based validation layer in a SAX parsing event flow.
28948 * The original pointers used in the call are restored.
28949 *
28950 * Returns 0 in case of success and -1 in case of failure.
28951 */
28952int
28953xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28954{
28955 xmlSAXHandlerPtr *sax;
28956 void **user_data;
28957
28958 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28959 return(-1);
28960 plug->magic = 0;
28961
Daniel Veillardf10ae122005-07-10 19:03:16 +000028962 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000028963 /* restore the data */
28964 sax = plug->user_sax_ptr;
28965 *sax = plug->user_sax;
28966 if (plug->user_sax != NULL) {
28967 user_data = plug->user_data_ptr;
28968 *user_data = plug->user_data;
28969 }
28970
28971 /* free and return */
28972 xmlFree(plug);
28973 return(0);
28974}
28975
28976/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +080028977 * xmlSchemaValidateSetLocator:
28978 * @vctxt: a schema validation context
28979 * @f: the locator function pointer
28980 * @ctxt: the locator context
28981 *
28982 * Allows to set a locator function to the validation context,
28983 * which will be used to provide file and line information since
28984 * those are not provided as part of the SAX validation flow
28985 * Setting @f to NULL disable the locator.
28986 */
28987
28988void
28989xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28990 xmlSchemaValidityLocatorFunc f,
28991 void *ctxt)
28992{
28993 if (vctxt == NULL) return;
28994 vctxt->locFunc = f;
28995 vctxt->locCtxt = ctxt;
28996}
28997
28998/**
28999 * xmlSchemaValidateStreamLocator:
29000 * @ctx: the xmlTextReaderPtr used
29001 * @file: returned file information
29002 * @line: returned line information
29003 *
29004 * Internal locator function for the readers
29005 *
Haibo Huangcfd91dc2020-07-30 23:01:33 -070029006 * Returns 0 in case the Schema validation could be (de)activated and
Daniel Veillard97fa5b32012-08-14 11:01:07 +080029007 * -1 in case of error.
29008 */
29009static int
29010xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29011 unsigned long *line) {
29012 xmlParserCtxtPtr ctxt;
29013
29014 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29015 return(-1);
29016
29017 if (file != NULL)
29018 *file = NULL;
29019 if (line != NULL)
29020 *line = 0;
29021
29022 ctxt = (xmlParserCtxtPtr) ctx;
29023 if (ctxt->input != NULL) {
29024 if (file != NULL)
29025 *file = ctxt->input->filename;
29026 if (line != NULL)
29027 *line = ctxt->input->line;
29028 return(0);
29029 }
29030 return(-1);
29031}
29032
29033/**
Daniel Veillard4255d502002-04-16 15:50:10 +000029034 * xmlSchemaValidateStream:
29035 * @ctxt: a schema validation context
29036 * @input: the input to use for reading the data
29037 * @enc: an optional encoding information
29038 * @sax: a SAX handler for the resulting events
29039 * @user_data: the context to provide to the SAX handler.
29040 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000029041 * Validate an input based on a flow of SAX event from the parser
29042 * and forward the events to the @sax handler with the provided @user_data
29043 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000029044 *
29045 * Returns 0 if the document is schemas valid, a positive error code
29046 * number otherwise and -1 in case of internal or API error.
29047 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029048int
Daniel Veillard4255d502002-04-16 15:50:10 +000029049xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029050 xmlParserInputBufferPtr input, xmlCharEncoding enc,
29051 xmlSAXHandlerPtr sax, void *user_data)
29052{
Daniel Veillard971771e2005-07-09 17:32:57 +000029053 xmlSchemaSAXPlugPtr plug = NULL;
29054 xmlSAXHandlerPtr old_sax = NULL;
29055 xmlParserCtxtPtr pctxt = NULL;
29056 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000029057 int ret;
29058
Daniel Veillard4255d502002-04-16 15:50:10 +000029059 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000029060 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000029061
Daniel Veillardcdc82732005-07-08 15:04:06 +000029062 /*
29063 * prepare the parser
29064 */
29065 pctxt = xmlNewParserCtxt();
29066 if (pctxt == NULL)
29067 return (-1);
29068 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000029069 pctxt->sax = sax;
29070 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000029071#if 0
29072 if (options)
29073 xmlCtxtUseOptions(pctxt, options);
29074#endif
Daniel Veillarddee23482008-04-11 12:58:43 +000029075 pctxt->linenumbers = 1;
Daniel Veillard97fa5b32012-08-14 11:01:07 +080029076 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
Daniel Veillardcdc82732005-07-08 15:04:06 +000029077
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000029078 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000029079 if (inputStream == NULL) {
29080 ret = -1;
29081 goto done;
29082 }
29083 inputPush(pctxt, inputStream);
29084 ctxt->parserCtxt = pctxt;
29085 ctxt->input = input;
29086
29087 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000029088 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000029089 */
Daniel Veillard971771e2005-07-09 17:32:57 +000029090 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29091 if (plug == NULL) {
29092 ret = -1;
29093 goto done;
29094 }
29095 ctxt->input = input;
29096 ctxt->enc = enc;
29097 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000029098 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29099 ret = xmlSchemaVStart(ctxt);
29100
29101 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29102 ret = ctxt->parserCtxt->errNo;
29103 if (ret == 0)
29104 ret = 1;
Daniel Veillard33fe2882008-04-10 08:09:25 +000029105 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000029106
29107done:
Daniel Veillard971771e2005-07-09 17:32:57 +000029108 ctxt->parserCtxt = NULL;
29109 ctxt->sax = NULL;
29110 ctxt->input = NULL;
29111 if (plug != NULL) {
29112 xmlSchemaSAXUnplug(plug);
29113 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000029114 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000029115 if (pctxt != NULL) {
29116 pctxt->sax = old_sax;
29117 xmlFreeParserCtxt(pctxt);
29118 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000029119 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000029120}
29121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029122/**
29123 * xmlSchemaValidateFile:
29124 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000029125 * @filename: the URI of the instance
29126 * @options: a future set of options, currently unused
29127 *
29128 * Do a schemas validation of the given resource, it will use the
29129 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029130 *
29131 * Returns 0 if the document is valid, a positive error code
29132 * number otherwise and -1 in case of an internal or API error.
29133 */
29134int
29135xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000029136 const char * filename,
29137 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029138{
29139 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000029140 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029141
29142 if ((ctxt == NULL) || (filename == NULL))
29143 return (-1);
Daniel Veillarddee23482008-04-11 12:58:43 +000029144
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000029145 input = xmlParserInputBufferCreateFilename(filename,
29146 XML_CHAR_ENCODING_NONE);
29147 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029148 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000029149 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
Daniel Veillarddee23482008-04-11 12:58:43 +000029150 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029151 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000029152}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000029153
Daniel Veillarddee23482008-04-11 12:58:43 +000029154/**
29155 * xmlSchemaValidCtxtGetParserCtxt:
29156 * @ctxt: a schema validation context
29157 *
29158 * allow access to the parser context of the schema validation context
29159 *
29160 * Returns the parser context of the schema validation context or NULL
29161 * in case of error.
29162 */
29163xmlParserCtxtPtr
29164xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29165{
29166 if (ctxt == NULL)
29167 return(NULL);
29168 return (ctxt->parserCtxt);
29169}
29170
Daniel Veillard5d4644e2005-04-01 13:11:58 +000029171#define bottom_xmlschemas
29172#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000029173#endif /* LIBXML_SCHEMAS_ENABLED */